]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2-20050119
authorWietse Venema <wietse@porcupine.org>
Wed, 19 Jan 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:30:26 +0000 (06:30 +0000)
92 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/Makefile.in
postfix/README_FILES/AAAREADME
postfix/README_FILES/ADDRESS_REWRITING_README
postfix/README_FILES/INSTALL
postfix/README_FILES/TLS_README [new file with mode: 0644]
postfix/RELEASE_NOTES
postfix/TLS_LICENSE [new file with mode: 0644]
postfix/conf/TLS_LICENSE [new symlink]
postfix/conf/master.cf
postfix/conf/post-install
postfix/conf/postfix-files
postfix/html/ADDRESS_REWRITING_README.html
postfix/html/INSTALL.html
postfix/html/Makefile.in
postfix/html/TLS_README.html [new file with mode: 0644]
postfix/html/index.html
postfix/html/postconf.5.html
postfix/html/postfix-manuals.html
postfix/html/postfix.1.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/html/tlsmgr.8.html [new file with mode: 0644]
postfix/makedefs
postfix/man/Makefile.in
postfix/man/man1/postfix.1
postfix/man/man5/postconf.5
postfix/man/man8/master.8
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/man/man8/tlsmgr.8 [new file with mode: 0644]
postfix/mantools/postlink
postfix/mantools/xpostdef
postfix/proto/ADDRESS_REWRITING_README.html
postfix/proto/INSTALL.html
postfix/proto/Makefile.in
postfix/proto/TLS_README.html [new file with mode: 0644]
postfix/proto/postconf.proto
postfix/proto/stop
postfix/src/global/Makefile.in
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/global/own_inet_addr.c
postfix/src/master/master.c
postfix/src/postfix/postfix.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_sasl_proto.c
postfix/src/smtpd/smtpd_state.c
postfix/src/tls/.indent.pro [new symlink]
postfix/src/tls/Makefile.in [new file with mode: 0644]
postfix/src/tls/TLS_ACKNOWLEDGEMENTS [new file with mode: 0644]
postfix/src/tls/TLS_CHANGES [new file with mode: 0644]
postfix/src/tls/TLS_TODO [new file with mode: 0644]
postfix/src/tls/tls.h [new file with mode: 0644]
postfix/src/tls/tls_bio_ops.c [new file with mode: 0644]
postfix/src/tls/tls_certkey.c [new file with mode: 0644]
postfix/src/tls/tls_client.c [new file with mode: 0644]
postfix/src/tls/tls_dh.c [new file with mode: 0644]
postfix/src/tls/tls_mgr.c [new file with mode: 0644]
postfix/src/tls/tls_mgr.h [new file with mode: 0644]
postfix/src/tls/tls_misc.c [new file with mode: 0644]
postfix/src/tls/tls_prng.h [new file with mode: 0644]
postfix/src/tls/tls_prng_dev.c [new file with mode: 0644]
postfix/src/tls/tls_prng_egd.c [new file with mode: 0644]
postfix/src/tls/tls_prng_exch.c [new file with mode: 0644]
postfix/src/tls/tls_prng_file.c [new file with mode: 0644]
postfix/src/tls/tls_rsa.c [new file with mode: 0644]
postfix/src/tls/tls_scache.c [new file with mode: 0644]
postfix/src/tls/tls_scache.h [new file with mode: 0644]
postfix/src/tls/tls_seed.c [new file with mode: 0644]
postfix/src/tls/tls_server.c [new file with mode: 0644]
postfix/src/tls/tls_session.c [new file with mode: 0644]
postfix/src/tls/tls_stream.c [new file with mode: 0644]
postfix/src/tls/tls_temp.c [new file with mode: 0644]
postfix/src/tls/tls_verify.c [new file with mode: 0644]
postfix/src/tlsmgr/.indent.pro [new symlink]
postfix/src/tlsmgr/Makefile.in [new file with mode: 0644]
postfix/src/tlsmgr/tlsmgr.c [new file with mode: 0644]
postfix/src/util/sys_defs.h
postfix/src/util/valid_hostname.c
postfix/src/verify/Makefile.in

index a6844755a88d39048583f86a4193bd7015eb4647..7b958be895021bff51e63cc2e2729fd2ac51178d 100644 (file)
@@ -13,6 +13,7 @@
 -TBINATTR_INFO
 -TBINHASH
 -TBINHASH_INFO
+-TBIO
 -TBOUNCE_INFO
 -TBOUNCE_LOG
 -TBOUNCE_STAT
@@ -29,6 +30,7 @@
 -TCONFIG_STR_TABLE
 -TCONFIG_TIME_FN_TABLE
 -TCONFIG_TIME_TABLE
+-TCRYPTO_EX_DATA
 -TCTABLE
 -TCTABLE_ENTRY
 -TDELIVER_ATTR
 -TSMTP_RESP
 -TSMTP_SESSION
 -TSMTP_STATE
+-TSMTP_TLS_SITE_POLICY
 -TSM_STATE
 -TSOCKADDR_SIZE
 -TSPAWN_ATTR
+-TSSL
+-TSSL_CTX
+-TSSL_SESSION
 -TSTRING_LIST
 -TSTRING_TABLE
 -TSYS_EXITS_TABLE
+-TTLS_PRNG_SEED_INFO
+-TTLS_PRNG_SRC
+-TTLS_SCACHE
+-TTLS_SCACHE_ENTRY
+-TTLScontext_t
 -TTOK822
 -TTRANSPORT_INFO
 -TTRIGGER_SERVER
 -TWAIT_STATUS_T
 -TWATCHDOG
 -TWATCH_FD
+-TX509_STORE_CTX
 -Tregex_t
 -Tregmatch_t
 -Tsasl_conn_t
 -Tsasl_secret_t
+-Ttls_info_t
index 4fa3e13fdb2a4559b19a27f69d32ba8ab142d3a3..b7036e2d622ed2b02b6ad5bb1d374a7fe7718b75 100644 (file)
@@ -9663,7 +9663,7 @@ Apologies for any names omitted.
        Portability: avoid postmap/postalias test file name clashes
        on Windows.  Ian Lance Taylor (of Taylor UUCP fame).
 
-20030823
+20040823
 
        Bugfix: vstream_popen() did not close the child pipe
        after failure to fork(). File: util/vstream_popen.c.
@@ -9815,6 +9815,12 @@ Apologies for any names omitted.
        Robustness: extra sanity checks. Files: util/dict_db.c,
        util/dict_dbm.c, dict_nis.c.
 
+20041025
+
+       Initial merge of Lutz Jaenicke's TLS patch. Initial rewrite
+       of tlsmgr to eliminate some code duplication and to postpone
+       calls into OpenSSL until after dropping privileges.
+
 20041030
 
        Compatibility: "session cache" renamed to "connection cache"
@@ -9877,12 +9883,36 @@ Apologies for any names omitted.
        Victor Duchovni for Solaris 2.5.1, but we play safe and
        enable it unconditionally.
 
+20041120
+
+       The TLS support routines are moved to a "tls" directory,
+       and are published via the "libtls.a" object library.
+
 20041122
 
        Infrastructure: support for binary attribute values
        (ATTR_TYPE_DATA) in Postfix IPC messages. Files:
        util/attr_scan*c, util/attr_print*c.
 
+20041123-20041205
+
+       TLS support: via a process of gradual transformation,
+       decomposed Lutz Jaenicke's pfixtls.c into separate modules
+       for clients, servers, certificate verification, session
+       caching, and PRNG management. Global variables were eliminated
+       so that the code now supports multiple client and/or server
+       contexts in the same process.  Files:  tls/*.[hc].
+
+20041205
+
+       TLS support: eliminated shared access (and locking) of the
+       TLS PRNG exchange file and TLS session caches. Instead,
+       Postfix uses a client-server protocol, and the tlsmgr
+       becomes the sole mediator. This eliminated the need for
+       1000+ lines of SDBM support, and eliminated the need for
+       running a persistent tlsmgr process on systems don't enable
+       TLS in main.cf.
+
 20041124
 
        Feature: configurable list of forbidden SMTP commands
@@ -9911,22 +9941,15 @@ Apologies for any names omitted.
        sequence operator support: hash, btree, dbm, and sdbm.
        Files:  postmap/postmap.c, postalias/postalias.c.
 
-20041210
-
-       Back-ports of minor cosmetic changes in comments, in order
-       to keep differences minimal with respect to the TLS-enabled
-       version.
-
-       Client SDBM module, from the TLS-enabled version. Files:
-       util/dict_sdbm.[hc].
-
-       Hexadecimal encode/decode routines, from the TLS-enabled
-       version. Files:  util/hext_code.[hc].
-
 20041212
 
        Solaris 10/ix86 chroot setup script update by J.D. Bronson.
 
+       TLS support: cosmetic changes to comments and messages;
+       completed the code for the master -> tlsmgr trigger handshake,
+       so that the master no longer complains about trigger
+       responses timing out.
+
 20041213
 
        Updated the SDBM dictionary interface. It had fallen behind
@@ -9968,6 +9991,12 @@ Apologies for any names omitted.
        "postcat -o" now prints queue file record offsets; this is
        useful for debugging. File: postcat/postcat.c.
 
+       NON-PRODUCTION Bugfix: (bug introduced while adopting the
+       Postfix/TLS patch):  the new TLS certification call-back
+       routine expects that the peer hostname is in
+       tlscontext->peername_save, but the TLS server code never
+       updated this field.  File:  tls/tls_server.c.
+
 20041218
 
        Feature: selective suppression of SMTP extensions (pipelining,
@@ -9986,13 +10015,33 @@ Apologies for any names omitted.
 
 20041220
 
+       NON-PRODUCTION Bugfix: (bug introduced while adopting
+       Postfix/TLS patch):  don't call smtp_flush() after return
+       from vstream_setjmp(), we'll call you.  File: smtpd/smtpd.c.
+
        Dummy VSTREAM read-write routines. Files: util/dummy_read.c,
        util/dummy_write.c.
 
+20041221
+
+       Fixes for TLS_README by Victor Duchovni. File:
+       proto/TLS_README.html.
+
+       NON-PRODUCTION Bugfix: (bug introduced while adopting
+       Postfix/TLS patch).  The client code had become too similar
+       to the server implementation, and also required a host
+       certificate and key. Fix by Victor Duchovni. File:
+       tls/tls_client.c.
+
 20041221
 
        Bugfix: further postcat corner cases.
 
+20041223
+
+       Cosmetic: don't log disconnect events as I/O errors.
+       File: tls/tls_bio_ops.c.
+
 20041221-9
 
        Infrastructure: unified IPv4/IPv6 name/address API so that
@@ -10096,9 +10145,7 @@ Apologies for any names omitted.
        of the new internal APIs.
 
        Performance: reduced start-up delay by moving warning-only
-       startup checks into the background; they now start after
-       one minute to allow the system to finish booting. File:
-       conf/postfix-script.
+       startup checks into the background. File: conf/postfix-script.
 
 20050115
 
@@ -10135,8 +10182,17 @@ Apologies for any names omitted.
 
 20050117
 
+       Performance: reduced start-up delay by moving warning-only
+       startup checks into the background; they now start after
+       one minute to allow the system to finish booting. File:
+       conf/postfix-script.
+
        Milestone: first non-non-production snapshot with IPv6.
 
+20050119
+
+       Milestone: first non-non-production snapshot with TLS.
+
 Open problems:
 
        Med: transform IPv4-in-IPv6 address literals to IPv4 form
@@ -10165,6 +10221,13 @@ Open problems:
        Low: cap bounce queue life time with regular queue life
        time.
 
+       Med: the TLS certificate verification depth parameters
+       never worked.
+
+       Med: eliminate the tls_info data structure.
+
+       Low: something to alias sdbm:name into btree:name?
+
        Med: implement ${name[?:]value} in main.cf or update the
        postconf(5) manual.
 
index e2a77297637c60fd215d21278edb4da636522f90..daab257977067328841ecef457040cf3f6ddd200 100644 (file)
@@ -1,13 +1,13 @@
 SHELL  = /bin/sh
 WARN    = -Wmissing-prototypes -Wformat
 OPTS   = 'CC=$(CC)'
-DIRS   = src/util src/global src/dns src/master src/postfix src/smtpstone \
+DIRS   = src/util src/global src/dns src/tls src/master src/postfix src/smtpstone \
        src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
        src/lmtp src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \
        src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
        src/postkick src/postlock src/postlog src/postmap src/postqueue \
        src/postsuper src/qmqpd src/spawn src/flush src/verify \
-       src/virtual src/proxymap src/anvil src/scache src/discard
+       src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr
 MANDIRS        = proto man html
 
 default: update
index c2d8e4263a30001d6283546969465dd3595e744c..9b2bf9ad692654ff0c1535ca0a231d60eeefb528 100644 (file)
@@ -8,6 +8,7 @@ G\bGe\ben\bne\ber\bra\bal\bl c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
   * ADDRESS_REWRITING_README: Address rewriting
   * VIRTUAL_README: Virtual domain hosting
   * SASL_README: SASL Authentication
+  * TLS_README: TLS Encryption and authentication
   * IPV6_README: IP Version 6 Support
   * INSTALL: Installation from source code
 
index f1497a327332e1399ce6a9d26ef9d68b72eeeeb5..3ed5247a8b48878843c8e8b20436b874f7eb51ea 100644 (file)
@@ -538,9 +538,9 @@ M\bMa\bai\bil\bl t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt s\bsw\bwi\bit\btc\bch\bh
 
 Once the trivial-rewrite(8) daemon has determined a default delivery method it
 searches the optional transport(5) table for information that overrides the
-message destination and/or delivery method. Typical use of the transport(5) is
-to send mail to a system that is not connected to the Internet, or to use a
-special SMTP client configuration for destinations that have special
+message destination and/or delivery method. Typical use of the transport(5)
+table is to send mail to a system that is not connected to the Internet, or to
+use a special SMTP client configuration for destinations that have special
 requirements. See, for example, the STANDARD_CONFIGURATION_README and
 UUCP_README documents, and the examples in the transport(5) manual page.
 
index 08df531cd4dba6943c42a564b22da7ad74db5d4e..1d959023c8b3c8537a5c1d0bdd43efd2498378d9 100644 (file)
@@ -168,10 +168,11 @@ support for extensions:
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |SASL authentication               |SASL_README |Postfix 1.0 |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |STARTTLS session encryption       |TLS_README  |Postfix 2.2 |
+    |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
 
-Note: support for TLS (encrypted SMTP sessions and certificate based
-authentication) and for IP version 6 is still separate from Postfix but is
-expected to be merged soon.
+Note: IP version 6 support is compiled into Postfix on operating systems that
+have IPv6 support. See the IPV6_README file for details.
 
 4\b4.\b.4\b4 -\b- O\bOv\bve\ber\brr\bri\bid\bdi\bin\bng\bg b\bbu\bui\bil\blt\bt-\b-i\bin\bn p\bpa\bar\bra\bam\bme\bet\bte\ber\br d\bde\bef\bfa\bau\bul\blt\bt s\bse\bet\btt\bti\bin\bng\bgs\bs
 
diff --git a/postfix/README_FILES/TLS_README b/postfix/README_FILES/TLS_README
new file mode 100644 (file)
index 0000000..832a5cd
--- /dev/null
@@ -0,0 +1,981 @@
+P\bPo\bos\bst\btf\bfi\bix\bx T\bTL\bLS\bS S\bSu\bup\bpp\bpo\bor\brt\bt
+
+-------------------------------------------------------------------------------
+
+W\bWA\bAR\bRN\bNI\bIN\bNG\bG
+
+By turning on TLS support in Postfix, you not only get the ability to encrypt
+mail and to authenticate clients or servers. You also turn on thousands and
+thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as
+carefully as Wietse's own code, every 1000 lines introduce one additional bug
+into Postfix.
+
+P\bPu\bur\brp\bpo\bos\bse\be o\bof\bf t\bth\bhi\bis\bs d\bdo\boc\bcu\bum\bme\ben\bnt\bt
+
+This document describes how to build Postfix with Transport Layer Security
+(TLS) support in the Postfix SMTP client and Postfix SMTP server, and how to
+configure the TLS manager daemon that maintains the Pseudo Random Number
+Generator (PRNG) pool and the TLS session cache information.
+
+Topics covered in this document:
+
+  * Building Postfix with TLS support
+  * SMTP Server specific settings
+  * SMTP Client specific settings
+  * TLS manager specific settings
+  * Reporting problems
+  * Compatibility with Postfix < 2.2 TLS support
+  * Credits
+
+And last but not least, for the impatient:
+
+  * Getting started, quick and dirty
+
+B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh T\bTL\bLS\bS s\bsu\bup\bpp\bpo\bor\brt\bt
+
+To build Postfix with TLS support, first we need to generate the make(1) files
+with the necessary definitions. This is done by invoking the command "make
+makefiles in the Postfix top-level directory and with arguments as shown next.
+
+  * If the OpenSSL include files (such as ssl.h) are in directory /usr/include/
+    openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are
+    in directory /usr/lib:
+
+        % m\bma\bak\bke\be t\bti\bid\bdy\by # if you have left-over files from a previous build
+        % m\bma\bak\bke\be m\bma\bak\bke\bef\bfi\bil\ble\bes\bs C\bCC\bCA\bAR\bRG\bGS\bS=\b="\b"-\b-D\bDU\bUS\bSE\bE_\b_T\bTL\bLS\bS"\b" A\bAU\bUX\bXL\bLI\bIB\bBS\bS=\b="\b"-\b-l\bls\bss\bsl\bl -\b-l\blc\bcr\bry\byp\bpt\bto\bo"\b"
+
+  * If the OpenSSL include files (such as ssl.h) are in directory /usr/local/
+    include/openssl, and the OpenSSL libraries (such as libssl.so and
+    libcrypto.so) are in directory /usr/local/lib:
+
+        % m\bma\bak\bke\be t\bti\bid\bdy\by # if you have left-over files from a previous build
+        % m\bma\bak\bke\be m\bma\bak\bke\bef\bfi\bil\ble\bes\bs C\bCC\bCA\bAR\bRG\bGS\bS=\b="\b"-\b-D\bDU\bUS\bSE\bE_\b_T\bTL\bLS\bS -\b-I\bI/\b/u\bus\bsr\br/\b/l\blo\boc\bca\bal\bl/\b/i\bin\bnc\bcl\blu\bud\bde\be"\b" \\b\
+            A\bAU\bUX\bXL\bLI\bIB\bBS\bS=\b="\b"-\b-L\bL/\b/u\bus\bsr\br/\b/l\blo\boc\bca\bal\bl/\b/l\bli\bib\bb -\b-l\bls\bss\bsl\bl -\b-l\blc\bcr\bry\byp\bpt\bto\bo"\b"
+
+If you need to apply other customizations (such as Berkeley DB databases,
+MySQL, PosgreSQL, LDAP or SASL), see the respective Postfix README documents,
+and combine their "make makefiles" instructions with the instructions above:
+
+    % m\bma\bak\bke\be t\bti\bid\bdy\by # if you have left-over files from a previous build
+    % m\bma\bak\bke\be m\bma\bak\bke\bef\bfi\bil\ble\bes\bs C\bCC\bCA\bAR\bRG\bGS\bS=\b="\b"-\b-D\bDU\bUS\bSE\bE_\b_T\bTL\bLS\bS \\b\
+        (\b(o\bot\bth\bhe\ber\br -\b-D\bD o\bor\br -\b-I\bI o\bop\bpt\bti\bio\bon\bns\bs)\b)"\b" \\b\
+        A\bAU\bUX\bXL\bLI\bIB\bBS\bS=\b="\b"-\b-l\bls\bss\bsl\bl -\b-l\blc\bcr\bry\byp\bpt\bto\bo \\b\
+        (\b(o\bot\bth\bhe\ber\br -\b-l\bl o\bop\bpt\bti\bio\bon\bns\bs f\bfo\bor\br l\bli\bib\bbr\bra\bar\bri\bie\bes\bs i\bin\bn /\b/u\bus\bsr\br/\b/l\bli\bib\bb)\b) \\b\
+        (\b(-\b-L\bL/\b/p\bpa\bat\bth\bh/\b/n\bna\bam\bme\be +\b+ -\b-l\bl o\bop\bpt\bti\bio\bon\bns\bs f\bfo\bor\br o\bot\bth\bhe\ber\br l\bli\bib\bbr\bra\bar\bri\bie\bes\bs)\b)"\b"
+
+To complete the build process, see the Postfix INSTALL instructions. Postfix
+has TLS support turned off by default, so you can start using Postfix as soon
+as it is installed.
+
+S\bSM\bMT\bTP\bP S\bSe\ber\brv\bve\ber\br s\bsp\bpe\bec\bci\bif\bfi\bic\bc s\bse\bet\btt\bti\bin\bng\bgs\bs
+
+Topics covered in this section:
+
+  * Server-side certificate and private key configuration
+  * Server-side TLS activity logging
+  * Enabling TLS in the Postfix SMTP server
+  * Client certificate verification
+  * Supporting AUTH over TLS only
+  * Server-side TLS session cache
+  * Server access control
+  * Server-side cipher controls
+  * Miscellaneous server controls
+
+S\bSe\ber\brv\bve\ber\br-\b-s\bsi\bid\bde\be c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be a\ban\bnd\bd p\bpr\bri\biv\bva\bat\bte\be k\bke\bey\by c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
+
+In order to use TLS, the Postfix SMTP server needs a certificate and a private
+key. Both must be in "pem" format. The private key must not be encrypted,
+meaning: the key must be accessible without password. Both certificate and
+private key may be in the same file.
+
+Both RSA and DSA certificates are supported. Typically you will only have RSA
+certificates issued by a commercial CA. In addition, the tools supplied with
+OpenSSL will by default issue RSA certificates. You can have both at the same
+time, in which case the cipher used determines which certificate is presented.
+For Netscape and OpenSSL clients without special cipher choices, the RSA
+certificate is preferred.
+
+In order for remote SMTP clients to check the Postfix SMTP server certificates,
+the CA certificate (in case of a certificate chain, all CA certificates) must
+be available. You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s).
+
+Example: the certificate for "server.dom.ain" was issued by "intermediate CA"
+which itself has a certificate issued by "root CA". Create the server.pem file
+with:
+
+    % c\bca\bat\bt s\bse\ber\brv\bve\ber\br_\b_c\bce\ber\brt\bt.\b.p\bpe\bem\bm i\bin\bnt\bte\ber\brm\bme\bed\bdi\bia\bat\bte\be_\b_C\bCA\bA.\b.p\bpe\bem\bm >\b> s\bse\ber\brv\bve\ber\br.\b.p\bpe\bem\bm
+
+A Postfix SMTP server certificate supplied here must be usable as SSL server
+certificate and hence pass the "openssl verify -purpose sslserver ..." test.
+
+A client that trusts the root CA has a local copy of the root CA certificate,
+so it is not necessary to include the root CA certificate here. Leaving it out
+of the "server.pem" file reduces the overhead of the TLS exchange.
+
+If you want the Postfix SMTP server to accept remote SMTP client certificates
+issued by these CAs, append the root certificate to $smtpd_tls_CAfile or
+install it in the $smtpd_tls_CApath directory. When you configure trust in a
+root CA, it is not necessary to explicitly trust intermediary CAs signed by the
+root CA, unless $smtpd_tls_verify_depth is less than the number of CAs in the
+certificate chain for the clients of interest. With a verify depth of 1 you can
+only verify certificates directly signed by a trusted CA, and all trusted
+intermediary CAs need to be configured explicitly. With a verify depth of 2 you
+can verify clients signed by a root CA or a direct intermediary CA (so long as
+the client is correctly configured to supply its intermediate CA certificate).
+
+RSA key and certificate examples:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_cert_file = /etc/postfix/server.pem
+        smtpd_tls_key_file = $smtpd_tls_cert_file
+
+Their DSA counterparts:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
+        smtpd_tls_dkey_file = $smtpd_tls_dcert_file
+
+To verify a remote SMTP client certificate, the Postfix SMTP server needs to
+trust the certificates of the issuing certification authorities. These
+certificates in "pem" format can be stored in a single $smtpd_tls_CAfile or in
+multiple files, one CA per file in the $smtpd_tls_CApath directory. If you use
+a directory, don't forget to create the necessary "hash" links with:
+
+    # $\b$O\bOP\bPE\bEN\bNS\bSS\bSL\bL_\b_H\bHO\bOM\bME\bE/\b/b\bbi\bin\bn/\b/c\bc_\b_r\bre\beh\bha\bas\bsh\bh /\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/d\bdi\bir\bre\bec\bct\bto\bor\bry\by
+
+The $smtpd_tls_CAfile contains the CA certificates of one or more trusted CAs.
+The file is opened (with root privileges) before Postfix enters the optional
+chroot jail and so need not be accessible from inside the chroot jail.
+
+Additional trusted CAs can be specified via the $smtpd_tls_CApath directory, in
+which case the certificates are read (with $mail_owner privileges) from the
+files in the directory when the information is needed. Thus, the
+$smtpd_tls_CApath directory needs to be accessible inside the optional chroot
+jail.
+
+When you configure Postfix to request client certificates (by setting
+$smtpd_tls_asck_ccert = yes), any certificates in $smtpd_tls_CAfile are sent to
+the client, in order to allow it to choose an identity signed by a CA you
+trust. If no $smtpd_tls_CAfile is specified, no preferred CA list is sent, and
+the client is free to choose an identity signed by any CA. Many clients use a
+fixed identity regardless of the preferred CA list and you may be able to
+reduce TLS negotiation overhead by installing client CA certificates mostly or
+only in $smtpd_tls_CApath. In the latter case you need not specify a
+$smtpd_tls_CAfile.
+
+Note, that unless client certificates are used to allow greater access to TLS
+authenticated clients, it is best to not ask for client certificates at all, as
+in addition to increased overhead some clients (notably in some cases qmail)
+are unable to complete the TLS handshake when client certificates are
+requested.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_CAfile = /etc/postfix/CAcert.pem
+        smtpd_tls_CApath = /etc/postfix/certs
+
+S\bSe\ber\brv\bve\ber\br-\b-s\bsi\bid\bde\be T\bTL\bLS\bS a\bac\bct\bti\biv\bvi\bit\bty\by l\blo\bog\bgg\bgi\bin\bng\bg
+
+To get additional information about Postfix SMTP server TLS activity you can
+increase the loglevel from 0..4. Each logging level also includes the
+information that is logged at a lower logging level.
+
+    0 Disable logging of TLS activity.
+
+    1 Log TLS handshake and certificate information.
+
+    2 Log levels during TLS negotiation.
+
+    3 Log hexadecimal and ASCII dump of TLS negotiation process
+
+    4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS
+
+Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
+discouraged.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_loglevel = 0
+
+To include information about the protocol and cipher used as well as the client
+and issuer CommonName into the "Received:" message header, set the
+smtpd_tls_received_header variable to true. The default is no, as the
+information is not necessarily authentic. Only information recorded at the
+final destination is reliable, since the headers may be changed by intermediate
+servers.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_received_header = yes
+
+E\bEn\bna\bab\bbl\bli\bin\bng\bg T\bTL\bLS\bS i\bin\bn t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP s\bse\ber\brv\bve\ber\br
+
+By default, TLS is disabled in the Postfix SMTP server, so no difference to
+plain Postfix is visible. Explicitly switch it on using "smtpd_use_tls = yes".
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_use_tls = yes
+
+With this, Postfix SMTP server announces STARTTLS support to SMTP clients, but
+does not require that clients use TLS encryption.
+
+Note: when an unprivileged user invokes "sendmail -bs", STARTTLS is never
+offered due to insufficient privileges to access the server private key. This
+is intended behavior.
+
+You can ENFORCE the use of TLS, so that the Postfix SMTP server announces
+STARTTLS and accepts no mail without TLS encryption, by setting
+"smtpd_enforce_tls = yes". According to RFC 2487 this MUST NOT be applied in
+case of a publicly-referenced Postfix SMTP server. This option is off by
+default and should only seldom be used.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_enforce_tls = yes
+
+TLS is sometimes used in the non-standard "wrapper" mode where a server always
+uses TLS, instead of announcing STARTTLS support and waiting for clients to
+request TLS service. Some clients, namely Outlook [Express] prefer the
+"wrapper" mode. This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a
+port<>25 and OE (5.01 Mac on all ports).
+
+It is strictly discouraged to use this mode from main.cf. If you want to
+support this service, enable a special port in master.cf and specify "-
+o smtpd_tls_wrappermode = yes" as an smtpd(8) command line option. Port 465
+(smtps) was once chosen for this feature.
+
+Example:
+
+    /etc/postfix/master.cf:
+        smtps    inet  n       -       n       -       -       smtpd
+          -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
+
+C\bCl\bli\bie\ben\bnt\bt c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be v\bve\ber\bri\bif\bfi\bic\bca\bat\bti\bio\bon\bn
+
+To receive a remote SMTP client certificate, the Postfix SMTP server must
+explicitly ask for one (any contents of $smtpd_tls_CAfile are also sent to the
+client as a hint for choosing a certificate from a suitable CA). Unfortunately,
+Netscape clients will either complain if no matching client certificate is
+available or will offer the user client a list of certificates to choose from.
+Additionally some MTAs (notably some versions of qmail) are unable to complete
+TLS negotiation when client certificates are requested, and abort the SMTP
+session. So this option is "off" by default. You will however need the
+certificate if you want to use certificate based relaying with, for example,
+the permit_tls_clientcerts feature.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_ask_ccert = no
+
+You may also decide to REQUIRE a remote SMTP client certificate before allowing
+TLS connections. This feature is included for completeness, and implies
+"smtpd_tls_ask_ccert = yes".
+
+Please be aware, that this will inhibit TLS connections without a proper client
+certificate and that it makes sense only when non-TLS submission is disabled
+(smtpd_enforce_tls = yes). Otherwise, clients could bypass the restriction by
+simply not using STARTTLS at all.
+
+When TLS is not enforced, the connection will be handled as if only
+"smtpd_tls_ask_ccert = yes" is specified, and a warning is logged.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_req_ccert = no
+
+A client certificate verification depth of 1 is sufficient if the certificate
+is directly issued by a CA listed in the CA file. The default value (5) should
+also suffice for longer chains (root CA issues special CA which then issues the
+actual certificate...)
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_ccert_verifydepth = 5
+
+S\bSu\bup\bpp\bpo\bor\brt\bti\bin\bng\bg A\bAU\bUT\bTH\bH o\bov\bve\ber\br T\bTL\bLS\bS o\bon\bnl\bly\by
+
+Sending AUTH data over an unencrypted channel poses a security risk. When TLS
+layer encryption is required (smtpd_enforce_tls = yes), the Postfix SMTP server
+will announce and accept AUTH only after the TLS layer has been activated with
+STARTTLS. When TLS layer encryption is optional (smtpd_enforce_tls = no), it
+may however still be useful to only offer AUTH when TLS is active. To maintain
+compatibility with non-TLS clients, the default is to accept AUTH without
+encryption. In order to change this behavior, set "smtpd_tls_auth_only = yes".
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_auth_only = no
+
+S\bSe\ber\brv\bve\ber\br-\b-s\bsi\bid\bde\be T\bTL\bLS\bS s\bse\bes\bss\bsi\bio\bon\bn c\bca\bac\bch\bhe\be
+
+The Postfix SMTP server and the remote SMTP client negotiate a session, which
+takes some computer time and network bandwidth. By default, this session
+information is cached only in the smtpd(8) process actually using this session
+and is lost when the process terminates. To share the session information
+between multiple smtpd(8) processes, a persistent session cache can be used.
+You can specify any database type that can store objects of several kbytes and
+that supports the sequence operator. DBM databases are not suitable because
+they can only store small objects. The cache is maintained by the tlsmgr(8)
+process, so there is no problem with concurrent access.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
+
+Cached Postfix SMTP server session information expires after a certain amount
+of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer
+time of 3600sec (=1 hour). RFC 2246 recommends a maximum of 24 hours.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_session_cache_timeout = 3600s
+
+S\bSe\ber\brv\bve\ber\br a\bac\bcc\bce\bes\bss\bs c\bco\bon\bnt\btr\bro\bol\bl
+
+Postfix TLS support introduces two additional features for Postfix SMTP server
+access control:
+
+    permit_tls_clientcerts
+        Allow the remote SMTP client SMTP request if the client certificate
+        passes verification, and if its fingerprint is listed in the list of
+        client certificates (see relay_clientcerts discussion below).
+
+    permit_tls_all_clientcerts
+        Allow the remote client SMTP request if the client certificate passes
+        verification.
+
+The permit_tls_all_clientcerts feature must be used with caution, because it
+can result in too many access permissions. Use this feature only if a special
+CA issues the client certificates, and only if this CA is listed as trusted CA.
+If other CAs are trusted, any owner of a valid client certificate would be
+authorized. The permit_tls_all_clientcerts feature can be practical for a
+specially created email relay server.
+
+It is however recommended to stay with the permit_tls_clientcerts feature and
+list all certificates via $relay_clientcerts, as permit_tls_all_clientcerts
+does not permit any control when a certificate must no longer be used (e.g. an
+employee leaving).
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_recipient_restrictions =
+            ...
+            permit_tls_clientcerts
+            reject_unauth_destination
+            ...
+
+The Postfix list manipulation routines give special treatment to whitespace and
+some other characters, making the use of certificate names unpractical. Instead
+we use the certificate fingerprints as they are difficult to fake but easy to
+use for lookup. Postfix lookup tables are in the form of (key, value) pairs.
+Since we only need the key, the value can be chosen freely, e.g. the name of
+the user or host.
+
+Example:
+
+    /etc/postfix/main.cf:
+        relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+
+    /etc/postfix/relay_clientcerts:
+        D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
+
+S\bSe\ber\brv\bve\ber\br-\b-s\bsi\bid\bde\be c\bci\bip\bph\bhe\ber\br c\bco\bon\bnt\btr\bro\bol\bls\bs
+
+To influence the Postfix SMTP server cipher selection scheme, you can give
+cipherlist string. A detailed description would go to far here; please refer to
+the OpenSSL documentation. If you don't know what to do with it, simply don't
+touch it and leave the (openssl-)compiled in default!
+
+DO NOT USE " to enclose the string, specify just the string!!!
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_cipherlist = DEFAULT
+
+If you want to take advantage of ciphers with EDH, DH parameters are needed.
+Instead of using the built-in DH parameters for both 1024bit and 512bit, it is
+better to generate "own" parameters, since otherwise it would "pay" for a
+possible attacker to start a brute force attack against parameters that are
+used by everybody. For this reason, the parameters chosen are already different
+from those distributed with other TLS packages.
+
+To generate your own set of DH parameters, use:
+
+    % o\bop\bpe\ben\bns\bss\bsl\bl g\bge\ben\bnd\bdh\bh -\b-o\bou\but\bt /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/d\bdh\bh_\b_1\b10\b02\b24\b4.\b.p\bpe\bem\bm -\b-2\b2 -\b-r\bra\ban\bnd\bd /\b/v\bva\bar\br/\b/r\bru\bun\bn/\b/e\beg\bgd\bd-\b-p\bpo\boo\bol\bl
+    1\b10\b02\b24\b4
+    % o\bop\bpe\ben\bns\bss\bsl\bl g\bge\ben\bnd\bdh\bh -\b-o\bou\but\bt /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/d\bdh\bh_\b_5\b51\b12\b2.\b.p\bpe\bem\bm -\b-2\b2 -\b-r\bra\ban\bnd\bd /\b/v\bva\bar\br/\b/r\bru\bun\bn/\b/e\beg\bgd\bd-\b-p\bpo\boo\bol\bl 5\b51\b12\b2
+
+Examples:
+
+    /etc/postfix/main.cf:
+        smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+        smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
+
+M\bMi\bis\bsc\bce\bel\bll\bla\ban\bne\beo\bou\bus\bs s\bse\ber\brv\bve\ber\br c\bco\bon\bnt\btr\bro\bol\bls\bs
+
+The smtpd_starttls_timeout parameter limits the time of Postfix SMTP server
+write and read operations during TLS startup and shutdown handshake procedures.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtpd_starttls_timeout = 300s
+
+S\bSM\bMT\bTP\bP C\bCl\bli\bie\ben\bnt\bt s\bsp\bpe\bec\bci\bif\bfi\bic\bc s\bse\bet\btt\bti\bin\bng\bgs\bs
+
+Topics covered in this section:
+
+  * Client-side certificate and private key configuration
+  * Client-side TLS activity logging
+  * Client-side TLS session cache
+  * Enabling TLS in the Postfix SMTP client
+  * Server certificate verification
+  * Client-side cipher controls
+  * Miscellaneous client controls
+
+C\bCl\bli\bie\ben\bnt\bt-\b-s\bsi\bid\bde\be c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be a\ban\bnd\bd p\bpr\bri\biv\bva\bat\bte\be k\bke\bey\by c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
+
+During TLS startup negotiation the Postfix SMTP client may present a
+certificate to the remote SMTP server. The Netscape client is rather clever
+here and lets the user select between only those certificates that match CA
+certificates offered by the remote SMTP server. As the Postfix SMTP client uses
+the "SSL_connect()" function from the OpenSSL package, this is not possible and
+we have to choose just one certificate. So for now the default is to use _no_
+certificate and key unless one is explicitly specified here.
+
+Both RSA and DSA certificates are supported. You can have both at the same
+time, in which case the cipher used determines which certificate is presented.
+
+It is possible for the Postfix SMTP client to use the same key/certificate pair
+as the Postfix SMTP server. If a certificate is to be presented, it must be in
+"pem" format. The private key must not be encrypted, meaning: it must be
+accessible without password. Both parts (certificate and private key) may be in
+the same file.
+
+In order for remote SMTP servers to verify the Postfix SMTP client
+certificates, the CA certificate (in case of a certificate chain, all CA
+certificates) must be available. You should add these certificates to the
+client certificate, the client certificate first, then the issuing CA(s).
+
+Example: the certificate for "client.example.com" was issued by "intermediate
+CA" which itself has a certificate of "root CA". Create the client.pem file
+with:
+
+    % c\bca\bat\bt c\bcl\bli\bie\ben\bnt\bt_\b_c\bce\ber\brt\bt.\b.p\bpe\bem\bm i\bin\bnt\bte\ber\brm\bme\bed\bdi\bia\bat\bte\be_\b_C\bCA\bA.\b.p\bpe\bem\bm >\b> c\bcl\bli\bie\ben\bnt\bt.\b.p\bpe\bem\bm
+
+A Postfix SMTP client certificate supplied here must be usable as SSL client
+certificate and hence pass the "openssl verify -purpose sslclient ..." test.
+
+A server that trusts the root CA has a local copy of the root CA certificate,
+so it is not necessary to include the root CA certificate here. Leaving it out
+of the "client.pem" file reduces the overhead of the TLS exchange.
+
+If you want the Postfix SMTP client to accept remote SMTP server certificates
+issued by these CAs, append the root certificate to $smtp_tls_CAfile or install
+it in the $smtp_tls_CApath directory. When you configure trust in a root CA, it
+is not necessary to explicitly trust intermediary CAs signed by the root CA,
+unless $smtp_tls_verify_depth is less than the number of CAs in the certificate
+chain for the servers of interest. With a verify depth of 1 you can only verify
+certificates directly signed by a trusted CA, and all trusted intermediary CAs
+need to be configured explicitly. With a verify depth of 2 you can verify
+servers signed by a root CA or a direct intermediary CA (so long as the server
+is correctly configured to supply its intermediate CA certificate).
+
+RSA key and certificate examples:
+
+    /etc/postfix/main.cf:
+        smtp_tls_cert_file = /etc/postfix/client.pem
+        smtp_tls_key_file = $smtp_tls_cert_file
+
+Their DSA counterparts:
+
+    /etc/postfix/main.cf:
+        smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
+        smtp_tls_dkey_file = $smtpd_tls_cert_file
+
+To verify a remote SMTP server certificate, the Postfix SMTP client needs to
+trust the certificates of the issuing certification authorities. These
+certificates in "pem" format can be stored in a single $smtp_tls_CAfile or in
+multiple files, one CA per file in the $smtp_tls_CApath directory. If you use a
+directory, don't forget to create the necessary "hash" links with:
+
+    # $\b$O\bOP\bPE\bEN\bNS\bSS\bSL\bL_\b_H\bHO\bOM\bME\bE/\b/b\bbi\bin\bn/\b/c\bc_\b_r\bre\beh\bha\bas\bsh\bh /\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/d\bdi\bir\bre\bec\bct\bto\bor\bry\by
+
+The $smtp_tls_CAfile contains the CA certificates of one or more trusted CAs.
+The file is opened (with root privileges) before Postfix enters the optional
+chroot jail and so need not be accessible from inside the chroot jail.
+
+Additional trusted CAs can be specified via the $smtp_tls_CApath directory, in
+which case the certificates are read (with $mail_owner privileges) from the
+files in the directory when the information is needed. Thus, the
+$smtp_tls_CApath directory needs to be accessible inside the optional chroot
+jail.
+
+The choice between $smtp_tls_CAfile and $smtpd_tls_CApath is a space/time
+tradeoff. If there are many trusted CAs, the cost of preloading them all into
+memory may not pay off in reduced access time when the certificate is needed.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_CAfile = /etc/postfix/CAcert.pem
+        smtp_tls_CApath = /etc/postfix/certs
+
+C\bCl\bli\bie\ben\bnt\bt-\b-s\bsi\bid\bde\be T\bTL\bLS\bS a\bac\bct\bti\biv\bvi\bit\bty\by l\blo\bog\bgg\bgi\bin\bng\bg
+
+To get additional information about Postfix SMTP client TLS activity you can
+increase the loglevel from 0..4. Each logging level also includes the
+information that is logged at a lower logging level.
+
+    0 Disable logging of TLS activity.
+
+    1 Log TLS handshake and certificate information.
+
+    2 Log levels during TLS negotiation.
+
+    3 Log hexadecimal and ASCII dump of TLS negotiation process
+
+    4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_loglevel = 0
+
+C\bCl\bli\bie\ben\bnt\bt-\b-s\bsi\bid\bde\be T\bTL\bLS\bS s\bse\bes\bss\bsi\bio\bon\bn c\bca\bac\bch\bhe\be
+
+The remote SMTP server and the Postfix SMTP client negotiate a session, which
+takes some computer time and network bandwidth. By default, this session
+information is cached only in the smtp(8) process actually using this session
+and is lost when the process terminates. To share the session information
+between multiple smtp(8) processes, a persistent session cache can be used. You
+can specify any database type that can store objects of several kbytes and that
+supports the sequence operator. DBM databases are not suitable because they can
+only store small objects. The cache is maintained by the tlsmgr(8) process, so
+there is no problem with concurrent access.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_session_cache_database = btree:/etc/postfix/smtp_scache
+
+Cached Postfix SMTP client session information expires after a certain amount
+of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer
+time of 3600s (=1 hour). RFC 2246 recommends a maximum of 24 hours.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_session_cache_timeout = 3600s
+
+E\bEn\bna\bab\bbl\bli\bin\bng\bg T\bTL\bLS\bS i\bin\bn t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP c\bcl\bli\bie\ben\bnt\bt
+
+By default, TLS is disabled in the Postfix SMTP client, so no difference to
+plain Postfix is visible. If you enable TLS, the Postfix SMTP client will send
+STARTTLS when TLS support is announced by the remote SMTP server.
+
+WARNING: MS Exchange servers will announce STARTTLS support even when the
+service is not configured, so that the TLS handshake will fail. It may be wise
+to not use this option on your central mail hub, as you don't know in advance
+whether you are going to connect to such a host. Instead, use the
+smtp_tls_per_site recipient/site specific options that are described below.
+
+When the TLS handshake fails and no other server is available, the Postfix SMTP
+client defers the delivery attempt, and the mail stays in the queue.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_use_tls = yes
+
+You can ENFORCE the use of TLS, so that the Postfix SMTP client will not
+deliver mail over unencrypted connections. In this mode, the remote SMTP server
+hostname must match the information in the remote server certificate, and the
+server certificate must be issued by a CA that is trusted by the Postfix SMTP
+client. If the remote server certificate doesn't verify or the remote SMTP
+server hostname doesn't match, and no other server is available, the delivery
+attempt is deferred and the mail stays in the queue.
+
+The remote SMTP server hostname used in the check is beyond question, as it
+must be the principal hostname (no CNAME allowed here). Checks are performed
+against all names provided as dNSNames in the SubjectAlternativeName. If no
+dNSNames are specified, the CommonName is checked. The behavior may be changed
+with the smtp_tls_enforce_peername option which is discussed below.
+
+This option is useful only if you know that you will only connect to servers
+that support RFC 2487 _and_ that present server certificates that meet the
+above requirements. An example would be a client only sends email to one
+specific mailhub that offers the necessary STARTTLS support.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_enforce_tls = no
+
+As of RFC 2487 the requirements for hostname checking for MTA clients are not
+set. When TLS is required (smtp_enforce_tls = yes), the option
+smtp_tls_enforce_peername can be set to "no" to disable strict remote SMTP
+server hostname checking. In this case, the mail delivery will proceed
+regardless of the CommonName etc. listed in the certificate.
+
+Note: the smtp_tls_enforce_peername setting has no effect on sessions that are
+controlled via the smtp_tls_per_site table.
+
+Disabling the remote SMTP server hostname verification can make sense in closed
+environment where special CAs are created. If not used carefully, this option
+opens the danger of a "man-in-the-middle" attack (the CommonName of this
+possible attacker is logged).
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_enforce_peername = yes
+
+Generally, trying TLS can be a bad idea, as some servers offer STARTTLS but the
+negotiation will fail leading to unexplainable failures. Instead, it may be a
+good idea to choose the TLS usage policy based on the recipient or the mailhub
+to which you are connecting.
+
+Deciding the TLS usage policy per recipient may be difficult, since a single
+email delivery attempt can involve several recipients. Instead, use of TLS is
+controlled by the Postfix next-hop destination domain name and by the remote
+SMTP server hostname. If either of these matches an entry in the
+smtp_tls_per_site table, appropriate action is taken.
+
+The remote SMTP server hostname is simply the DNS name of the server that the
+Postfix SMTP client connects to. The next-hop destination is Postfix specific.
+By default, this is the domain name in the recipient address, but this
+information can be overruled by the transport(5) table or by the relayhost
+parameter setting. In these cases the relayhost etc. must be listed in the
+smtp_tls_per_site table, instead of the recipient domain name.
+
+Format of the table: domain or host names are specified on the left-hand side;
+no wildcards are allowed. On the right hand side specify one of the following
+keywords:
+
+    NONE
+        Don't use TLS at all.
+    MAY
+        Try to use STARTTLS if offered, otherwise use the unencrypted
+        connection. NOTE: STARTTLS can be used only if TLS is already enabled
+        via main.cf, so that the client TLS engine is properly initialized at
+        program startup.
+    MUST
+        Require usage of STARTTLS, require that the remote SMTP server hostname
+        matches the information in the remote SMTP server certificate, and
+        require that the remote SMTP server certificate was issued by a trusted
+        CA.
+    MUST_NOPEERMATCH
+        Require usage of STARTTLS, but do not require that the remote SMTP
+        server hostname matches the information in the remote SMTP server
+        certificate, or that the server certificate was issued by a trusted CA.
+
+The actual TLS usage policy depends not only on whether the next-hop
+destination or remote SMTP server hostname are found in the smtp_tls_per_site
+table, but also on the smtp_enforce_tls setting:
+
+  * If no match was found, the policy is applied as specified with
+    smtp_enforce_tls.
+
+  * If a match was found, and the smtp_enforce_tls policy is "enforce", NONE
+    explicitly switches it off; otherwise the "enforce" mode is used even for
+    entries that specify MAY.
+
+Special hint for TLS enforcement mode: since no secure DNS lookup mechanism is
+available, mail can be delivered to the wrong remote SMTP server. This is not
+prevented by specifying MUST for the next-hop domain name. The recommended
+setup is: specify local transport(5) table entries for sensitive domains with
+explicit smtp:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+smtp_tls_per_site table.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_per_site = hash:/etc/postfix/tls_per_site
+
+As we decide on a "per site" basis whether or not to use TLS, it would be good
+to have a list of sites that offered "STARTTLS". We can collect it ourselves
+with this option.
+
+If the smtp_tls_note_starttls_offer feature is enabled and a server offers
+STARTTLS while TLS is not already enabled for that server, the Postfix SMTP
+client logs a line as follows:
+
+    postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_note_starttls_offer = yes
+
+S\bSe\ber\brv\bve\ber\br c\bce\ber\brt\bti\bif\bfi\bic\bca\bat\bte\be v\bve\ber\bri\bif\bfi\bic\bca\bat\bti\bio\bon\bn
+
+When verifying a remote SMTP server certificate, a verification depth of 1 is
+sufficient if the certificate is directly issued by a CA specified with
+smtp_tls_CAfile or smtp_tls_CApath. The default value of 5 should also suffice
+for longer chains (root CA issues special CA which then issues the actual
+certificate...)
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_scert_verifydepth = 5
+
+C\bCl\bli\bie\ben\bnt\bt-\b-s\bsi\bid\bde\be c\bci\bip\bph\bhe\ber\br c\bco\bon\bnt\btr\bro\bol\bls\bs
+
+To influence the Postfix SMTP client cipher selection scheme, you can give
+cipherlist string. A detailed description would go to far here; please refer to
+the OpenSSL documentation. If you don't know what to do with it, simply don't
+touch it and leave the (openssl-)compiled in default!
+
+DO NOT USE " to enclose the string, specify just the string!!!
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_tls_cipherlist = DEFAULT
+
+M\bMi\bis\bsc\bce\bel\bll\bla\ban\bne\beo\bou\bus\bs c\bcl\bli\bie\ben\bnt\bt c\bco\bon\bnt\btr\bro\bol\bls\bs
+
+The smtp_starttls_timeout parameter limits the time of Postfix SMTP client
+write and read operations during TLS startup and shutdown handshake procedures.
+In case of problems the Postfix SMTP client tries the next network address on
+the mail exchanger list, and defers delivery if no alternative server is
+available.
+
+Example:
+
+    /etc/postfix/main.cf:
+        smtp_starttls_timeout = 300s
+
+T\bTL\bLS\bS m\bma\ban\bna\bag\bge\ber\br s\bsp\bpe\bec\bci\bif\bfi\bic\bc s\bse\bet\btt\bti\bin\bng\bgs\bs
+
+The security of cryptographic software such as TLS depends critically on the
+ability to generate unpredictable numbers for keys and other information. To
+this end, the tlsmgr(8) process maintains a Pseudo Random Number Generator
+(PRNG) pool. This is queried by the smtp(8) and smtpd(8) processes when they
+initialize. By default, these daemons request 32 bytes, the equivalent to 256
+bits. This is more than sufficient to generate a 128bit (or 168bit) session
+key.
+
+Example:
+
+    /etc/postfix/main.cf:
+        tls_daemon_random_bytes = 32
+
+In order to feed its in-memory PRNG pool, the tlsmgr(8) reads entropy from an
+external source, both at startup and during run-time. Specify a good entropy
+source, like EGD or /dev/urandom; be sure to only use non-blocking sources. If
+the entropy source is not a regular file, you must prepend the source type to
+the source name: "dev:" for a device special file, or "egd:" for a source with
+EGD compatible socket interface.
+
+Examples (specify only one in main.cf):
+
+    /etc/postfix/main.cf:
+        tls_random_source = dev:/dev/urandom
+        tls_random_source = egd:/var/run/egd-pool
+
+By default, tlsmgr(8) reads 32 bytes from the external entropy source at each
+seeding event. This amount (256bits) is more than sufficient for generating a
+128bit symmetric key. With EGD and device entropy sources, the tlsmgr(8) limits
+the amount of data read at each step to 255 bytes. If you specify a regular
+file as entropy source, a larger amount of data can be read.
+
+Example:
+
+    /etc/postfix/main.cf:
+        tls_random_bytes = 32
+
+In order to update its in-memory PRNG pool, the tlsmgr(8) queries the external
+entropy source again after a pseudo-random amount of time. The time is
+calculated using the PRNG, and is between 0 and the maximal time specified with
+tls_random_reseed_period. The default maximal time interval is 1 hour.
+
+Example:
+
+    /etc/postfix/main.cf:
+        tls_random_reseed_period = 3600s
+
+The tlsmgr(8) process saves the PRNG state to a persistent exchange file at
+regular times and when the process terminates, so that it can recover the PRNG
+state the next time it starts up. This file is created when it does not exist.
+Its default location is under the Postfix configuration directory, which is not
+the proper place for information that is modified by Postfix. Instead, the file
+location should probably be on the /var partition (but n\bno\bot\bt inside the chroot
+jail).
+
+Examples:
+
+    /etc/postfix/main.cf:
+        tls_random_exchange_name = /etc/postfix/prng_exch
+        tls_random_prng_update_period = 3600s
+
+G\bGe\bet\btt\bti\bin\bng\bg s\bst\bta\bar\brt\bte\bed\bd,\b, q\bqu\bui\bic\bck\bk a\ban\bnd\bd d\bdi\bir\brt\bty\by
+
+The following steps will get you started quickly. Because you sign your own
+Postfix public key certificate, you get TLS encryption but no TLS
+authentication. This is sufficient for testing, and for exchanging email with
+sites that you have no trust relationship with. For real authentication, your
+Postfix public key certificate needs to be signed by a recognized Certificate
+Authority, and Postfix needs to be configured with a list of public key
+certificates of Certificate Authorities, so that Postfix can verify the public
+key certificates of remote hosts.
+
+In the examples below, user input is shown in b\bbo\bol\bld\bd font, and a "#" prompt
+indicates a super-user shell.
+
+  * Become your own Certificate Authority, so that you can sign your own public
+    keys. This example uses the CA.pl script that ships with OpenSSL. By
+    default, OpenSSL installs this as /usr/local/ssl/misc/CA.pl, but your
+    mileage may vary. The script creates a private key in ./demoCA/private/
+    cakey.pem and a public key in ./demoCA/cacert.pem.
+
+        % /\b/u\bus\bsr\br/\b/l\blo\boc\bca\bal\bl/\b/s\bss\bsl\bl/\b/m\bmi\bis\bsc\bc/\b/C\bCA\bA.\b.p\bpl\bl -\b-n\bne\bew\bwc\bca\ba
+        CA certificate filename (or enter to create)
+
+        Making CA certificate ...
+        Using configuration from /etc/ssl/openssl.cnf
+        Generating a 1024 bit RSA private key
+        ....................++++++
+        .....++++++
+        writing new private key to './demoCA/private/cakey.pem'
+        Enter PEM pass phrase:w\bwh\bha\bat\bte\bev\bve\ber\br
+
+  * Create an unpassworded private key for host FOO and create an unsigned
+    public key certificate.
+
+        % o\bop\bpe\ben\bns\bss\bsl\bl r\bre\beq\bq -\b-n\bne\bew\bw -\b-n\bno\bod\bde\bes\bs -\b-k\bke\bey\byo\bou\but\bt F\bFO\bOO\bO-\b-k\bke\bey\by.\b.p\bpe\bem\bm -\b-o\bou\but\bt F\bFO\bOO\bO-\b-r\bre\beq\bq.\b.p\bpe\bem\bm -\b-d\bda\bay\bys\bs
+        3\b36\b65\b5
+        Using configuration from /etc/ssl/openssl.cnf
+        Generating a 1024 bit RSA private key
+        ........................................++++++
+        ....++++++
+        writing new private key to 'FOO-key.pem'
+        -----
+        You are about to be asked to enter information that will be
+        incorporated
+        into your certificate request.
+        What you are about to enter is what is called a Distinguished Name or a
+        DN.
+        There are quite a few fields but you can leave some blank
+        For some fields there will be a default value,
+        If you enter '.', the field will be left blank.
+        -----
+        Country Name (2 letter code) [AU]:U\bUS\bS
+        State or Province Name (full name) [Some-State]:N\bNe\bew\bw Y\bYo\bor\brk\bk
+        Locality Name (eg, city) []:W\bWe\bes\bst\btc\bch\bhe\bes\bst\bte\ber\br
+        Organization Name (eg, company) [Internet Widgits Pty Ltd]:P\bPo\bor\brc\bcu\bup\bpi\bin\bne\be
+        Organizational Unit Name (eg, section) []:
+        Common Name (eg, YOUR name) []:F\bFO\bOO\bO
+        Email Address []:w\bwi\bie\bet\bts\bse\be@\b@p\bpo\bor\brc\bcu\bup\bpi\bin\bne\be.\b.o\bor\brg\bg
+
+        Please enter the following 'extra' attributes
+        to be sent with your certificate request
+        A challenge password []:w\bwh\bha\bat\bte\bev\bve\ber\br
+        An optional company name []:
+
+  * Sign the public key certificate for host FOO with the Certification
+    Authority private key that we created a few steps ago.
+
+        % o\bop\bpe\ben\bns\bss\bsl\bl c\bca\ba -\b-o\bou\but\bt F\bFO\bOO\bO-\b-c\bce\ber\brt\bt.\b.p\bpe\bem\bm -\b-i\bin\bnf\bfi\bil\ble\bes\bs F\bFO\bOO\bO-\b-r\bre\beq\bq.\b.p\bpe\bem\bm
+        Uing configuration from /etc/ssl/openssl.cnf
+        Enter PEM pass phrase:w\bwh\bha\bat\bte\bev\bve\ber\br
+        Check that the request matches the signature
+        Signature ok
+        The Subjects Distinguished Name is as follows
+        countryName           :PRINTABLE:'US'
+        stateOrProvinceName   :PRINTABLE:'New York'
+        localityName          :PRINTABLE:'Westchester'
+        organizationName      :PRINTABLE:'Porcupine'
+        commonName            :PRINTABLE:'FOO'
+        emailAddress          :IA5STRING:'wietse@porcupine.org'
+        Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365
+        days)
+        Sign the certificate? [y/n]:y\by
+
+        1 out of 1 certificate requests certified, commit? [y/n]y\by
+        Write out database with 1 new entries
+        Data Base Updated
+
+  * Install the host private key, the host public key certificate, and the
+    Certification Authority certificate files. This requires super-user
+    privileges.
+
+        # c\bcp\bp d\bde\bem\bmo\boC\bCA\bA/\b/c\bca\bac\bce\ber\brt\bt.\b.p\bpe\bem\bm F\bFO\bOO\bO-\b-k\bke\bey\by.\b.p\bpe\bem\bm F\bFO\bOO\bO-\b-c\bce\ber\brt\bt.\b.p\bpe\bem\bm /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx
+        # c\bch\bhm\bmo\bod\bd 6\b64\b44\b4 /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/F\bFO\bOO\bO-\b-c\bce\ber\brt\bt.\b.p\bpe\bem\bm /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bca\bac\bce\ber\brt\bt.\b.p\bpe\bem\bm
+        # c\bch\bhm\bmo\bod\bd 4\b40\b00\b0 /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/F\bFO\bOO\bO-\b-k\bke\bey\by.\b.p\bpe\bem\bm
+
+  * Configure Postfix, by adding the following to /etc/postfix/main.cf.
+
+        smtp_tls_CAfile = /etc/postfix/cacert.pem
+        smtp_tls_cert_file = /etc/postfix/FOO-cert.pem
+        smtp_tls_key_file = /etc/postfix/FOO-key.pem
+        smtp_tls_session_cache_database = btree:/var/run/smtp_tls_session_cache
+        smtp_use_tls = yes
+        smtpd_tls_CAfile = /etc/postfix/cacert.pem
+        smtpd_tls_cert_file = /etc/postfix/FOO-cert.pem
+        smtpd_tls_key_file = /etc/postfix/FOO-key.pem
+        smtpd_tls_received_header = yes
+        smtpd_tls_session_cache_database = btree:/var/run/
+        smtpd_tls_session_cache
+        smtpd_use_tls = yes
+        tls_random_source = dev:/dev/urandom
+
+R\bRe\bep\bpo\bor\brt\bti\bin\bng\bg p\bpr\bro\bob\bbl\ble\bem\bms\bs
+
+When reporting a problem, please be thorough in the report. Patches, when
+possible, are greatly appreciated too.
+
+Please differentiate when possible between:
+
+  * Problems in the TLS code: <postfix_tls@aet.tu-cottbus.de>
+  * Problems in vanilla Postfix: <postfix-users@postfix.org>
+
+C\bCo\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by w\bwi\bit\bth\bh P\bPo\bos\bst\btf\bfi\bix\bx <\b<2\b2.\b.2\b2 T\bTL\bLS\bS s\bsu\bup\bpp\bpo\bor\brt\bt
+
+Postfix version 2.2 TLS support is based on the Postfix/TLS patch by Lutz
+Jänicke, but differs in a few minor ways.
+
+  * main.cf: Use b\bbt\btr\bre\bee\be instead of s\bsd\bdb\bbm\bm for TLS session cache databases.
+
+    TLS session cache databases are now accessed only by the tlsmgr(8) process,
+    so there are no more concurrency issues. Although Postfix has an s\bsd\bdb\bbm\bm
+    client, the s\bsd\bdb\bbm\bm library (1000 lines of code) is not included with Postfix.
+
+    TLS session caches can use any database that can store objects of several
+    kbytes or more, and that implements the sequence operation. In most cases,
+    b\bbt\btr\bre\bee\be databases should be adequate.
+
+    NOTE: You cannot use d\bdb\bbm\bm databases. TLS session objects are too large.
+
+  * master.cf: Specify u\bun\bni\bix\bx instead of f\bfi\bif\bfo\bo as the tlsmgr service type.
+
+    The smtp(8) and smtpd(8) processes now use a client-server protocol in
+    order to access the tlsmgr(8) pseudo-random number generation (PRNG) pool,
+    and in order to access the TLS session cache databases. Such a protocol
+    cannot be run across fifos.
+
+C\bCr\bre\bed\bdi\bit\bts\bs
+
+  * TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus
+    Technical University.
+  * Wietse Venema adopted the code, did some restructuring, and compiled this
+    part of the documentation from Lutz's documents.
+
index bc4123a1fe2d98179becb7da5b09b5527d0254dc..7e9f0c46753743dcc400e8e0b6c266296d896bfa 100644 (file)
@@ -55,6 +55,40 @@ Postfix will simply use IP version 4 just like it did before. See
 the IPV6_README document for what systems are supported, and how
 to turn on IPv6 in main.cf.
 
+Incompatible changes with snapshot Postfix-2.2-20041210+TLS
+===========================================================
+
+Postfix version 2.2 TLS support is based on the Postfix/TLS patch
+by Lutz Jaenicke, but differs in a few minor ways.
+
+- main.cf: Use btree instead of sdbm for TLS session cache databases.
+
+  Session caches are now accessed only by the tlsmgr(8) process,
+  so there are no more concurrency issues. Although Postfix still
+  has an sdbm client, the sdbm library (1000 lines of code) is no
+  longer included with Postfix/TLS.
+
+  TLS session caches can use any database that can store objects
+  of several kbytes or more, and that implements the sequence
+  operation. In most cases, btree databases should be adequate.
+
+  NOTE: You cannot use dbm databases. TLS session objects are too
+  large.
+
+- master.cf: Specify unix instead of fifo as the tlsmgr service type.
+
+  The smtp(8) and smtpd(8) processes now use a client-server protocol
+  in order to access the tlsmgr(8)'s pseudo-random number generation
+  (PRNG) pool, and in order to access the TLS session cache databases.
+  Such a protocol cannot be run across fifos.
+
+Major changes with snapshot Postfix-2.2-20041210+TLS
+=====================================================
+
+TLS support based on the Postfix/TLS patch by Lutz Jaenicke.  This
+is not compiled in by default. To build Postfix with TLS support,
+see the TLS_README document.
+
 Major changes with snapshot Postfix-2.2-20041218
 ================================================
 
diff --git a/postfix/TLS_LICENSE b/postfix/TLS_LICENSE
new file mode 100644 (file)
index 0000000..c588674
--- /dev/null
@@ -0,0 +1,36 @@
+Author:
+=======
+- Postfix/TLS support was originally developed by Lutz Jaenicke of
+  Brandenburg University of Technology, Cottbus, Germany.
+
+License:
+========
+- This software is free. You can do with it whatever you want.
+  I would however kindly ask you to acknowledge the use of this
+  package, if you are going use it in your software, which you might
+  be going to distribute. I would also like to receive a note if
+  you are a satisfied user :-)
+
+Acknowledgements:
+=================
+- This package is based on the OpenSSL package as provided by the
+  ``OpenSSL Project''.
+
+Disclaimer:
+===========
+- This software is provided ``as is''. You are using it at your own risk.
+  I will take no liability in any case.
+- This software package uses strong cryptography, so even if it is created,
+  maintained and distributed from liberal countries in Europe (where it is
+  legal to do this), it falls under certain export/import and/or use
+  restrictions in some other parts of the world. 
+- PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG
+  CRYPTOGRAPHY SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST
+  COMMUNICATING TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS
+  ILLEGAL IN SOME PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE
+  TO YOUR COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL
+  TECHNICAL SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR
+  OTHER PEOPLE YOU ARE STRONGLY ADVICED TO PAY CLOSE ATTENTION TO ANY
+  EXPORT/IMPORT AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHOR OF
+  PFIXTLS IS NOT LIABLE FOR ANY VIOLATIONS YOU MAKE HERE. SO BE
+  CAREFULLY YOURSELF, IT IS YOUR RESPONSIBILITY.  
diff --git a/postfix/conf/TLS_LICENSE b/postfix/conf/TLS_LICENSE
new file mode 120000 (symlink)
index 0000000..ff36e26
--- /dev/null
@@ -0,0 +1 @@
+../TLS_LICENSE
\ No newline at end of file
index 474dac5db570e8d5a18b385a3dc95d789199c6c5..2372fc4f9734454a05bd180865ca34e95690a60d 100644 (file)
@@ -9,11 +9,18 @@
 smtp      inet  n       -       n       -       -       smtpd
 #submission inet n      -       n       -       -       smtpd
 #      -o smtpd_etrn_restrictions=reject
+#      -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+#smtps    inet  n       -       n       -       -       smtpd
+#  -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
+#submission   inet    n       -       n       -       -       smtpd
+#  -o smtpd_etrn_restrictions=reject
+#  -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes
 #628      inet  n       -       n       -       -       qmqpd
 pickup    fifo  n       -       n       60      1       pickup
 cleanup   unix  n       -       n       -       0       cleanup
 qmgr      fifo  n       -       n       300     1       qmgr
 #qmgr     fifo  n       -       n       300     1       oqmgr
+tlsmgr    unix  -       -       n       1000?   1       tlsmgr
 rewrite   unix  -       -       n       -       -       trivial-rewrite
 bounce    unix  -       -       n       -       0       bounce
 defer     unix  -       -       n       -       0       bounce
index 8a2f65aa995c2979c9a925c51eed6c693d7d5327..8f7d1f78736b59368cef19b9547c23e4e9fe7ce0 100644 (file)
@@ -629,6 +629,15 @@ discard      unix  -       -       n       -       -       discard
 EOF
     }
 
+    # Add missing tlsmgr service to master.cf.
+
+    grep '^tlsmgr.*tlsmgr' $config_directory/master.cf >/dev/null || {
+       echo Editing $config_directory/master.cf, adding missing entry for tlsmgr service
+       cat >>$config_directory/master.cf <<EOF || exit 1
+tlsmgr    unix  -       -       n       1000?   1       tlsmgr
+EOF
+    }
+
     # Report (but do not remove) obsolete files.
 
     test -n "$obsolete" && {
index e7f1e5b8446158dc1a66a1931282fdde2f3f470f..a403fa1eb599c9135221029c38b59a48a0a15399 100644 (file)
@@ -81,6 +81,7 @@ $daemon_directory/showq:f:root:-:755
 $daemon_directory/smtp:f:root:-:755
 $daemon_directory/smtpd:f:root:-:755
 $daemon_directory/spawn:f:root:-:755
+$daemon_directory/tlsmgr:f:root:-:755
 $daemon_directory/trivial-rewrite:f:root:-:755
 $daemon_directory/verify:f:root:-:755
 $daemon_directory/virtual:f:root:-:755
@@ -100,6 +101,7 @@ $sendmail_path:f:root:-:755
 $newaliases_path:l:$sendmail_path
 $mailq_path:l:$sendmail_path
 $config_directory/LICENSE:f:root:-:644
+$config_directory/TLS_LICENSE:f:root:-:644
 $config_directory/access:f:root:-:644:p
 $config_directory/aliases:f:root:-:644:p
 $config_directory/canonical:f:root:-:644:p
@@ -175,6 +177,7 @@ $manpage_directory/man8/showq.8:f:root:-:644
 $manpage_directory/man8/smtp.8:f:root:-:644
 $manpage_directory/man8/smtpd.8:f:root:-:644
 $manpage_directory/man8/spawn.8:f:root:-:644
+$manpage_directory/man8/tlsmgr.8:f:root:-:644
 $manpage_directory/man8/trace.8:f:root:-:644
 $manpage_directory/man8/trivial-rewrite.8:f:root:-:644
 $manpage_directory/man8/verify.8:f:root:-:644
@@ -207,6 +210,7 @@ $sample_directory/sample-rewrite.cf:f:root:-:644:o
 $sample_directory/sample-scheduler.cf:f:root:-:644:o
 $sample_directory/sample-smtp.cf:f:root:-:644:o
 $sample_directory/sample-smtpd.cf:f:root:-:644:o
+$sample_directory/sample-tls.cf:f:root:-:644:o
 $sample_directory/sample-transport.cf:f:root:-:644:o
 $sample_directory/sample-verify.cf:f:root:-:644:o
 $sample_directory/sample-virtual.cf:f:root:-:644:o
@@ -248,6 +252,7 @@ $readme_directory/SMTPD_ACCESS_README:f:root:-:644
 $readme_directory/SMTPD_POLICY_README:f:root:-:644
 $readme_directory/SMTPD_PROXY_README:f:root:-:644
 $readme_directory/STANDARD_CONFIGURATION_README:f:root:-:644
+$readme_directory/TLS_README:f:root:-:644
 $readme_directory/TUNING_README:f:root:-:644
 $readme_directory/ULTRIX_README:f:root:-:644
 $readme_directory/UUCP_README:f:root:-:644
@@ -290,6 +295,7 @@ $html_directory/SMTPD_ACCESS_README.html:f:root:-:644
 $html_directory/SMTPD_POLICY_README.html:f:root:-:644
 $html_directory/SMTPD_PROXY_README.html:f:root:-:644
 $html_directory/STANDARD_CONFIGURATION_README.html:f:root:-:644
+$html_directory/TLS_README.html:f:root:-:644
 $html_directory/TUNING_README.html:f:root:-:644
 $html_directory/ULTRIX_README.html:f:root:-:644
 $html_directory/UUCP_README.html:f:root:-:644
index 25ba8bdebb3790de08ddae67173bed7463da1c0a..dfa689427afa07a906f8cf7a2cd76f7e1a6abd41 100644 (file)
@@ -852,7 +852,8 @@ align="left">Default delivery method </th> <th>Availability
 <p> Once the <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a> daemon has determined a default
 delivery method it searches the optional <a href="transport.5.html">transport(5)</a> table for
 information that overrides the message destination and/or delivery
-method.  Typical use of the <a href="transport.5.html">transport(5)</a> is to send mail to a system
+method.  Typical use of the <a href="transport.5.html">transport(5)</a> table is to send mail to
+a system
 that is not connected to the Internet, or to use a special SMTP
 client configuration for destinations that have special requirements.
 See, for example, the <a href="STANDARD_CONFIGURATION_README.html">STANDARD_CONFIGURATION_README</a> and <a href="UUCP_README.html">UUCP_README</a>
index 0c08aa00a61872511b618ade14111eb6d1c12fe1..916d82f8f54e3c433d68c0b1b86e1daceff23ed0 100644 (file)
@@ -257,13 +257,16 @@ Postfix 2.0 </td> </tr>
 <tr> <td> SASL authentication </td> <td><a href="SASL_README.html">SASL_README</a></td> <td>
 Postfix 1.0 </td> </tr>
 
+<tr> <td> STARTTLS session encryption </td> <td><a href="TLS_README.html">TLS_README</a></td> <td>
+Postfix 2.2 </td> </tr>
+
 </table>
 
 </blockquote>
 
-<p> Note: support for TLS (encrypted SMTP sessions and certificate
-based authentication) and for IP version 6 is still separate from
-Postfix but is expected to be merged soon. </p>
+<p> Note: IP version 6 support is compiled into Postfix on operating
+systems that have IPv6 support. See the <a href="IPV6_README.html">IPV6_README</a> file for details.
+</p>
 
 <h3>4.4 - Overriding built-in parameter default settings</h3>
 
index 514370806cfda16a9b0b65947f56924ad5062f69..e573cb5a44265221c3737d4dfea09a73b5f45ee4 100644 (file)
@@ -7,7 +7,7 @@ DAEMONS =  bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
        showq.8.html smtp.8.html smtpd.8.html trivial-rewrite.8.html \
        oqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
        trace.8.html verify.8.html proxymap.8.html anvil.8.html \
-       scache.8.html discard.8.html
+       scache.8.html discard.8.html tlsmgr.8.html
 COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
        postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
        postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
@@ -127,6 +127,10 @@ virtual.8.html: ../src/virtual/virtual.c
        PATH=../mantools:$$PATH; \
        srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
 
+tlsmgr.8.html: ../src/tlsmgr/tlsmgr.c
+       PATH=../mantools:$$PATH; \
+       srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
+
 trace.8.html: bounce.8.html
        rm -f $@
        ln -s $? $@
diff --git a/postfix/html/TLS_README.html b/postfix/html/TLS_README.html
new file mode 100644 (file)
index 0000000..6826d9f
--- /dev/null
@@ -0,0 +1,1389 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix TLS Support </title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix TLS Support
+</h1>
+
+<hr>
+
+<h2> WARNING </h2>
+
+<p> By turning on TLS support in Postfix, you not only get the
+ability to encrypt mail and to authenticate clients or servers.
+You also turn on thousands and thousands of lines of OpenSSL library
+code.  Assuming that OpenSSL is written as carefully as Wietse's
+own code, every 1000 lines introduce one additional bug into
+Postfix.  </p>
+
+<h2> Purpose of this document </h2>
+
+<p> This document describes how to build Postfix with Transport
+Layer Security (TLS) support in the Postfix SMTP client and Postfix
+SMTP server, and how to configure the TLS manager daemon that
+maintains the Pseudo Random Number Generator (PRNG) pool and the
+TLS session cache information. </p>
+
+<p> Topics covered in this document: </p>
+
+<ul>
+
+<li><a href="#build_tls">Building Postfix with TLS support</a>
+
+<li><a href="#server_tls">SMTP Server specific settings</a>
+
+<li> <a href="#client_tls">SMTP Client specific settings</a>
+
+<li><a href="#tlsmgr_controls"> TLS manager specific settings </a>
+
+<li><a href="#problems"> Reporting problems </a>
+
+<li><a href="#compat">Compatibility with Postfix < 2.2 TLS support</a>
+
+<li><a href="#credits"> Credits </a>
+
+</ul>
+
+<p> And last but not least, for the impatient: </p>
+
+<ul>
+
+<li><a href="#quick-start">Getting started, quick and dirty</a>
+
+</ul>
+
+<h2><a name="build_tls">Building Postfix with TLS support</a></h2>
+
+<p> To build Postfix with TLS support, first we need to generate
+the <tt>make(1)</tt> files with the necessary definitions. This is
+done by invoking the command "<tt>make makefiles</tt> in the Postfix
+top-level directory and with arguments as shown next. </p>
+
+<ul>
+
+<li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
+in directory <tt>/usr/include/openssl</tt>, and the OpenSSL libraries
+(such as <tt>libssl.so</tt> and <tt>libcrypto.so</tt>) are in
+directory <tt>/usr/lib</tt>:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS" AUXLIBS="-lssl -lcrypto"</b>
+</pre>
+</blockquote>
+
+<li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
+in directory <tt>/usr/local/include/openssl</tt>, and the OpenSSL
+libraries (such as <tt>libssl.so</tt> and <tt>libcrypto.so</tt>)
+are in directory <tt>/usr/local/lib</tt>:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \
+    AUXLIBS="-L/usr/local/lib -lssl -lcrypto" </b>
+</pre>
+</blockquote>
+
+</ul>
+
+<p> If you need to apply other customizations (such as Berkeley DB
+databases, MySQL, PosgreSQL, LDAP or SASL), see the respective
+Postfix README documents, and combine their "<tt>make makefiles</tt>"
+instructions with the instructions above:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS \
+    <i>(other -D or -I options)</i>" \
+    AUXLIBS="-lssl -lcrypto \
+    <i>(other -l options for libraries in /usr/lib)</i> \
+    <i>(-L/path/name + -l options for other libraries)</i>"</b>
+</pre>
+</blockquote>
+
+<p> To complete the build process, see the Postfix <a href="INSTALL.html">INSTALL</a>
+instructions. Postfix has TLS support turned off by default, so
+you can start using Postfix as soon as it is installed.  </p>
+
+<h2><a name="server_tls">SMTP Server specific settings</a></h2>
+
+<p> Topics covered in this section: </p>
+
+<ul>
+
+<li><a href="#server_cert_key">Server-side certificate and private
+key configuration </a>
+
+<li><a href="#server_logging"> Server-side TLS activity logging
+</a>
+
+<li><a href="#server_enable">Enabling TLS in the Postfix SMTP server </a>
+
+<li><a href="#server_vrfy_client">Client certificate verification</a>
+
+<li><a href="#server_tls_auth">Supporting AUTH over TLS only</a>
+
+<li><a href="#server_tls_cache">Server-side TLS session cache</a>
+
+<li><a href="#server_access">Server access control</a>
+
+<li><a href="#server_cipher">Server-side cipher controls</a>
+
+<li><a href="#server_misc"> Miscellaneous server controls</a>
+
+</ul>
+
+<h3><a name="server_cert_key">Server-side certificate and private
+key configuration </a> </h3>
+
+<p> In order to use TLS, the Postfix SMTP server needs a certificate
+and a private key. Both must be in "pem" format. The private key
+must not be encrypted, meaning:  the key must be accessible without
+password.  Both certificate and private key may be in the same
+file.  </p>
+
+<p> Both RSA and DSA certificates are supported. Typically you will
+only have RSA certificates issued by a commercial CA. In addition,
+the tools supplied with OpenSSL will by default issue RSA certificates.
+You can have both at the same time, in which case the cipher used
+determines which certificate is presented. For Netscape and OpenSSL
+clients without special cipher choices, the RSA certificate is
+preferred. </p>
+
+<p> In order for remote SMTP clients to check the Postfix SMTP
+server certificates, the CA certificate (in case of a certificate
+chain, all CA certificates) must be available.  You should add
+these certificates to the server certificate, the server certificate
+first, then the issuing CA(s).  </p>
+
+<p> Example: the certificate for "server.dom.ain" was issued by
+"intermediate CA" which itself has a certificate issued by "root
+CA".  Create the server.pem file with: </p>
+
+<blockquote>
+<pre>
+% <b>cat server_cert.pem intermediate_CA.pem &gt; server.pem</b>
+</pre>
+</blockquote>
+
+<p> A Postfix SMTP server certificate supplied here must be usable
+as SSL server certificate and hence pass the "openssl verify -purpose
+sslserver ..." test. </p>
+
+<p> A client that trusts the root CA has a local copy of the root
+CA certificate, so it is not necessary to include the root CA
+certificate here.  Leaving it out of the "server.pem" file reduces
+the overhead of the TLS exchange. </p>
+
+<p> If you want the Postfix SMTP server to accept remote SMTP client
+certificates issued by these CAs, append the root certificate to
+$<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> or install it in the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> directory.  When
+you configure trust in a root CA, it is not necessary to explicitly trust
+intermediary CAs signed by the root CA, unless $smtpd_tls_verify_depth
+is less than the number of CAs in the certificate chain for the clients
+of interest. With a verify depth of 1 you can only verify certificates
+directly signed by a trusted CA, and all trusted intermediary CAs need to
+be configured explicitly. With a verify depth of 2 you can verify clients
+signed by a root CA or a direct intermediary CA (so long as the client
+is correctly configured to supply its intermediate CA certificate). </p>
+
+<p> RSA key and certificate examples: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = /etc/postfix/server.pem
+    <a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> = $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>
+</pre>
+</blockquote>
+
+<p> Their DSA counterparts: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> = /etc/postfix/server-dsa.pem
+    <a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> = $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>
+</pre>  
+</blockquote>
+
+<p> To verify a remote SMTP client certificate, the Postfix SMTP
+server needs to trust the certificates of the issuing certification
+authorities. These certificates in "pem" format can be stored in a
+single $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> or in multiple files, one CA per file in
+the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> directory. If you use a directory, don't forget
+to create the necessary "hash" links with: </p>
+
+<blockquote>
+<pre>
+# <b>$OPENSSL_HOME/bin/c_rehash <i>/path/to/directory</i> </b>
+</pre>
+</blockquote>
+
+<p> The $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> contains the CA certificates of one or
+more trusted CAs. The file is opened (with root privileges) before
+Postfix enters the optional chroot jail and so need not be accessible
+from inside the chroot jail. </p>
+
+<p> Additional trusted CAs can be specified via the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>
+directory, in which case the certificates are read (with $<a href="postconf.5.html#mail_owner">mail_owner</a>
+privileges) from the files in the directory when the information
+is needed. Thus, the $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> directory needs to be
+accessible inside the optional chroot jail. </p>
+
+<p> When you configure Postfix to request client certificates (by
+setting $smtpd_tls_asck_ccert = yes), any certificates in
+$<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> are sent to the client, in order to allow it to
+choose an identity signed by a CA you trust. If no $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>
+is specified, no preferred CA list is sent, and the client is free
+to choose an identity signed by any CA. Many clients use a fixed
+identity regardless of the preferred CA list and you may be able
+to reduce TLS negotiation overhead by installing client CA certificates
+mostly or only in $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a>. In the latter case you need
+not specify a $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>. </p>
+
+<p> Note, that unless client certificates are used to allow greater
+access to TLS authenticated clients, it is best to not ask for
+client certificates at all, as in addition to increased overhead
+some clients (notably in some cases qmail) are unable to complete
+the TLS handshake when client certificates are requested. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> = /etc/postfix/CAcert.pem
+    <a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> = /etc/postfix/certs
+</pre>
+</blockquote>
+
+<h3><a name="server_logging"> Server-side TLS activity logging </a> </h3>
+
+<p> To get additional information about Postfix SMTP server TLS
+activity you can increase the loglevel from 0..4. Each logging
+level also includes the information that is logged at a lower
+logging level. </p>
+
+<blockquote>
+
+<table>
+
+<tr> <td> 0 </td> <td> Disable logging of TLS activity.</td> </tr>
+
+<tr> <td> 1 </td> <td> Log TLS handshake and certificate information.
+</td> </tr>
+
+<tr> <td> 2 </td> <td> Log levels during TLS negotiation.  </td>
+</tr>
+
+<tr> <td> 3 </td> <td> Log hexadecimal and ASCII dump of TLS
+negotiation process </td> </tr>
+
+<tr> <td> 4 </td> <td> Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> Use loglevel 3 only in case of problems. Use of loglevel 4 is
+strongly discouraged. </p>
+
+<p> Example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 0
+</pre>
+</blockquote>
+
+<p> To include information about the protocol and cipher used as
+well as the client and issuer CommonName into the "Received:"
+message header, set the <a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> variable to true.
+The default is no, as the information is not necessarily authentic.
+Only information recorded at the final destination is reliable,
+since the headers may be changed by intermediate servers. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes
+</pre>
+</blockquote>
+
+<h3><a name="server_enable">Enabling TLS in the Postfix SMTP server </a> </h3>
+
+<p> By default, TLS is disabled in the Postfix SMTP server, so no
+difference to plain Postfix is visible.  Explicitly switch it on
+using "<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> = yes". </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> = yes
+</pre>
+</blockquote>
+
+<p> With this, Postfix SMTP server announces STARTTLS support to
+SMTP clients, but does not require that clients use TLS encryption.
+</p>
+
+<p> Note: when an unprivileged user invokes "sendmail -bs", STARTTLS
+is never offered due to insufficient privileges to access the server
+private key. This is intended behavior. </p>
+
+<p> You can ENFORCE the use of TLS, so that the Postfix SMTP server
+announces STARTTLS and accepts no mail without TLS encryption, by
+setting "<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> = yes". According to <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> this MUST
+NOT be applied in case of a publicly-referenced Postfix SMTP server.
+This option is off by default and should only seldom be used. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> = yes
+</pre>
+</blockquote>
+
+<p> TLS is sometimes used in the non-standard "wrapper" mode where
+a server always uses TLS, instead of announcing STARTTLS support
+and waiting for clients to request TLS service. Some clients, namely
+Outlook [Express] prefer the "wrapper" mode.  This is true for OE
+(Win32 &lt; 5.0 and Win32 &gt;=5.0 when run on a port&lt;&gt;25
+and OE (5.01 Mac on all ports). </p>
+
+<p> It is strictly discouraged to use this mode from main.cf. If
+you want to support this service, enable a special port in master.cf
+and specify "-o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a> = yes" as an <a href="smtpd.8.html">smtpd(8)</a> command
+line option.  Port 465 (smtps) was once chosen for this feature.
+</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/master.cf:
+    smtps    inet  n       -       n       -       -       smtpd
+      -o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a>=yes -o <a href="postconf.5.html#smtpd_sasl_auth_enable">smtpd_sasl_auth_enable</a>=yes
+</pre>
+</blockquote>
+
+<h3><a name="server_vrfy_client">Client certificate verification</a> </h3>
+
+<p> To receive a remote SMTP client certificate, the Postfix SMTP
+server must explicitly ask for one (any contents of $<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>
+are also sent to the client as a hint for choosing a certificate
+from a suitable CA). Unfortunately, Netscape clients will either
+complain if no matching client certificate is available or will
+offer the user client a list of certificates to choose from.
+Additionally some MTAs (notably some versions of qmail) are unable
+to complete TLS negotiation when client certificates are requested,
+and abort the SMTP session. So this option is "off" by default.
+You will however need the certificate if you want to use certificate
+based relaying with, for example, the <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
+feature.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = no
+</pre>
+</blockquote>
+
+<p> You may also decide to REQUIRE a remote SMTP client certificate
+before allowing TLS connections.  This feature is included for
+completeness, and implies "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = yes".  </p>
+
+<p> Please be aware, that this will inhibit TLS connections without
+a proper client certificate and that it makes sense only when
+non-TLS submission is disabled (<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> = yes). Otherwise,
+clients could bypass the restriction by simply not using STARTTLS
+at all. </p>
+
+<p> When TLS is not enforced, the connection will be handled as
+if only "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = yes" is specified, and a warning is
+logged. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> = no
+</pre>
+</blockquote>
+
+<p> A client certificate verification depth of 1 is sufficient if
+the certificate is directly issued by a CA listed in the CA file.
+The default value (5) should also suffice for longer chains (root
+CA issues special CA which then issues the actual certificate...)
+</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> = 5
+</pre>
+</blockquote>
+
+<h3><a name="server_tls_auth">Supporting AUTH over TLS only</a></h3>
+
+<p> Sending AUTH data over an unencrypted channel poses a security
+risk. When TLS layer encryption is required (<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> =
+yes), the Postfix SMTP server will announce and accept AUTH only
+after the TLS layer has been activated with STARTTLS. When TLS
+layer encryption is optional (<a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> = no), it may
+however still be useful to only offer AUTH when TLS is active. To
+maintain compatibility with non-TLS clients, the default is to
+accept AUTH without encryption. In order to change this behavior,
+set "<a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> = yes". </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> = no
+</pre>
+</blockquote>
+
+<h3><a name="server_tls_cache">Server-side TLS session cache</a> </h3>
+
+<p> The Postfix SMTP server and the remote SMTP client negotiate
+a session, which takes some computer time and network bandwidth.
+By default, this session information is cached only in the <a href="smtpd.8.html">smtpd(8)</a>
+process actually using this session and is lost when the process
+terminates.  To share the session information between multiple
+<a href="smtpd.8.html">smtpd(8)</a> processes, a persistent session cache can be used. You
+can specify any database type that can store objects of several
+kbytes and that supports the sequence operator. DBM databases are
+not suitable because they can only store small objects. The cache
+is maintained by the <a href="tlsmgr.8.html">tlsmgr(8)</a> process, so there is no problem with
+concurrent access. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = btree:/etc/postfix/smtpd_scache
+</pre>
+</blockquote>
+
+<p> Cached Postfix SMTP server session information expires after
+a certain amount of time.  Postfix/TLS does not use the OpenSSL
+default of 300s, but a longer time of 3600sec (=1 hour). <a href="http://www.faqs.org/rfcs/rfc2246.html">RFC 2246</a>
+recommends a maximum of 24 hours.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> = 3600s
+</pre>
+</blockquote>
+
+<h3><a name="server_access">Server access control</a> </h3>
+
+<p> Postfix TLS support introduces two additional features for
+Postfix SMTP server access control:  </p>
+
+<blockquote>
+
+<dl>
+
+<dt> <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a> </dt> <dd> <p> Allow the remote SMTP
+client SMTP request if the client certificate passes verification,
+and if its fingerprint is listed in the list of client certificates
+(see relay_clientcerts discussion below). </p> </dd>
+
+<dt> <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> </dt> <dd> <p> Allow the remote
+client SMTP request if the client certificate passes verification.
+</p> </dd>
+
+</dl>
+
+</blockquote>
+
+<p> The <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> feature must be used with caution,
+because it can result in too many access permissions.  Use this
+feature only if a special CA issues the client certificates, and
+only if this CA is listed as trusted CA. If other CAs are trusted,
+any owner of a valid client certificate would be authorized.
+The <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> feature can be practical for a
+specially created email relay server.  </p>
+
+<p> It is however recommended to stay with the <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
+feature and list all certificates via $relay_clientcerts, as
+<a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> does not permit any control when a
+certificate must no longer be used (e.g. an employee leaving). </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> = 
+        ... 
+        <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a> 
+        <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
+        ...
+</pre>
+</blockquote>
+
+<p> The Postfix list manipulation routines give special treatment
+to whitespace and some other characters, making the use of certificate
+names unpractical.  Instead we use the certificate fingerprints as
+they are difficult to fake but easy to use for lookup.  Postfix
+lookup tables are in the form of (key, value) pairs.  Since we only
+need the key, the value can be chosen freely, e.g.  the name of
+the user or host.</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+
+/etc/postfix/relay_clientcerts:
+    D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
+</pre>
+</blockquote>
+
+<h3><a name="server_cipher">Server-side cipher controls</a> </h3>
+
+<p> To influence the Postfix SMTP server cipher selection scheme,
+you can give cipherlist string.  A detailed description would go
+to far here; please refer to the OpenSSL documentation.  If you
+don't know what to do with it, simply don't touch it and leave the
+(openssl-)compiled in default! </p>
+
+<p> DO NOT USE " to enclose the string, specify just the string!!! </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> = DEFAULT
+</pre>
+</blockquote>
+
+<p> If you want to take advantage of ciphers with EDH, DH parameters
+are needed.  Instead of using the built-in DH parameters for both
+1024bit and 512bit, it is better to generate "own" parameters,
+since otherwise it would "pay" for a possible attacker to start a
+brute force attack against parameters that are used by everybody.
+For this reason, the parameters chosen are already different from
+those distributed with other TLS packages. </p>
+
+<p> To generate your own set of DH parameters, use: </p>
+
+<blockquote>
+<pre>
+% <b>openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024</b>
+% <b>openssl gendh -out /etc/postfix/dh_512.pem -2 -rand /var/run/egd-pool 512</b>
+</pre>
+</blockquote>
+
+<p> Examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh_1024.pem
+    <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = /etc/postfix/dh_512.pem
+</pre>
+</blockquote>
+
+<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
+
+<p> The <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> parameter limits the time of Postfix
+SMTP server write and read operations during TLS startup and shutdown
+handshake procedures.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> = 300s
+</pre>
+</blockquote>
+
+<h2> <a name="client_tls">SMTP Client specific settings</a> </h2>
+
+<p> Topics covered in this section: </p>
+
+<ul>
+
+<li><a href="#client_cert_key">Client-side certificate and private
+key configuration </a>
+
+<li><a href="#client_logging"> Client-side TLS activity logging
+</a>
+
+<li><a href="#client_tls_cache">Client-side TLS session cache</a>
+
+<li><a href="#client_tls"> Enabling TLS in the Postfix SMTP client </a>
+
+<li><a href="#client_vrfy_server">Server certificate verification</a>
+
+<li> <a href="#client_cipher">Client-side cipher controls </a>
+
+<li> <a href="#client_misc"> Miscellaneous client controls </a>
+
+</ul>
+
+<h3><a name="client_cert_key">Client-side certificate and private
+key configuration </a> </h3>
+
+<p> During TLS startup negotiation the Postfix SMTP client may present
+a certificate to the remote SMTP server.  The Netscape client is
+rather clever here and lets the user select between only those
+certificates that match CA certificates offered by the remote SMTP
+server. As the Postfix SMTP client uses the "SSL_connect()" function
+from the OpenSSL package, this is not possible and we have to choose
+just one certificate.  So for now the default is to use _no_
+certificate and key unless one is explicitly specified here. </p>
+
+<p> Both RSA and DSA certificates are supported.  You can have both
+at the same time, in which case the cipher used determines which
+certificate is presented.  </p>
+
+<p> It is possible for the Postfix SMTP client to use the same
+key/certificate pair as the Postfix SMTP server.  If a certificate
+is to be presented, it must be in "pem" format. The private key
+must not be encrypted, meaning: it must be accessible without
+password. Both parts (certificate and private key) may be in the
+same file. </p>
+
+<p> In order for remote SMTP servers to verify the Postfix SMTP
+client certificates, the CA certificate (in case of a certificate
+chain, all CA certificates) must be available.  You should add
+these certificates to the client certificate, the client certificate
+first, then the issuing CA(s). </p>
+
+<p> Example: the certificate for "client.example.com" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the client.pem file with: </p>
+
+<blockquote>
+<pre>
+% <b>cat client_cert.pem intermediate_CA.pem &gt; client.pem </b>
+</pre>
+</blockquote>
+
+<p> A Postfix SMTP client certificate supplied here must be usable
+as SSL client certificate and hence pass the "openssl verify -purpose
+sslclient ..." test. </p>
+
+<p> A server that trusts the root CA has a local copy of the root
+CA certificate, so it is not necessary to include the root CA
+certificate here. Leaving it out of the "client.pem" file reduces
+the overhead of the TLS exchange. </p>
+
+<p> If you want the Postfix SMTP client to accept remote SMTP server
+certificates issued by these CAs, append the root certificate to
+$<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> or install it in the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> directory.  When
+you configure trust in a root CA, it is not necessary to explicitly trust
+intermediary CAs signed by the root CA, unless $smtp_tls_verify_depth
+is less than the number of CAs in the certificate chain for the servers
+of interest. With a verify depth of 1 you can only verify certificates
+directly signed by a trusted CA, and all trusted intermediary CAs need to
+be configured explicitly. With a verify depth of 2 you can verify servers
+signed by a root CA or a direct intermediary CA (so long as the server
+is correctly configured to supply its intermediate CA certificate). </p>
+
+<p> RSA key and certificate examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/client.pem
+    <a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> = $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>
+</pre>
+</blockquote>
+
+<p> Their DSA counterparts: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> = /etc/postfix/client-dsa.pem
+    <a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> = $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>
+</pre>  
+</blockquote>
+
+<p> To verify a remote SMTP server certificate, the Postfix SMTP
+client needs to trust the certificates of the issuing certification
+authorities. These certificates in "pem" format can be stored in a
+single $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> or in multiple files, one CA per file in
+the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> directory. If you use a directory, don't forget
+to create the necessary "hash" links with: </p>
+
+<blockquote>
+<pre>
+# <b>$OPENSSL_HOME/bin/c_rehash <i>/path/to/directory</i> </b>
+</pre>
+</blockquote>
+
+<p> The $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> contains the CA certificates of one or more
+trusted CAs. The file is opened (with root privileges) before Postfix
+enters the optional chroot jail and so need not be accessible from inside the
+chroot jail. </p>
+
+<p> Additional trusted CAs can be specified via the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>
+directory, in which case the certificates are read (with $<a href="postconf.5.html#mail_owner">mail_owner</a>
+privileges) from the files in the directory when the information
+is needed. Thus, the $<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> directory needs to be accessible
+inside the optional chroot jail.  </p>
+
+<p> The choice between $<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> and $<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> is
+a space/time tradeoff. If there are many trusted CAs, the cost of
+preloading them all into memory may not pay off in reduced access time
+when the certificate is needed.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> = /etc/postfix/CAcert.pem
+    <a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> = /etc/postfix/certs
+</pre>
+</blockquote>
+
+<h3><a name="client_logging"> Client-side TLS activity logging </a> </h3>
+
+<p> To get additional information about Postfix SMTP client TLS
+activity you can increase the loglevel from 0..4. Each logging
+level also includes the information that is logged at a lower
+logging level. </p>
+
+<blockquote>
+
+<table>
+
+<tr> <td> 0 </td> <td> Disable logging of TLS activity.</td> </tr>
+
+<tr> <td> 1 </td> <td> Log TLS handshake and certificate information.
+</td> </tr>
+
+<tr> <td> 2 </td> <td> Log levels during TLS negotiation.  </td>
+</tr>
+
+<tr> <td> 3 </td> <td> Log hexadecimal and ASCII dump of TLS
+negotiation process </td> </tr>
+
+<tr> <td> 4 </td> <td> Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 0
+</pre>
+</blockquote>
+
+<h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3>
+
+<p> The remote SMTP server and the Postfix SMTP client negotiate a
+session, which takes some computer time and network bandwidth.  By
+default, this session information is cached only in the <a href="smtp.8.html">smtp(8)</a>
+process actually using this session and is lost when the process
+terminates.  To share the session information between multiple
+<a href="smtp.8.html">smtp(8)</a> processes, a persistent session cache can be used. You
+can specify any database type that can store objects of several
+kbytes and that supports the sequence operator. DBM databases are
+not suitable because they can only store small objects. The cache
+is maintained by the <a href="tlsmgr.8.html">tlsmgr(8)</a> process, so there is no problem with
+concurrent access. </p>
+
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = btree:/etc/postfix/smtp_scache
+</pre>
+</blockquote>
+
+<p> Cached Postfix SMTP client session information expires after
+a certain amount of time.  Postfix/TLS does not use the OpenSSL
+default of 300s, but a longer time of 3600s (=1 hour). <a href="http://www.faqs.org/rfcs/rfc2246.html">RFC 2246</a>
+recommends a maximum of 24 hours.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> = 3600s
+</pre>
+</blockquote>
+
+<h3><a name="client_tls"> Enabling TLS in the Postfix SMTP client </a>
+</h3>
+
+<p> By default, TLS is disabled in the Postfix SMTP client, so no
+difference to plain Postfix is visible.  If you enable TLS, the
+Postfix SMTP client will send STARTTLS when TLS support is announced
+by the remote SMTP server. </p>
+
+<p> WARNING: MS Exchange servers will announce STARTTLS support
+even when the service is not configured, so that the TLS handshake
+will fail.  It may be wise to not use this option on your central
+mail hub, as you don't know in advance whether you are going to
+connect to such a host. Instead, use the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
+recipient/site specific options that are described below. </p>
+
+<p> When the TLS handshake fails and no other server is available,
+the Postfix SMTP client defers the delivery attempt, and the mail
+stays in the queue.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> = yes
+</pre>
+</blockquote>
+
+<p> You can ENFORCE the use of TLS, so that the Postfix SMTP client
+will not deliver mail over unencrypted connections.  In this mode,
+the remote SMTP server hostname must match the information in the
+remote server certificate, and the server certificate must be issued
+by a CA that is trusted by the Postfix SMTP client.  If the remote
+server certificate doesn't verify or the remote SMTP server hostname
+doesn't match, and no other server is available, the delivery
+attempt is deferred and the mail stays in the queue.  </p>
+
+<p> The remote SMTP server hostname used in the check is beyond
+question, as it must be the principal hostname (no CNAME allowed
+here). Checks are performed against all names provided as dNSNames
+in the SubjectAlternativeName. If no dNSNames are specified, the
+CommonName is checked.  The behavior may be changed with the
+<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> option which is discussed below. </p>
+
+<p> This option is useful only if you know that you will only
+connect to servers that support <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> _and_ that present server
+certificates that meet the above requirements.  An example would
+be a client only sends email to one specific mailhub that offers
+the necessary STARTTLS support.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = no
+</pre>
+</blockquote>
+
+<p> As of <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> the requirements for hostname checking for MTA
+clients are not set. When TLS is required (<a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> = yes),
+the option <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> can be set to "no" to disable
+strict remote SMTP server hostname checking. In this case, the mail
+delivery will proceed regardless of the CommonName etc. listed in
+the certificate. </p>
+
+<p> Note: the <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> setting has no effect on
+sessions that are controlled via the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table.  </p>
+
+<p>  Disabling the remote SMTP server hostname verification can
+make sense in closed environment where special CAs are created.
+If not used carefully, this option opens the danger of a
+"man-in-the-middle" attack (the CommonName of this possible attacker
+is logged). </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> = yes
+</pre>
+</blockquote>
+
+<p> Generally, trying TLS can be a bad idea, as some servers offer
+STARTTLS but the negotiation will fail leading to unexplainable
+failures. Instead, it may be a good idea to choose the TLS usage
+policy based on the recipient or the mailhub to which you are
+connecting. </p>
+
+<p> Deciding the TLS usage policy per recipient may be difficult,
+since a single email delivery attempt can involve several recipients.
+Instead, use of TLS is controlled by the Postfix next-hop destination
+domain name and by the remote SMTP server hostname.  If either of these
+matches an entry in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table, appropriate action
+is taken.  </p>
+
+<p> The remote SMTP server hostname is simply the DNS name of the
+server that the Postfix SMTP client connects to.  The next-hop
+destination is Postfix specific.  By default, this is the domain
+name in the recipient address, but this information can be overruled
+by the <a href="transport.5.html">transport(5)</a> table or by the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting.
+In these cases the <a href="postconf.5.html#relayhost">relayhost</a> etc. must be listed in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
+table, instead of the recipient domain name. </p>
+
+<p> Format of the table: domain or host names are specified on the
+left-hand side; no wildcards are allowed.  On the right hand side
+specify one of the following keywords:  </p>
+
+<blockquote>
+
+<dl>
+
+<dt> NONE </dt> <dd> Don't use TLS at all. </dd>
+
+<dt> MAY </dt> <dd> Try to use STARTTLS if offered, otherwise use
+the unencrypted connection. NOTE: STARTTLS can be used only if TLS
+is already enabled via main.cf, so that the client TLS engine is
+properly initialized at program startup. </dd>
+
+<dt> MUST </dt> <dd> Require usage of STARTTLS, require that the
+remote SMTP server hostname matches the information in the remote
+SMTP server certificate, and require that the remote SMTP server
+certificate was issued by a trusted CA. </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> Require usage of STARTTLS, but do
+not require that the remote SMTP server hostname matches the
+information in the remote SMTP server certificate, or that the
+server certificate was issued by a trusted CA. </dd>
+
+</dl>
+
+</blockquote>
+
+<p> The actual TLS usage policy depends not only on whether the
+next-hop destination or remote SMTP server hostname are found in
+the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table, but also on the <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>
+setting:  </p>
+
+<ul>
+
+<li> <p> If no match was found, the policy is applied as specified
+with <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a>. </p>
+
+<li> <p> If a match was found, and the <a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> policy is
+"enforce", NONE explicitly switches it off; otherwise the "enforce"
+mode is used even for entries that specify MAY. </p>
+
+</ul>
+
+<p> Special hint for TLS enforcement mode:  since no secure DNS
+lookup mechanism is available, mail can be delivered to the wrong
+remote SMTP server. This is not prevented by specifying MUST for
+the next-hop domain name.  The recommended setup is:  specify local
+<a href="transport.5.html">transport(5)</a> table entries for sensitive domains with explicit
+<a href="smtp.8.html">smtp</a>:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> = hash:/etc/postfix/tls_per_site
+</pre>
+</blockquote>
+
+<p> As we decide on a "per site" basis whether or not to use TLS,
+it would be good to have a list of sites that offered "STARTTLS".
+We can collect it ourselves with this option. </p>
+
+<p> If the <a href="postconf.5.html#smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a> feature is enabled and a
+server offers STARTTLS while TLS is not already enabled for that
+server, the Postfix SMTP client logs a line as follows: </p>
+
+<blockquote>
+<pre>
+postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
+</pre>
+</blockquote>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a> = yes
+</pre>
+</blockquote>
+
+<h3><a name="client_vrfy_server">Server certificate verification</a> </h3>
+
+<p> When verifying a remote SMTP server certificate, a verification
+depth of 1 is sufficient if the certificate is directly issued by
+a CA specified with <a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> or <a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a>.  The default
+value of 5 should also suffice for longer chains (root CA issues
+special CA which then issues the actual certificate...) </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a> = 5
+</pre>
+</blockquote>
+
+<h3> <a name="client_cipher">Client-side cipher controls </a> </h3>
+
+<p> To influence the Postfix SMTP client cipher selection scheme,
+you can give cipherlist string.  A detailed description would go
+to far here; please refer to the OpenSSL documentation.  If you
+don't know what to do with it, simply don't touch it and leave the
+(openssl-)compiled in default! </p>
+
+<p> DO NOT USE " to enclose the string, specify just the string!!! </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> = DEFAULT
+</pre>
+</blockquote>
+
+<h3> <a name="client_misc"> Miscellaneous client controls </a> </h3>
+
+<p> The <a href="postconf.5.html#smtp_starttls_timeout">smtp_starttls_timeout</a> parameter limits the time of Postfix
+SMTP client write and read operations during TLS startup and shutdown
+handshake procedures.  In case of problems the Postfix SMTP client
+tries the next network address on the mail exchanger list, and
+defers delivery if no alternative server is available. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_starttls_timeout">smtp_starttls_timeout</a> = 300s
+</pre>
+</blockquote>
+
+<h2><a name="tlsmgr_controls"> TLS manager specific settings </a> </h2>
+
+<p> The security of cryptographic software such as TLS depends
+critically on the ability to generate unpredictable numbers for
+keys and other information. To this end, the <a href="tlsmgr.8.html">tlsmgr(8)</a> process
+maintains a Pseudo Random Number Generator (PRNG) pool.  This is
+queried by the <a href="smtp.8.html">smtp(8)</a> and <a href="smtpd.8.html">smtpd(8)</a> processes when they initialize.
+By default, these daemons request 32 bytes, the equivalent to 256
+bits. This is more than sufficient to generate a 128bit (or 168bit)
+session key.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> = 32
+</pre>
+</blockquote>
+
+<p> In order to feed its in-memory PRNG pool, the <a href="tlsmgr.8.html">tlsmgr(8)</a> reads
+entropy from an external source, both at startup and during run-time.
+Specify a good entropy source, like EGD or /dev/urandom; be sure
+to only use non-blocking sources.  If the entropy source is not a
+regular file, you must prepend the source type to the source name:
+"dev:" for a device special file, or "egd:" for a source with EGD
+compatible socket interface.  </p>
+
+<p> Examples (specify only one in main.cf): </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#tls_random_source">tls_random_source</a> = dev:/dev/urandom
+    <a href="postconf.5.html#tls_random_source">tls_random_source</a> = egd:/var/run/egd-pool
+</pre>
+</blockquote>
+
+<p> By default, <a href="tlsmgr.8.html">tlsmgr(8)</a> reads 32 bytes from the external entropy
+source at each seeding event.  This amount (256bits) is more than
+sufficient for generating a 128bit symmetric key.  With EGD and
+device entropy sources, the <a href="tlsmgr.8.html">tlsmgr(8)</a> limits the amount of data
+read at each step to 255 bytes. If you specify a regular file as
+entropy source, a larger amount of data can be read.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#tls_random_bytes">tls_random_bytes</a> = 32
+</pre>
+</blockquote>
+
+<p> In order to update its in-memory PRNG pool, the <a href="tlsmgr.8.html">tlsmgr(8)</a>
+queries the external entropy source again after a pseudo-random
+amount of time. The time is calculated using the PRNG, and is
+between 0 and the maximal time specified with <a href="postconf.5.html#tls_random_reseed_period">tls_random_reseed_period</a>.
+The default maximal time interval is 1 hour. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#tls_random_reseed_period">tls_random_reseed_period</a> = 3600s
+</pre>
+</blockquote>
+
+<p> The <a href="tlsmgr.8.html">tlsmgr(8)</a> process saves the PRNG state to a persistent
+exchange file at regular times and when the process terminates, so
+that it can recover the PRNG state the next time it starts up.
+This file is created when it does not exist. Its default location
+is under the Postfix configuration directory, which is not the
+proper place for information that is modified by Postfix.  Instead,
+the file location should probably be on the /var partition (but
+<b>not</b> inside the chroot jail).  </p>
+
+<p> Examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#tls_random_exchange_name">tls_random_exchange_name</a> = /etc/postfix/prng_exch
+    <a href="postconf.5.html#tls_random_prng_update_period">tls_random_prng_update_period</a> = 3600s
+</pre>
+</blockquote>
+
+<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
+
+<p> The following steps will get you started quickly. Because you
+sign your own Postfix public key certificate, you get TLS encryption
+but no TLS authentication.  This is sufficient for testing, and
+for exchanging email with sites that you have no trust relationship
+with.  For real authentication, your Postfix public key certificate
+needs to be signed by a recognized Certificate Authority, and
+Postfix needs to be configured with a list of public key certificates
+of Certificate Authorities, so that Postfix can verify the public key
+certificates of remote hosts. </p>
+
+<p> In the examples below, user input is shown in <b><tt>bold</tt></b>
+font, and a "<tt>#</tt>" prompt indicates a super-user shell. </p>
+
+<ul>
+
+<li> <p> Become your own Certificate Authority, so that you can
+sign your own public keys. This example uses the CA.pl script that
+ships with OpenSSL.  By default, OpenSSL installs this as
+<tt>/usr/local/ssl/misc/CA.pl</tt>, but your mileage may vary. 
+The script creates a private key in <tt>./demoCA/private/cakey.pem</tt>
+and a public key in <tt>./demoCA/cacert.pem</tt>.</p>
+
+<blockquote>
+<pre>
+% <b>/usr/local/ssl/misc/CA.pl -newca</b>
+CA certificate filename (or enter to create)
+
+Making CA certificate ...
+Using configuration from /etc/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+....................++++++
+.....++++++
+writing new private key to './demoCA/private/cakey.pem'
+Enter PEM pass phrase:<b>whatever</b>
+</pre>
+</blockquote>
+
+<li> <p> Create an unpassworded private key for host FOO and create
+an unsigned public key certificate. </p>
+
+<blockquote>
+<pre>
+% <b>openssl req -new -nodes -keyout FOO-key.pem -out FOO-req.pem -days 365</b>
+Using configuration from /etc/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+........................................++++++
+....++++++
+writing new private key to 'FOO-key.pem'
+-----
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:<b>US</b>
+State or Province Name (full name) [Some-State]:<b>New York</b>
+Locality Name (eg, city) []:<b>Westchester</b>
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:<b>Porcupine</b>
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:<b>FOO</b>
+Email Address []:<b>wietse@porcupine.org</b>
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:<b>whatever</b>
+An optional company name []:
+</pre>
+</blockquote>
+
+<li> <p> Sign the public key certificate for host FOO with the
+Certification Authority private key that we created a few
+steps ago. </p>
+
+<blockquote>
+<pre>
+% <b>openssl ca -out FOO-cert.pem -infiles FOO-req.pem</b>
+Uing configuration from /etc/ssl/openssl.cnf
+Enter PEM pass phrase:<b>whatever</b>
+Check that the request matches the signature
+Signature ok
+The Subjects Distinguished Name is as follows
+countryName           :PRINTABLE:'US'
+stateOrProvinceName   :PRINTABLE:'New York'
+localityName          :PRINTABLE:'Westchester'
+organizationName      :PRINTABLE:'Porcupine'
+commonName            :PRINTABLE:'FOO'
+emailAddress          :IA5STRING:'wietse@porcupine.org'
+Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365 days)
+Sign the certificate? [y/n]:<b>y</b>
+
+
+1 out of 1 certificate requests certified, commit? [y/n]<b>y</b>
+Write out database with 1 new entries
+Data Base Updated
+</pre>
+</blockquote>
+
+<li> <p> Install the host private key, the host public key certificate,
+and the Certification Authority certificate files.  This requires
+super-user privileges. </p>
+
+<blockquote>
+<pre>
+# <b>cp demoCA/cacert.pem FOO-key.pem FOO-cert.pem /etc/postfix</b>
+# <b>chmod 644 /etc/postfix/FOO-cert.pem /etc/postfix/cacert.pem</b>
+# <b>chmod 400 /etc/postfix/FOO-key.pem</b>
+</pre>
+</blockquote>
+
+<li> <p> Configure Postfix, by adding the following to
+<tt>/etc/postfix/main.cf</tt>. </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> = /etc/postfix/cacert.pem
+<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/FOO-cert.pem
+<a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> = /etc/postfix/FOO-key.pem
+<a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = btree:/var/run/smtp_tls_session_cache
+<a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> = yes
+<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> = /etc/postfix/cacert.pem
+<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = /etc/postfix/FOO-cert.pem
+<a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> = /etc/postfix/FOO-key.pem
+<a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes
+<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = btree:/var/run/smtpd_tls_session_cache
+<a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> = yes
+<a href="postconf.5.html#tls_random_source">tls_random_source</a> = dev:/dev/urandom
+</pre>
+</blockquote>
+
+</ul>
+
+
+<h2> <a name="problems"> Reporting problems </a> </h2>
+
+<p> When reporting a problem, please be thorough in the report.
+Patches, when possible, are greatly appreciated too. </p>
+
+<p> Please differentiate when possible between: </p>
+
+<ul>
+
+<li> Problems in the TLS code: &lt;postfix_tls@aet.tu-cottbus.de&gt;
+
+<li> Problems in vanilla Postfix: &lt;postfix-users@postfix.org&gt;
+
+</ul>
+
+<h2><a name="compat">Compatibility with Postfix <2.2 TLS support</a></h2>
+
+<p> Postfix version 2.2 TLS support is based on the Postfix/TLS
+patch by Lutz J&auml;nicke, but differs in a few minor ways. </p>
+
+<ul>
+
+<li> <p> main.cf: Use <b>btree</b> instead of <b>sdbm</b> for TLS
+session cache databases. </p>
+
+<p> TLS session cache databases are now accessed only by the
+<a href="tlsmgr.8.html">tlsmgr(8)</a> process, so there are no more concurrency issues. Although
+Postfix has an <b>sdbm</b> client, the <b>sdbm</b> library (1000
+lines of code) is not included with Postfix. </p>
+
+<p> TLS session caches can use any database that can store objects
+of several kbytes or more, and that implements the sequence operation.
+In most cases, <b>btree</b> databases should be adequate.  </p>
+
+<p> NOTE:  You cannot use <b>dbm</b> databases. TLS session objects
+are too large. </p>
+
+<li> <p> master.cf: Specify <b>unix</b> instead of <b>fifo</b> as
+the tlsmgr service type. </p>
+
+<p> The <a href="smtp.8.html">smtp(8)</a> and <a href="smtpd.8.html">smtpd(8)</a> processes now use a client-server
+protocol in order to access the <a href="tlsmgr.8.html">tlsmgr(8)</a> pseudo-random number
+generation (PRNG) pool, and in order to access the TLS session
+cache databases. Such a protocol cannot be run across fifos. </p>
+
+</ul>
+
+<h2><a name="credits">Credits </a> </h2>
+
+<ul>
+
+<li> TLS support for Postfix was originally developed by  Lutz
+J&auml;nicke at Cottbus Technical University.
+
+<li> Wietse Venema adopted the code, did some restructuring, and
+compiled this part of the documentation from Lutz's documents.
+
+</ul>
+
+</body>
+
+</html>
index 520e3bed62cbcb3d8311fae3ae7dc8745063110a..56a61526ab9d8ca20bd68d661d04af329cdbc0ad 100644 (file)
@@ -38,6 +38,8 @@ configuration examples </a>
 
 <li> <a href="SASL_README.html"> SASL Authentication </a>
 
+<li> <a href="TLS_README.html"> TLS Encryption and authentication </a>
+
 <li> <a href="IPV6_README.html"> IP Version 6 Support </a>
 
 <li> <a href="INSTALL.html"> Installation from source code </a>
index 1b6ca7b5fc5e18f1e67e24912855a27e3a0e0e34..e2b876ba9fcef405198e995d9753f6405093d361 100644 (file)
@@ -2542,7 +2542,8 @@ Note: you need to stop and start Postfix when this parameter changes.
 
 <p> When <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies just one IPv4 and/or IPv6 address
 that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail. </p>
+this address as the IP source address for outbound mail. Support
+for IPv6 is available in Postfix version 2.2 and later. </p>
 
 <p>
 On a multi-homed firewall with separate Postfix instances listening on the
@@ -2590,6 +2591,8 @@ or accepting connections. Specify one or more of "ipv4" or "ipv6",
 separated by whitespace or commas. The form "all" is equivalent to
 "ipv4, ipv6". </p>
 
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
 <p> Note: you MUST stop and start Postfix after changing this
 parameter. </p>
 
@@ -2613,8 +2616,6 @@ Postfix will do DNS type AAAA record lookups. </p>
 client will attempt to connect via IPv6 before attempting to use
 IPv4.  </p>
 
-<p> This feature is available in Postfix version 2.2 and later. </p>
-
 <p>
 Examples:
 </p>
@@ -3172,8 +3173,8 @@ protocol. This is enabled by default. </dd>
 
 <dd> Append the domain name in $<a href="postconf.5.html#myorigin">myorigin</a> or $<a href="postconf.5.html#mydomain">mydomain</a> when the
 client TLS certificate is successfully verified, and the client
-certificate fingerprint is listed on the server. This is enabled
-by default. </dd>
+certificate fingerprint is listed in $relay_clientcerts. This is
+enabled by default. </dd>
 
 <dt><b> <a href="postconf.5.html#permit_tls_all_clientcerts">permit_tls_all_clientcerts</a> </b></dt>
 
@@ -4977,6 +4978,30 @@ Do not change this unless you have a complete understanding of <a href="http://w
 </p>
 
 
+</DD>
+
+<DT><b><a name="relay_clientcerts">relay_clientcerts</a>
+(default: empty)</b></DT><DD>
+
+<p> The list of remote SMTP client certificates for which the
+Postfix SMTP server will allow access with the <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
+feature.  This feature does not use certificate names, because
+Postfix list manipulation routines treat whitespace and some other
+characters as special.  Instead we use certificate fingerprints as
+they are difficult to fake but easy to use for lookup. </p>
+
+<p> Postfix lookup tables are in the form of (key, value) pairs.
+Since we only need the key, the value can be chosen freely, e.g.
+the name of the user or host:
+D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home </p>
+
+<p> Example: </p>
+
+<pre>
+relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+</pre>
+
+
 </DD>
 
 <DT><b><a name="relay_destination_concurrency_limit">relay_destination_concurrency_limit</a>
@@ -5563,6 +5588,8 @@ An optional numerical network address that the SMTP client should
 bind to when making an IPv6 connection.
 </p>
 
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
 <p>
 This can be specified in the main.cf file for all SMTP clients, or
 it can be specified in the master.cf file for a specific client,
@@ -5583,8 +5610,6 @@ IP hosting, but can be a problem on multi-homed firewalls. See the
 <p> Note 2: address information may be enclosed inside <tt>[]</tt>,
 but this form is not recommended. </p>
 
-<p> This feature is available in Postfix version 2.2 and later. </p>
-
 
 </DD>
 
@@ -5813,6 +5838,30 @@ from a remote SMTP server. Use the <a href="postconf.5.html#smtp_discard_ehlo_ke
 feature to discard EHLO keywords selectively. </p>
 
 
+</DD>
+
+<DT><b><a name="smtp_enforce_tls">smtp_enforce_tls</a>
+(default: no)</b></DT><DD>
+
+<p> Enforcement mode: require that remote SMTP servers use TLS
+encryption, and never send mail in the clear.  This also requires
+that the remote SMTP server hostname matches the information in
+the remote server certificate, and that the remote SMTP server
+certificate was issued by a CA that is trusted by the Postfix SMTP
+client. If the certificate doesn't verify or the hostname doesn't
+match, delivery is deferred and mail stays in the queue.  </p>
+
+<p> The server hostname is matched against all names provided as
+dNSNames in the SubjectAlternativeName.  If no dNSNames are specified,
+the CommonName is checked.  The behavior may be changed with the
+<a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> option.  </p>
+
+<p> This option is useful only if you are definitely sure that you
+will only connect to servers that support <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> _and_ that
+provide valid server certificates.  Typical use is for clients that
+send all their email to a dedicated mailhub.  </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_helo_name">smtp_helo_name</a>
@@ -6211,6 +6260,15 @@ Example:
 </pre>
 
 
+</DD>
+
+<DT><b><a name="smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>
+(default: $<a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_security_options</a>)</b></DT><DD>
+
+<p> The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions. </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_send_xforward_command">smtp_send_xforward_command</a>
@@ -6281,6 +6339,308 @@ Do not wait for the response to the SMTP QUIT command.
 </p>
 
 
+</DD>
+
+<DT><b><a name="smtp_starttls_timeout">smtp_starttls_timeout</a>
+(default: 300s)</b></DT><DD>
+
+<p> Time limit for Postfix SMTP client write and read operations
+during TLS startup and shutdown handshake procedures. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_CAfile">smtp_tls_CAfile</a>
+(default: empty)</b></DT><DD>
+
+<p> The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP client certificate.  This is
+needed only when the CA certificate is not already present in the
+client certificate file.  </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> = /etc/postfix/CAcert.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_CApath">smtp_tls_CApath</a>
+(default: empty)</b></DT><DD>
+
+<p> Directory with PEM format certificate authority certificates
+that the Postfix SMTP client uses to verify a remote SMTP server
+certificate.  Don't forget to create the necessary "hash" links
+with, for example, "$OPENSSL_HOME/bin/c_rehash /etc/postfix/certs".
+</p>
+
+<p> To use this option in chroot mode, this directory (or a copy)
+must be inside the chroot jail. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> = /etc/postfix/certs
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_cert_file">smtp_tls_cert_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with the Postfix SMTP client RSA certificate in PEM format.
+This file may also contain the client private key, and these may
+be the same as the server certificate and key file. </p>
+
+<p> In order to verify certificates, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s). </p>
+
+<p> Example: the certificate for "client.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the client.pem file with "cat client_cert.pem intermediate_CA.pem
+root_CA.pem &gt; client.pem". </p>
+
+<p> If you want to accept remote SMTP server certificates issued
+by these CAs yourself, you can also add the CA certificates to the
+<a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a>, in which case it is not necessary to have them in
+the <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> or <a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>. </p>
+
+<p> A certificate supplied here must be usable as SSL client certificate and
+hence pass the "openssl verify -purpose sslclient ..." test. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> = /etc/postfix/client.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_cipherlist">smtp_tls_cipherlist</a>
+(default: empty)</b></DT><DD>
+
+<p> Controls the Postfix SMTP client TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_dcert_file">smtp_tls_dcert_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with the Postfix SMTP client DSA certificate in PEM format.
+This file may also contain the server private key. </p>
+
+<p> See the discussion under <a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> for more details.
+</p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> = /etc/postfix/client-dsa.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_dkey_file">smtp_tls_dkey_file</a>
+(default: $<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix SMTP client DSA private key in PEM format.
+The private key must not be encrypted. In other words, the key must
+be accessible without password. </p>
+
+<p> This file may be combined with the server certificate file
+specified with $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_enforce_peername">smtp_tls_enforce_peername</a>
+(default: yes)</b></DT><DD>
+
+<p> When TLS encryption is enforced, require that the remote SMTP
+server hostname matches the information in the remote SMTP server
+certificate.  As of <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a> the requirements for hostname checking
+for MTA clients are not specified. </p>
+
+<p> This option can be set to "no" to disable strict peer name
+checking. This setting has no effect on sessions that are controlled
+via the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table.  </p>
+
+<p> Disabling the hostname verification can make sense in closed
+environment where special CAs are created.  If not used carefully,
+this option opens the danger of a "man-in-the-middle" attack (the
+CommonName of this attacker will be logged). </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_key_file">smtp_tls_key_file</a>
+(default: $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix SMTP client RSA private key in PEM format.
+This file may be combined with the client certificate file specified
+with $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> = $<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_loglevel">smtp_tls_loglevel</a>
+(default: 0)</b></DT><DD>
+
+<p> Enable additional Postfix SMTP client logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.  </p>
+
+<dl compact>
+
+<dt> </dt> <dd> 0 Disable logging of TLS activity. </dd>
+
+<dt> </dt> <dd> 1 Log TLS handshake and certificate information. </dd>
+
+<dt> </dt> <dd> 2 Log levels during TLS negotiation. </dd>
+
+<dt> </dt> <dd> 3 Log hexadecimal and ASCII dump of TLS negotiation
+process.  </dd>
+
+<dt> </dt> <dd> 4 Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS. </dd>
+
+</dl>
+
+<p> Use "<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a>
+(default: no)</b></DT><DD>
+
+<p> Log the hostname of a remote SMTP server that offers STARTTLS,
+when TLS is not already enabled for that server. </p>
+
+<p> The logfile record looks like:  </p>
+
+<pre>
+postfix/smtp[pid]:  Host offered STARTTLS: [name.of.host]
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_per_site">smtp_tls_per_site</a>
+(default: empty)</b></DT><DD>
+
+<p> Optional lookup tables with the Postfix SMTP client TLS usage
+policy by next-hop domain name and by remote SMTP server hostname.
+</p>
+
+<p> Table format:  domain names or server hostnames are specified
+on the left-hand side; no wildcards are allowed.  On the right hand
+side specify one of the following keywords:  </p>
+
+<dl>
+
+<dt> NONE </dt> <dd>Don't use TLS at all. </dd>
+
+<dt> MAY </dt> <dd>Try to use STARTTLS if offered, otherwise use
+the unencrypted connection. NOTE: STARTTLS can be used only if
+TLS is already enabled via main.cf, so that the client TLS engine
+is properly initialized at program startup. </dd>
+
+<dt> MUST </dt> <dd>Require usage of STARTTLS, require that the
+remote SMTP server hostname matches the information in the remote
+SMTP server certificate, and require that the remote SMTP server
+certificate was issued by a trusted CA. </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd>Require usage of STARTTLS, but do
+not require that the remote SMTP server hostname matches the
+information in the remote SMTP server certificate, or that the
+server certificate was issued by a trusted CA. </dd>
+
+</dl>
+
+<p> Special hint for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:  specify local
+<a href="transport.5.html">transport(5)</a> table entries for sensitive domains with explicit
+<a href="smtp.8.html">smtp</a>:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a>
+(default: 5)</b></DT><DD>
+
+<p> The verification depth for remote SMTP server certificates. A
+depth of 1 is sufficient, if the certificate is directly issued by
+a CA listed in the CA files.  The default value (5) should suffice
+for longer chains (the root CA issues special CA which then issues
+the actual certificate...). </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_session_cache_database">smtp_tls_session_cache_database</a>
+(default: empty)</b></DT><DD>
+
+<p> Name of the file containing the optional Postfix SMTP client
+TLS session cache. Specify a database type that supports enumeration,
+such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+concurrent access.  The file is created if it does not exist.  </p>
+
+<p> NOTE: <b>dbm</b> databases are not suitable. TLS
+session objects are too large. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = btree:/var/postfix/smtp_scache
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a>
+(default: 3600s)</b></DT><DD>
+
+<p> The expiration time of Postfix SMTP client TLS session cache
+information.  A cache cleanup is performed periodically every
+$<a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> seconds.  </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_use_tls">smtp_use_tls</a>
+(default: no)</b></DT><DD>
+
+<p> Opportunistic mode: use TLS when a remote SMTP server announces
+STARTTLS support, otherwise send the mail in the clear. Beware:
+some SMTP servers offer STARTTLS even if it is not configured.  If
+the TLS handshake fails, and no other server is available, delivery
+is deferred and mail stays in the queue.  If this is a concern for
+you, use the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> feature instead.  </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_xforward_timeout">smtp_xforward_timeout</a>
@@ -6646,6 +7006,19 @@ network or network address listed in  $<a href="postconf.5.html#mynetworks">myne
 <dd> Permit the request when the client is successfully
 authenticated via the <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH) protocol. </dd>
 
+<dt><b><a name="permit_tls_all_clientcerts">permit_tls_all_clientcerts</a></b></dt>
+
+<dd> Permit the request when the remote SMTP client certificate is
+verified successfully.  This option must be used only if a special
+CA issues the certificates and only this CA is listed as trusted
+CA, otherwise all clients with a recognized certificate would be
+allowed to relay.  </dd>
+
+<dt><b><a name="permit_tls_clientcerts">permit_tls_clientcerts</a></b></dt>
+
+<dd>Permit the request when the remote SMTP client certificate is
+verified successfully, and the certificate fingerprint is listed
+in $relay_clientcerts. </dd>
 <dt><b><a name="reject_rbl_client">reject_rbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
 
 <dd>Reject the request when the reversed client network address is
@@ -6897,6 +7270,24 @@ applies in the context of the SMTP END-OF-DATA command. </p>
 <p> See <a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> for syntax details. </p>
 
 
+</DD>
+
+<DT><b><a name="smtpd_enforce_tls">smtpd_enforce_tls</a>
+(default: no)</b></DT><DD>
+
+<p> Enforcement mode: announce STARTTLS support to SMTP clients,
+and require that clients use TLS encryption.  According to <a href="http://www.faqs.org/rfcs/rfc2487.html">RFC 2487</a>
+this MUST NOT be applied in case of a publicly-referenced SMTP
+server.  This option is off by default and should be used only on
+dedicated servers. </p>
+
+<p> Note 1: this mode implies "<a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> = yes". </p>
+
+<p> Note 2: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private
+key. This is intended behavior. </p>
+
+
 </DD>
 
 <DT><b><a name="smtpd_error_sleep_time">smtpd_error_sleep_time</a>
@@ -7776,6 +8167,15 @@ Example:
 </pre>
 
 
+</DD>
+
+<DT><b><a name="smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a>
+(default: $<a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_security_options</a>)</b></DT><DD>
+
+<p> The SASL authentication security options that the Postfix SMTP
+server uses for TLS encrypted SMTP sessions. </p>
+
+
 </DD>
 
 <DT><b><a name="smtpd_sender_login_maps">smtpd_sender_login_maps</a>
@@ -7988,6 +8388,15 @@ server delays all responses by (number of errors) seconds. </p>
 </ul>
 
 
+</DD>
+
+<DT><b><a name="smtpd_starttls_timeout">smtpd_starttls_timeout</a>
+(default: 300s)</b></DT><DD>
+
+<p> The time limit for Postfix SMTP server write and read operations
+during TLS startup and shutdown handshake procedures. </p>
+
+
 </DD>
 
 <DT><b><a name="smtpd_timeout">smtpd_timeout</a>
@@ -8009,6 +8418,339 @@ The default time unit is s (seconds).
 </p>
 
 
+</DD>
+
+<DT><b><a name="smtpd_tls_CAfile">smtpd_tls_CAfile</a>
+(default: empty)</b></DT><DD>
+
+<p> The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP server certificate.  This is
+needed only when the CA certificate is not already present in the
+server certificate file.  This file may also contain the CA
+certificates of other trusted CAs.  You must use this file for the
+list of trusted CAs if you want to use chroot-mode. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> = /etc/postfix/CAcert.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_CApath">smtpd_tls_CApath</a>
+(default: empty)</b></DT><DD>
+
+<p> Directory with PEM format certificate authority certificates
+that the Postfix SMTP server offers to remote SMTP clients for the
+purpose of client certificate verification.  Do not forget to create
+the necessary "hash" links with, for example, "$OPENSSL_HOME/bin/c_rehash
+/etc/postfix/certs".  </p>
+
+<p> To use this option in chroot mode, this directory (or a copy)
+must be inside the chroot jail. Please note that in this case the
+CA certificates are not offered to the client, so that e.g.  Netscape
+clients might not offer certificates issued by them.  Use of this
+feature is therefore not recommended. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_CApath">smtpd_tls_CApath</a> = /etc/postfix/certs
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>
+(default: no)</b></DT><DD>
+
+<p> Ask a remote SMTP client for a client certificate. This
+information is needed for certificate based mail relaying with,
+for example, the <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a> feature. </p>
+
+<p> Some clients such as Netscape will either complain if no
+certificate is available (for the list of CAs in /etc/postfix/certs)
+or will offer multiple client certificates to choose from. This
+may be annoying, so this option is "off" by default. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_auth_only">smtpd_tls_auth_only</a>
+(default: no)</b></DT><DD>
+
+<p> When TLS encryption is optional in the Postfix SMTP server, do
+not announce or accept SASL authentication over unencrypted
+connections. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a>
+(default: 5)</b></DT><DD>
+
+<p> The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file.  The default value should also suffice for longer chains (the
+root CA issues special CA which then issues the actual certificate...).
+</p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_cert_file">smtpd_tls_cert_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with the Postfix SMTP server RSA certificate in PEM format.
+This file may also contain the server private key. </p>
+
+<p> Both RSA and DSA certificates are supported.  When both types
+are present, the cipher used determines which certificate will be
+presented to the client.  For Netscape and OpenSSL clients without
+special cipher choices the RSA certificate is preferred. </p>
+
+<p> In order to verify a certificate, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s).  </p>
+
+<p> Example: the certificate for "server.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the server.pem file with "cat server_cert.pem intermediate_CA.pem
+root_CA.pem &gt; server.pem". </p>
+
+<p> If you want to accept certificates issued by these CAs yourself,
+you can also add the CA certificates to the <a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a>, in
+which case it is not necessary to have them in the <a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>
+or <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. </p>
+
+<p> A certificate supplied here must be usable as SSL server
+certificate and hence pass the "openssl verify -purpose sslserver
+..." test. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> = /etc/postfix/server.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_cipherlist">smtpd_tls_cipherlist</a>
+(default: empty)</b></DT><DD>
+
+<p> Controls the Postfix SMTP server TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with the Postfix SMTP server DSA certificate in PEM format.
+This file may also contain the server private key. <p>
+
+<p> See the discussion under <a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> for more details.
+</p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> = /etc/postfix/server-dsa.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers. </p>
+
+<p> Instead of using the exact same parameter sets as distributed
+with other TLS packages, it is more secure to generate your own
+set of parameters with something like the following command:  </p>
+
+<pre>
+openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
+</pre>
+
+<p> Your actual source for entropy may differ. Some systems have
+/dev/random; on other system you may consider using the "Entropy
+Gathering Daemon EGD", available at <a href="http://www.lothar.com/tech/crypto/">http://www.lothar.com/tech/crypto/</a>.
+</p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh_1024.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>
+(default: empty)</b></DT><DD>
+
+<p> File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers. </p>
+
+<p> See also the discussion under the <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>
+configuration parameter.  </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = /etc/postfix/dh_512.pem
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix SMTP server DSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_key_file">smtpd_tls_key_file</a>
+(default: $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b></DT><DD>
+
+<p> File with the Postfix SMTP server RSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_loglevel">smtpd_tls_loglevel</a>
+(default: 0)</b></DT><DD>
+
+<p> Enable additional Postfix SMTP server logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.  </p>
+
+<dl compact>
+
+<dt> </dt> <dd> 0 Disable logging of TLS activity. </dd>
+
+<dt> </dt> <dd> 1 Log TLS handshake and certificate information. </dd>
+
+<dt> </dt> <dd> 2 Log levels during TLS negotiation. </dd>
+
+<dt> </dt> <dd> 3 Log hexadecimal and ASCII dump of TLS negotiation
+process.  </dd>
+
+<dt> </dt> <dd> 4 Also log hexadecimal and ASCII dump of complete
+transmission after STARTTLS. </dd>
+
+</dl>
+
+<p> Use "<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_received_header">smtpd_tls_received_header</a>
+(default: no)</b></DT><DD>
+
+<p> Request that the Postfix SMTP server produces Received:  message
+headers that include information about the protocol and cipher used,
+as well as the client CommonName and client certificate issuer
+CommonName.  This is disabled by default, as the information may
+be modified in transit through other mail servers.  Only information
+that was recorded by the final destination can be trusted. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_req_ccert">smtpd_tls_req_ccert</a>
+(default: no)</b></DT><DD>
+
+<p> When TLS encryption is enforced, require a remote SMTP client
+certificate in order to allow TLS connections to proceed.  This
+option implies "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> = yes". </p>
+
+<p> When TLS encryption is optional, remote SMTP clients can bypass
+the restriction by simply not using STARTTLS at all. For this reason
+a TLS connection will be handled as if only "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>
+= yes" is specified.  </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a>
+(default: empty)</b></DT><DD>
+
+<p> Name of the file containing the optional Postfix SMTP server
+TLS session cache. Specify a database type that supports enumeration,
+such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+concurrent access.  The file is created if it does not exist.  </p>
+
+<p> NOTE: <b>dbm</b> databases are not suitable. TLS
+session objects are too large. </p>
+
+<p> Example: </p>
+
+<pre>
+<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = btree:/var/postfix/smtpd_scache
+</pre>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a>
+(default: 3600s)</b></DT><DD>
+
+<p> The expiration time of Postfix SMTP server TLS session cache
+information.  A cache cleanup is performed periodically every
+$<a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> seconds.  </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_tls_wrappermode">smtpd_tls_wrappermode</a>
+(default: no)</b></DT><DD>
+
+<p> Run the Postfix SMTP server in the non-standard "wrapper" mode,
+instead of using the STARTTLS command. </p>
+
+<p> If you want to support this service, enable a special port in
+master.cf, and specify "-o <a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a>=yes" on the SMTP
+server's command line. Port 465 (smtps) was once chosen for this
+purpose. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_use_tls">smtpd_use_tls</a>
+(default: no)</b></DT><DD>
+
+<p> Opportunistic mode: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. </p>
+
+<p> Note: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private
+key. This is intended behavior. </p>
+
+
 </DD>
 
 <DT><b><a name="soft_bounce">soft_bounce</a>
@@ -8221,6 +8963,78 @@ while accessing the Postfix main.cf configuration file.
 </p>
 
 
+</DD>
+
+<DT><b><a name="tls_daemon_random_bytes">tls_daemon_random_bytes</a>
+(default: 32)</b></DT><DD>
+
+<p> The number of pseudo-random bytes that an <a href="smtp.8.html">smtp(8)</a> or <a href="smtpd.8.html">smtpd(8)</a>
+process requests from the <a href="tlsmgr.8.html">tlsmgr(8)</a> server in order to seed its
+internal pseudo random number generator (PRNG).  The default of 32
+bytes (equivalent to 256 bits) is sufficient to generate a 128bit
+(or 168bit) session key. </p>
+
+
+</DD>
+
+<DT><b><a name="tls_random_bytes">tls_random_bytes</a>
+(default: 32)</b></DT><DD>
+
+<p> The number of bytes that <a href="tlsmgr.8.html">tlsmgr(8)</a> reads from $<a href="postconf.5.html#tls_random_source">tls_random_source</a>
+when (re)seeding the in-memory pseudo random number generator (PRNG)
+pool. The default of 32 bytes (256 bits) is good enough for 128bit
+symmetric keys.  If using EGD or a device file, a maximum of 255
+bytes is read. </p>
+
+
+</DD>
+
+<DT><b><a name="tls_random_exchange_name">tls_random_exchange_name</a>
+(default: ${<a href="postconf.5.html#config_directory">config_directory</a>}/prng_exch)</b></DT><DD>
+
+<p> Name of the pseudo random number generator (PRNG) state file
+that is maintained by <a href="tlsmgr.8.html">tlsmgr(8)</a>. The file is created when it does
+not exist, and its length is fixed at 1024 bytes.  </p>
+
+<p> Since this file is modified by Postfix, it should probably be
+kept in the /var file system, instead of under $<a href="postconf.5.html#config_directory">config_directory</a>.
+The location should not be inside the chroot jail. </p>
+
+
+</DD>
+
+<DT><b><a name="tls_random_prng_update_period">tls_random_prng_update_period</a>
+(default: 3600s)</b></DT><DD>
+
+<p> The time between attempts by <a href="tlsmgr.8.html">tlsmgr(8)</a> to save the state of
+the pseudo random number generator (PRNG) to the file specified
+with $<a href="postconf.5.html#tls_random_exchange_name">tls_random_exchange_name</a>.  </p>
+
+
+</DD>
+
+<DT><b><a name="tls_random_reseed_period">tls_random_reseed_period</a>
+(default: 3600s)</b></DT><DD>
+
+<p> The maximal time between attempts by <a href="tlsmgr.8.html">tlsmgr(8)</a> to re-seed the
+in-memory pseudo random number generator (PRNG) pool from external
+sources.  The actual time between re-seeding attempts is calculated
+using the PRNG, and is between 0 and the time specified.  </p>
+
+
+</DD>
+
+<DT><b><a name="tls_random_source">tls_random_source</a>
+(default: see "postconf -d" output)</b></DT><DD>
+
+<p> The external entropy source for the in-memory <a href="tlsmgr.8.html">tlsmgr(8)</a> pseudo
+random number generator (PRNG) pool. Be sure to specify a non-blocking
+source.  If this source is not a regular file, the entropy source
+type must be prepended:  egd:/path/to/egd_socket for a source with
+EGD compatible socket interface, or dev:/path/to/device for a
+device file.  </p>
+
+
 </DD>
 
 <DT><b><a name="trace_service_name">trace_service_name</a>
index c73b363691223980db248e91b6fcaa9ece23219a..0c957a5081529caa036583f49500d99907144ac0 100644 (file)
@@ -198,6 +198,8 @@ the following convention:  </p>
 
 <li> <a href="spawn.8.html">spawn(8)</a>, run non-Postfix server 
 
+<li> <a href="tlsmgr.8.html">tlsmgr(8)</a>, Postfix TLS cache and randomness manager 
+
 <li> <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, Postfix address rewriting 
 
 <li> <a href="verify.8.html">verify(8)</a>, Postfix address verification 
index aacc67fcf3a4650333002731885e5d78f79b3c19..977ff99882cebd40b3a90b457e6fdcebefe92180 100644 (file)
@@ -249,6 +249,7 @@ POSTFIX(1)                                             POSTFIX(1)
        <a href="smtp.8.html">smtp(8)</a>, Postfix SMTP client
        <a href="smtpd.8.html">smtpd(8)</a>, Postfix SMTP server
        <a href="spawn.8.html">spawn(8)</a>, run non-Postfix server
+       <a href="tlsmgr.8.html">tlsmgr(8)</a>, Postfix TLS cache and randomness manager
        <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, Postfix address rewriting
        <a href="verify.8.html">verify(8)</a>, Postfix address verification
        <a href="virtual.8.html">virtual(8)</a>, Postfix virtual delivery agent
index de553093b05925f5d338fd1e9f6966451b855425..708da272d2627a3bb1f05c1ae499ce816af970cb 100644 (file)
@@ -60,6 +60,7 @@ SMTP(8)                                                   SMTP(8)
        <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
        <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> (SMTP protocol)
        <a href="http://www.faqs.org/rfcs/rfc2920.html">RFC 2920</a> (SMTP Pipelining)
+       <a href="http://www.faqs.org/rfcs/rfc3207.html">RFC 3207</a> (STARTTLS command)
 
 <b>DIAGNOSTICS</b>
        Problems  and transactions are logged to <b>syslogd</b>(8).  Cor-
@@ -192,26 +193,118 @@ SMTP(8)                                                   SMTP(8)
               remote  SMTP  server's  list of offered SASL mecha-
               nisms.
 
+<b>STARTTLS SUPPORT CONTROLS</b>
+       Detailed information about STARTTLS configuration  may  be
+       found in the <a href="TLS_README.html">TLS_README</a> document.
+
+       <b><a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> (no)</b>
+              Opportunistic  mode:  use  TLS  when  a remote SMTP
+              server announces STARTTLS support,  otherwise  send
+              the mail in the clear.
+
+       <b><a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> (no)</b>
+              Enforcement  mode: require that remote SMTP servers
+              use TLS encryption, and  never  send  mail  in  the
+              clear.
+
+       <b><a href="postconf.5.html#smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>           ($<a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_secu</a>-</b>
+       <b><a href="postconf.5.html#smtp_sasl_security_options">rity_options</a>)</b>
+              The  SASL  authentication security options that the
+              Postfix SMTP client uses  for  TLS  encrypted  SMTP
+              sessions.
+
+       <b><a href="postconf.5.html#smtp_starttls_timeout">smtp_starttls_timeout</a> (300s)</b>
+              Time  limit  for Postfix SMTP client write and read
+              operations during TLS startup  and  shutdown  hand-
+              shake procedures.
+
+       <b><a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> (empty)</b>
+              The  file with the certificate of the certification
+              authority (CA) that issued the Postfix SMTP  client
+              certificate.
+
+       <b><a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> (empty)</b>
+              Directory  with  PEM  format  certificate authority
+              certificates that the Postfix SMTP client  uses  to
+              verify a remote SMTP server certificate.
+
+       <b><a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> (empty)</b>
+              File  with  the Postfix SMTP client RSA certificate
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> (empty)</b>
+              Controls the Postfix SMTP client TLS cipher  selec-
+              tion scheme.
+
+       <b><a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> (empty)</b>
+              File  with  the Postfix SMTP client DSA certificate
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> ($<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b>
+              File with the Postfix SMTP client DSA  private  key
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> (yes)</b>
+              When  TLS  encryption is enforced, require that the
+              remote SMTP server hostname matches the information
+              in the remote SMTP server certificate.
+
+       <b><a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> ($<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b>
+              File  with  the Postfix SMTP client RSA private key
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> (0)</b>
+              Enable additional Postfix SMTP  client  logging  of
+              TLS activity.
+
+       <b><a href="postconf.5.html#smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a> (no)</b>
+              Log  the  hostname  of  a  remote  SMTP server that
+              offers STARTTLS, when TLS is  not  already  enabled
+              for that server.
+
+       <b><a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> (empty)</b>
+              Optional lookup tables with the Postfix SMTP client
+              TLS usage policy by next-hop  domain  name  and  by
+              remote SMTP server hostname.
+
+       <b><a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a> (5)</b>
+              The  verification depth for remote SMTP server cer-
+              tificates.
+
+       <b><a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> (empty)</b>
+              Name of the file containing  the  optional  Postfix
+              SMTP client TLS session cache.
+
+       <b><a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> (3600s)</b>
+              The expiration time of Postfix SMTP client TLS ses-
+              sion cache information.
+
+       <b><a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> (32)</b>
+              The number of pseudo-random bytes that  an  <a href="smtp.8.html">smtp(8)</a>
+              or  <a href="smtpd.8.html">smtpd(8)</a>  process  requests  from the <a href="tlsmgr.8.html">tlsmgr(8)</a>
+              server in order to seed its internal pseudo  random
+              number generator (PRNG).
+
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#smtp_destination_concurrency_limit">smtp_destination_concurrency_limit</a>      ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destina</a>-</b>
        <b><a href="postconf.5.html#default_destination_concurrency_limit">tion_concurrency_limit</a>)</b>
-              The maximal number of parallel  deliveries  to  the
-              same  destination  via  the  smtp  message delivery
+              The  maximal  number  of parallel deliveries to the
+              same destination  via  the  smtp  message  delivery
               transport.
 
        <b><a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a>        ($<a href="postconf.5.html#default_destination_recipient_limit">default_destina</a>-</b>
        <b><a href="postconf.5.html#default_destination_recipient_limit">tion_recipient_limit</a>)</b>
-              The maximal number of recipients per  delivery  via
+              The  maximal  number of recipients per delivery via
               the smtp message delivery transport.
 
        <b><a href="postconf.5.html#smtp_connect_timeout">smtp_connect_timeout</a> (30s)</b>
-              The  SMTP  client  time  limit for completing a TCP
+              The SMTP client time limit  for  completing  a  TCP
               connection,  or  zero  (use  the  operating  system
               built-in time limit).
 
        <b><a href="postconf.5.html#smtp_helo_timeout">smtp_helo_timeout</a> (300s)</b>
-              The  SMTP client time limit for sending the HELO or
-              EHLO command, and for receiving the initial  server
+              The SMTP client time limit for sending the HELO  or
+              EHLO  command, and for receiving the initial server
               response.
 
        <b><a href="postconf.5.html#smtp_xforward_timeout">smtp_xforward_timeout</a> (300s)</b>
@@ -219,30 +312,30 @@ SMTP(8)                                                   SMTP(8)
               command, and for receiving the server response.
 
        <b><a href="postconf.5.html#smtp_mail_timeout">smtp_mail_timeout</a> (300s)</b>
-              The SMTP client time limit  for  sending  the  MAIL
-              FROM   command,   and   for  receiving  the  server
+              The  SMTP  client  time  limit for sending the MAIL
+              FROM  command,  and  for   receiving   the   server
               response.
 
        <b><a href="postconf.5.html#smtp_rcpt_timeout">smtp_rcpt_timeout</a> (300s)</b>
-              The SMTP client time limit  for  sending  the  SMTP
-              RCPT  TO  command,  and  for  receiving  the server
+              The  SMTP  client  time  limit for sending the SMTP
+              RCPT TO  command,  and  for  receiving  the  server
               response.
 
        <b><a href="postconf.5.html#smtp_data_init_timeout">smtp_data_init_timeout</a> (120s)</b>
-              The SMTP client time limit  for  sending  the  SMTP
-              DATA   command,   and   for  receiving  the  server
+              The  SMTP  client  time  limit for sending the SMTP
+              DATA  command,  and  for   receiving   the   server
               response.
 
        <b><a href="postconf.5.html#smtp_data_xfer_timeout">smtp_data_xfer_timeout</a> (180s)</b>
-              The SMTP client time limit  for  sending  the  SMTP
+              The  SMTP  client  time  limit for sending the SMTP
               message content.
 
        <b><a href="postconf.5.html#smtp_data_done_timeout">smtp_data_done_timeout</a> (600s)</b>
-              The  SMTP  client  time  limit for sending the SMTP
+              The SMTP client time limit  for  sending  the  SMTP
               ".", and for receiving the server response.
 
        <b><a href="postconf.5.html#smtp_quit_timeout">smtp_quit_timeout</a> (300s)</b>
-              The SMTP client time limit  for  sending  the  QUIT
+              The  SMTP  client  time  limit for sending the QUIT
               command, and for receiving the server response.
 
        Available in Postfix version 2.1 and later:
@@ -253,77 +346,77 @@ SMTP(8)                                                   SMTP(8)
               lookups, or zero (no limit).
 
        <b><a href="postconf.5.html#smtp_mx_session_limit">smtp_mx_session_limit</a> (2)</b>
-              The  maximal  number  of SMTP sessions per delivery
-              request before giving up or delivering to  a  fall-
+              The maximal number of SMTP  sessions  per  delivery
+              request  before  giving up or delivering to a fall-
               back relay host, or zero (no limit).
 
        <b><a href="postconf.5.html#smtp_rset_timeout">smtp_rset_timeout</a> (20s)</b>
-              The  SMTP  client  time  limit for sending the RSET
+              The SMTP client time limit  for  sending  the  RSET
               command, and for receiving the server response.
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#smtp_connection_cache_destinations">smtp_connection_cache_destinations</a> (empty)</b>
-              Permanently enable SMTP connection caching for  the
+              Permanently  enable SMTP connection caching for the
               specified destinations.
 
        <b><a href="postconf.5.html#smtp_connection_cache_on_demand">smtp_connection_cache_on_demand</a> (yes)</b>
-              Temporarily  enable SMTP connection caching while a
+              Temporarily enable SMTP connection caching while  a
               destination has a high volume of mail in the active
               queue.
 
        <b><a href="postconf.5.html#smtp_connection_cache_reuse_limit">smtp_connection_cache_reuse_limit</a> (10)</b>
               When SMTP connection caching is enabled, the number
-              of times that an SMTP session is reused  before  it
+              of  times  that an SMTP session is reused before it
               is closed.
 
        <b><a href="postconf.5.html#smtp_connection_cache_time_limit">smtp_connection_cache_time_limit</a> (2s)</b>
               When SMTP connection caching is enabled, the amount
-              of time that an unused SMTP client socket  is  kept
+              of  time  that an unused SMTP client socket is kept
               open before it is closed.
 
 <b>TROUBLE SHOOTING CONTROLS</b>
        <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
-              The  increment  in  verbose  logging  level  when a
-              remote client or server matches a  pattern  in  the
+              The increment  in  verbose  logging  level  when  a
+              remote  client  or  server matches a pattern in the
               <a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
 
        <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
-              Optional  list  of remote client or server hostname
-              or network address patterns that cause the  verbose
-              logging  level  to increase by the amount specified
+              Optional list of remote client or  server  hostname
+              or  network address patterns that cause the verbose
+              logging level to increase by the  amount  specified
               in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
 
        <b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
-              The recipient  of  postmaster  notifications  about
-              mail  delivery  problems that are caused by policy,
+              The  recipient  of  postmaster  notifications about
+              mail delivery problems that are caused  by  policy,
               resource, software or protocol errors.
 
        <b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
-              The list of error classes that are reported to  the
+              The  list of error classes that are reported to the
               postmaster.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#best_mx_transport">best_mx_transport</a> (empty)</b>
-              Where  the  Postfix SMTP client should deliver mail
+              Where the Postfix SMTP client should  deliver  mail
               when it detects a "mail loops back to myself" error
               condition.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
+              The default location of  the  Postfix  main.cf  and
               master.cf configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How much time a Postfix daemon process may take  to
-              handle  a  request  before  it  is  terminated by a
+              How  much time a Postfix daemon process may take to
+              handle a request  before  it  is  terminated  by  a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#disable_dns_lookups">disable_dns_lookups</a> (no)</b>
-              Disable DNS lookups in the Postfix  SMTP  and  LMTP
+              Disable  DNS  lookups  in the Postfix SMTP and LMTP
               clients.
 
        <b><a href="postconf.5.html#fallback_relay">fallback_relay</a> (empty)</b>
-              Optional  list of relay hosts for SMTP destinations
+              Optional list of relay hosts for SMTP  destinations
               that can't be found or that are unreachable.
 
        <b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
@@ -331,7 +424,7 @@ SMTP(8)                                                   SMTP(8)
               tem receives mail on.
 
        <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
-              The  Internet protocols Postfix will attempt to use
+              The Internet protocols Postfix will attempt to  use
               when making or accepting connections.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -339,54 +432,54 @@ SMTP(8)                                                   SMTP(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits for the next  service  request
+              The maximum amount of time  that  an  idle  Postfix
+              daemon  process  waits for the next service request
               before exiting.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The  maximal number of connection requests before a
+              The maximal number of connection requests before  a
               Postfix daemon process terminates.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID of a Postfix command or daemon  pro-
+              The  process ID of a Postfix command or daemon pro-
               cess.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
               The network interface addresses that this mail sys-
-              tem  receives  mail on by way of a proxy or network
+              tem receives mail on by way of a proxy  or  network
               address translation unit.
 
        <b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
               An optional numerical network address that the SMTP
-              client  should  bind to when making an IPv4 connec-
+              client should bind to when making an  IPv4  connec-
               tion.
 
        <b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
               An optional numerical network address that the SMTP
-              client  should  bind to when making an IPv6 connec-
+              client should bind to when making an  IPv6  connec-
               tion.
 
        <b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              The hostname to send in the SMTP EHLO or HELO  com-
+              The  hostname to send in the SMTP EHLO or HELO com-
               mand.
 
        <b><a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a> (dns)</b>
-              What  mechanisms  when the SMTP client uses to look
+              What mechanisms when the SMTP client uses  to  look
               up a host's IP address.
 
        <b><a href="postconf.5.html#smtp_randomize_addresses">smtp_randomize_addresses</a> (yes)</b>
-              Randomize the order  of  equal-preference  MX  host
+              Randomize  the  order  of  equal-preference MX host
               addresses.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The  mail system name that is prepended to the pro-
+              The mail system name that is prepended to the  pro-
               cess  name  in  syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
@@ -397,13 +490,15 @@ SMTP(8)                                                   SMTP(8)
        <a href="postconf.5.html">postconf(5)</a>, configuration parameters
        <a href="master.5.html">master(5)</a>, generic daemon options
        <a href="master.8.html">master(8)</a>, process manager
+       <a href="tlsmgr.8.html">tlsmgr(8)</a>, TLS session and PRNG management
        syslogd(8), system logging
 
 <b>README FILES</b>
        <a href="SASL_README.html">SASL_README</a>, Postfix SASL howto
+       <a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
@@ -424,5 +519,12 @@ SMTP(8)                                                   SMTP(8)
        Victor Duchovni
        Morgan Stanley
 
+       TLS support originally by:
+       Lutz Jaenicke
+       BTU Cottbus
+       Allgemeine Elektrotechnik
+       Universitaetsplatz 3-4
+       D-03044 Cottbus, Germany
+
                                                           SMTP(8)
 </pre> </body> </html>
index 112cb5ef79d4a1b91a9f659e44937efaec9e23f4..6a23546dfdf54ef7a7b3a08c37cd978eab704efa 100644 (file)
@@ -46,6 +46,7 @@ SMTPD(8)                                                 SMTPD(8)
        <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
        <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> (SMTP protocol)
        <a href="http://www.faqs.org/rfcs/rfc2920.html">RFC 2920</a> (SMTP Pipelining)
+       <a href="http://www.faqs.org/rfcs/rfc3207.html">RFC 3207</a> (STARTTLS command)
 
 <b>DIAGNOSTICS</b>
        Problems and transactions are logged to <b>syslogd</b>(8).
@@ -222,6 +223,116 @@ SMTPD(8)                                                 SMTPD(8)
               What SMTP clients Postfix will not offer AUTH  sup-
               port to.
 
+<b>STARTTLS SUPPORT CONTROLS</b>
+       Detailed  information  about STARTTLS configuration may be
+       found in the <a href="TLS_README.html">TLS_README</a> document.
+
+       <b><a href="postconf.5.html#smtpd_use_tls">smtpd_use_tls</a> (no)</b>
+              Opportunistic mode: announce  STARTTLS  support  to
+              SMTP  clients,  but do not require that clients use
+              TLS encryption.
+
+       <b><a href="postconf.5.html#smtpd_enforce_tls">smtpd_enforce_tls</a> (no)</b>
+              Enforcement mode: announce STARTTLS support to SMTP
+              clients,  and  require that clients use TLS encryp-
+              tion.
+
+       <b><a href="postconf.5.html#smtpd_sasl_tls_security_options">smtpd_sasl_tls_security_options</a>         ($<a href="postconf.5.html#smtpd_sasl_security_options">smtpd_sasl_secu</a>-</b>
+       <b><a href="postconf.5.html#smtpd_sasl_security_options">rity_options</a>)</b>
+              The SASL authentication security options  that  the
+              Postfix  SMTP  server  uses  for TLS encrypted SMTP
+              sessions.
+
+       <b><a href="postconf.5.html#smtpd_starttls_timeout">smtpd_starttls_timeout</a> (300s)</b>
+              The time limit for Postfix SMTP  server  write  and
+              read  operations  during  TLS  startup and shutdown
+              handshake procedures.
+
+       <b><a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> (empty)</b>
+              The file with the certificate of the  certification
+              authority  (CA) that issued the Postfix SMTP server
+              certificate.
+
+       <b><a href="postconf.5.html#smtpd_tls_CAfile">smtpd_tls_CAfile</a> (empty)</b>
+              The file with the certificate of the  certification
+              authority  (CA) that issued the Postfix SMTP server
+              certificate.
+
+       <b><a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> (no)</b>
+              Ask a remote SMTP client for a client  certificate.
+
+       <b><a href="postconf.5.html#smtpd_tls_auth_only">smtpd_tls_auth_only</a> (no)</b>
+              When TLS encryption is optional in the Postfix SMTP
+              server, do not announce or accept SASL  authentica-
+              tion over unencrypted connections.
+
+       <b><a href="postconf.5.html#smtpd_tls_ccert_verifydepth">smtpd_tls_ccert_verifydepth</a> (5)</b>
+              The  verification depth for remote SMTP client cer-
+              tificates.
+
+       <b><a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a> (empty)</b>
+              File with the Postfix SMTP server  RSA  certificate
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtpd_tls_cipherlist">smtpd_tls_cipherlist</a> (empty)</b>
+              Controls  the Postfix SMTP server TLS cipher selec-
+              tion scheme.
+
+       <b><a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a> (empty)</b>
+              File with the Postfix SMTP server  DSA  certificate
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> (empty)</b>
+              File  with  DH  parameters  that  the  Postfix SMTP
+              server should use with EDH ciphers.
+
+       <b><a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> (empty)</b>
+              File with  DH  parameters  that  the  Postfix  SMTP
+              server should use with EDH ciphers.
+
+       <b><a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
+              File  with  the Postfix SMTP server DSA private key
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtpd_tls_key_file">smtpd_tls_key_file</a> ($<a href="postconf.5.html#smtpd_tls_cert_file">smtpd_tls_cert_file</a>)</b>
+              File with the Postfix SMTP server RSA  private  key
+              in PEM format.
+
+       <b><a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> (0)</b>
+              Enable  additional  Postfix  SMTP server logging of
+              TLS activity.
+
+       <b><a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> (no)</b>
+              Request  that  the  Postfix  SMTP  server  produces
+              Received:  message headers that include information
+              about the protocol and cipher used, as well as  the
+              client  CommonName  and  client  certificate issuer
+              CommonName.
+
+       <b><a href="postconf.5.html#smtpd_tls_req_ccert">smtpd_tls_req_ccert</a> (no)</b>
+              When TLS encryption is enforced, require  a  remote
+              SMTP  client certificate in order to allow TLS con-
+              nections to proceed.
+
+       <b><a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> (empty)</b>
+              Name of the file containing  the  optional  Postfix
+              SMTP server TLS session cache.
+
+       <b><a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> (3600s)</b>
+              The expiration time of Postfix SMTP server TLS ses-
+              sion cache information.
+
+       <b><a href="postconf.5.html#smtpd_tls_wrappermode">smtpd_tls_wrappermode</a> (no)</b>
+              Run the Postfix SMTP  server  in  the  non-standard
+              "wrapper"  mode, instead of using the STARTTLS com-
+              mand.
+
+       <b><a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> (32)</b>
+              The number of pseudo-random bytes that  an  <a href="smtp.8.html">smtp(8)</a>
+              or  <a href="smtpd.8.html">smtpd(8)</a>  process  requests  from the <a href="tlsmgr.8.html">tlsmgr(8)</a>
+              server in order to seed its internal pseudo  random
+              number generator (PRNG).
+
 <b>VERP SUPPORT CONTROLS</b>
        With  VERP  style  delivery,  each  recipient of a message
        receives a customized copy of the message with his/her own
@@ -809,6 +920,7 @@ SMTPD(8)                                                 SMTPD(8)
 <b>SEE ALSO</b>
        <a href="anvil.8.html">anvil(8)</a>, connection/rate limiting
        <a href="cleanup.8.html">cleanup(8)</a>, message canonicalization
+       <a href="tlsmgr.8.html">tlsmgr(8)</a>, TLS session and PRNG management
        <a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, address resolver
        <a href="verify.8.html">verify(8)</a>, address verification service
        <a href="postconf.5.html">postconf(5)</a>, configuration parameters
@@ -825,6 +937,7 @@ SMTPD(8)                                                 SMTPD(8)
        <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a>, external policy server
        <a href="SMTPD_PROXY_README.html">SMTPD_PROXY_README</a>, external before-queue content filter
        <a href="SASL_README.html">SASL_README</a>, Postfix SASL howto
+       <a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
        <a href="VERP_README.html">VERP_README</a>, Postfix XVERP extension
        <a href="XCLIENT_README.html">XCLIENT_README</a>, Postfix XCLIENT extension
        <a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
@@ -839,5 +952,12 @@ SMTPD(8)                                                 SMTPD(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
+       TLS support originally by:
+       Lutz Jaenicke
+       BTU Cottbus
+       Allgemeine Elektrotechnik
+       Universitaetsplatz 3-4
+       D-03044 Cottbus, Germany
+
                                                          SMTPD(8)
 </pre> </body> </html>
diff --git a/postfix/html/tlsmgr.8.html b/postfix/html/tlsmgr.8.html
new file mode 100644 (file)
index 0000000..0c6c126
--- /dev/null
@@ -0,0 +1,164 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title> Postfix manual - tlsmgr(8) </title>
+</head> <body> <pre>
+TLSMGR(8)                                               TLSMGR(8)
+
+<b>NAME</b>
+       tlsmgr - Postfix TLS session cache and PRNG manager
+
+<b>SYNOPSIS</b>
+       <b>tlsmgr</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+       The <a href="tlsmgr.8.html">tlsmgr(8)</a> maintains the TLS session caches for Postfix
+       SMTP client and server processes.  It periodically removes
+       entries  that have expired, and entries that are no longer
+       compatible with the currently running Postfix version.
+
+       The <a href="tlsmgr.8.html">tlsmgr(8)</a> also maintains the PRNG (pseudo random  num-
+       ber  generator)  pool. This is queried by the <a href="smtpd.8.html">smtpd(8)</a> and
+       <a href="smtp.8.html">smtp(8)</a> processes to seed their internal PRNG pools.
+
+       The <a href="tlsmgr.8.html">tlsmgr(8)</a>'s internal PRNG  pool  is  initially  seeded
+       from  an  external  source  (EGD, /dev/urandom, or regular
+       file).  It is updated at configurable pseudo-random inter-
+       vals  with  data  from  the external source. It is updated
+       periodically with data from TLS session cache entries  and
+       with  the time of day, and is updated with the time of day
+       whenever a process requests <a href="tlsmgr.8.html">tlsmgr(8)</a> service.
+
+       The <a href="tlsmgr.8.html">tlsmgr(8)</a> saves the PRNG state  to  an  exchange  file
+       periodically  and  when  the process terminates, and reads
+       the exchange file when initializing its PRNG.
+
+<b>SECURITY</b>
+       <a href="tlsmgr.8.html">tlsmgr(8)</a> is not security-sensitive. The code  that  main-
+       tains  the  external  and  internal  PRNG  pools  does not
+       "trust" the data that it manipulates, and  the  code  that
+       maintains  the  TLS  session cache does not touch the con-
+       tents of the cached entries, except for seeding its inter-
+       nal PRNG pool.
+
+       The  <a href="tlsmgr.8.html">tlsmgr(8)</a> can be run chrooted and with reduced privi-
+       leges.  At process startup  it  connects  to  the  entropy
+       source  and  exchange  file,  and creates or truncates the
+       optional TLS session cache files.
+
+<b>DIAGNOSTICS</b>
+       Problems and transactions are logged to the syslog daemon.
+
+<b>BUGS</b>
+       There is no automatic means to limit the number of entries
+       in the TLS session caches and/or the size of the TLS cache
+       files.
+
+<b>CONFIGURATION PARAMETERS</b>
+       Changes  to  <b>main.cf</b>  are  not  picked  up  automatically,
+       because <a href="tlsmgr.8.html">tlsmgr(8)</a> is a persistent processes.  Use the com-
+       mand "<b>postfix reload</b>" after a configuration change.
+
+       The  text  below  provides  only  a parameter summary. See
+       <a href="postconf.5.html">postconf(5)</a> for more details including examples.
+
+<b>TLS SESSION CACHE</b>
+       <b><a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> (empty)</b>
+              Name of the file containing  the  optional  Postfix
+              SMTP server TLS session cache.
+
+       <b><a href="postconf.5.html#smtpd_tls_session_cache_timeout">smtpd_tls_session_cache_timeout</a> (3600s)</b>
+              The expiration time of Postfix SMTP server TLS ses-
+              sion cache information.
+
+       <b><a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> (empty)</b>
+              Name of the file containing  the  optional  Postfix
+              SMTP client TLS session cache.
+
+       <b><a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> (3600s)</b>
+              The expiration time of Postfix SMTP client TLS ses-
+              sion cache information.
+
+<b>PSEUDO RANDOM NUMBER GENERATOR</b>
+       <b><a href="postconf.5.html#tls_random_source">tls_random_source</a> (see 'postconf -d' output)</b>
+              The  external  entropy  source  for  the  in-memory
+              <a href="tlsmgr.8.html">tlsmgr(8)</a>  pseudo  random  number  generator (PRNG)
+              pool.
+
+       <b><a href="postconf.5.html#tls_random_bytes">tls_random_bytes</a> (32)</b>
+              The number  of  bytes  that  <a href="tlsmgr.8.html">tlsmgr(8)</a>  reads  from
+              $<a href="postconf.5.html#tls_random_source">tls_random_source</a>  when  (re)seeding the in-memory
+              pseudo random number generator (PRNG) pool.
+
+       <b><a href="postconf.5.html#tls_random_exchange_name">tls_random_exchange_name</a> (${<a href="postconf.5.html#config_directory">config_directory</a>}/prng_exch)</b>
+              Name of the pseudo random number  generator  (PRNG)
+              state file that is maintained by <a href="tlsmgr.8.html">tlsmgr(8)</a>.
+
+       <b><a href="postconf.5.html#tls_random_prng_update_period">tls_random_prng_update_period</a> (3600s)</b>
+              The  time between attempts by <a href="tlsmgr.8.html">tlsmgr(8)</a> to save the
+              state of the pseudo random number generator  (PRNG)
+              to    the    file    specified    with    $<a href="postconf.5.html#tls_random_exchange_name">tls_ran</a>-
+              <a href="postconf.5.html#tls_random_exchange_name">dom_exchange_name</a>.
+
+       <b><a href="postconf.5.html#tls_random_reseed_period">tls_random_reseed_period</a> (3600s)</b>
+              The maximal time between attempts by  <a href="tlsmgr.8.html">tlsmgr(8)</a>  to
+              re-seed  the in-memory pseudo random number genera-
+              tor (PRNG) pool from external sources.
+
+<b>MISCELLANEOUS CONTROLS</b>
+       <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
+              The default location of  the  Postfix  main.cf  and
+              master.cf configuration files.
+
+       <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
+              How  much time a Postfix daemon process may take to
+              handle a request  before  it  is  terminated  by  a
+              built-in watchdog timer.
+
+       <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
+              The  process ID of a Postfix command or daemon pro-
+              cess.
+
+       <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
+              The process name of a  Postfix  command  or  daemon
+              process.
+
+       <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
+              The syslog facility of Postfix logging.
+
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
+              The  mail system name that is prepended to the pro-
+              cess  name  in  syslog  records,  so  that  "smtpd"
+              becomes, for example, "postfix/smtpd".
+
+<b>SEE ALSO</b>
+       <a href="smtp.8.html">smtp(8)</a> Postfix SMTP client
+       <a href="smtpd.8.html">smtpd(8)</a> Postfix SMTP server
+       <a href="postconf.5.html">postconf(5)</a>, configuration parameters
+       <a href="master.5.html">master(5)</a>, generic daemon options
+       <a href="master.8.html">master(8)</a>, process manager
+       syslogd(8), system logging
+
+<b>README FILES</b>
+       <a href="TLS_README.html">TLS_README</a>, Postfix TLS configuration and operation
+
+<b>LICENSE</b>
+       The Secure Mailer license must be  distributed  with  this
+       software.
+
+<b>AUTHOR(S)</b>
+       Lutz Jaenicke
+       BTU Cottbus
+       Allgemeine Elektrotechnik
+       Universitaetsplatz 3-4
+       D-03044 Cottbus, Germany
+
+       Adapted by:
+       Wietse Venema
+       IBM T.J. Watson Research
+       P.O. Box 704
+       Yorktown Heights, NY 10598, USA
+
+                                                        TLSMGR(8)
+</pre> </body> </html>
index 42a0528e866790c6283d0b943e0d331f199a123b..c5c60467a0995d3bf5077255909280c2e1befeaf 100644 (file)
 # .IP \fBCCARGS=\fIcompiler_arguments\fR
 #      Specifies non-default compiler arguments, for example, a non-default
 #      \fIinclude\fR directory.
+#      The following directives are special:
+# .RS
+# .IP "\fB-DUSE_TLS\fR (default)"
+#      Build with TLS (transport level security) support. This
+#      requires that OpenSSL is installed.
+# .IP \fB-DNO_TLS\fR
+#      Do not build with TLS support.
+# .IP \fB-DHAS_PCRE\fR
+#      Build with PCRE (Perl-compatible regular expression) support.
+#      By default, PCRE support is enabled when the \fBpcre-config\fR
+#      utility is installed.
+# .IP \fB-DNO_PCRE\fR
+#      Do not build with PCRE support.
+# .RE
 # .IP \fBDEBUG=\fIdebug_level\fR
 #      Specifies a non-default debugging level. The default is \fB-g\fR.
 #      Specify \fBDEBUG=\fR to turn off debugging.
@@ -143,9 +157,9 @@ case "$SYSTEM.$RELEASE" in
                case $RELEASE in
                    5.[0-7]) CCARGS="$CCARGS -DNO_IPV6";;
                esac
-               # Solaris 9 added closefrom()
+               # Solaris 9 added closefrom() and /dev/*random
                case $RELEASE in
-                   5.[0-8]) CCARGS="$CCARGS -DNO_CLOSEFROM";;
+                   5.[0-8]) CCARGS="$CCARGS -DNO_CLOSEFROM -DNO_DEV_URANDOM";;
                esac
                # Work around broken str*casecmp(). Do it all here instead
                # of having half the solution in the sys_defs.h file.
@@ -327,6 +341,20 @@ Rhapsody.5*|Darwin.*)
           *)   error "Unknown system type: $SYSTEM $RELEASE";;
 esac
 
+#
+# OpenSSL has no configuration query utility, but we don't try to
+# guess. We assume includes in /usr/include/openssl and libraries in
+# /usr/lib, or in their /usr/local equivalents. If the OpenSSL files
+# are in a non-standard place, their locations need to be specified.
+#
+#case "$CCARGS" in
+# *-DUSE_TLS*) ;;
+#  *-DNO_TLS*) ;;
+#           *) CCARGS="$CCARGS -DUSE_TLS"
+#              AUXLIBS="$AUXLIBS -lssl -lcrypto"
+#              ;;
+#esac
+
 #
 # PCRE 3.x has a pcre-config utility so we don't have to guess.
 #
index 703e3db7de12930560f0ad62ebc71a0a88a32765..73711c8f558b8847a3e0133781566abd929195ae 100644 (file)
@@ -7,7 +7,7 @@ DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
        man8/showq.8 man8/smtp.8 man8/smtpd.8 man8/trivial-rewrite.8 \
        man8/oqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \
        man8/verify.8 man8/trace.8 man8/proxymap.8 man8/anvil.8 \
-       man8/scache.8 man8/discard.8
+       man8/scache.8 man8/discard.8 man8/tlsmgr.8
 COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
        man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
        man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
@@ -152,6 +152,11 @@ man8/verify.8: ../src/verify/verify.c
 man8/trace.8:
        echo .so man8/bounce.8 >$@
 
+man8/tlsmgr.8: ../src/tlsmgr/tlsmgr.c
+       ../mantools/fixman ../proto/postconf.proto $? >junk && \
+           (cmp -s junk $? || mv junk $?)
+       ../mantools/srctoman $? >$@
+
 man8/trivial-rewrite.8: ../src/trivial-rewrite/trivial-rewrite.c
        ../mantools/fixman ../proto/postconf.proto $? >junk && \
            (cmp -s junk $? || mv junk $?)
index ff4512a4821f1ce2adc7761d3d096b6d58197892..da7b1812f0462b085f0e411a9c3be4b65ac58fc5 100644 (file)
@@ -214,6 +214,7 @@ showq(8), list Postfix mail queue
 smtp(8), Postfix SMTP client
 smtpd(8), Postfix SMTP server
 spawn(8), run non-Postfix server
+tlsmgr(8), Postfix TLS cache and randomness manager
 trivial-rewrite(8), Postfix address rewriting
 verify(8), Postfix address verification
 virtual(8), Postfix virtual delivery agent
index 01dd03408a97564ae751f5f3a56cce3a03d1fecf..63395ec11179e225c40b6e312fb2f10e1b2c7212 100644 (file)
@@ -1298,7 +1298,8 @@ Note: you need to stop and start Postfix when this parameter changes.
 .PP
 When inet_interfaces specifies just one IPv4 and/or IPv6 address
 that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail.
+this address as the IP source address for outbound mail. Support
+for IPv6 is available in Postfix version 2.2 and later.
 .PP
 On a multi-homed firewall with separate Postfix instances listening on the
 "inside" and "outside" interfaces, this can prevent each instance from
@@ -1338,6 +1339,8 @@ or accepting connections. Specify one or more of "ipv4" or "ipv6",
 separated by whitespace or commas. The form "all" is equivalent to
 "ipv4, ipv6".
 .PP
+This feature is available in Postfix version 2.2 and later.
+.PP
 Note: you MUST stop and start Postfix after changing this
 parameter.
 .PP
@@ -1361,8 +1364,6 @@ When both IPv4 and IPv6 support are enabled, the Postfix SMTP
 client will attempt to connect via IPv6 before attempting to use
 IPv4.
 .PP
-This feature is available in Postfix version 2.2 and later.
-.PP
 Examples:
 .PP
 .nf
@@ -1651,8 +1652,8 @@ protocol. This is enabled by default.
 .IP "\fB permit_tls_clientcerts \fR"
 Append the domain name in $myorigin or $mydomain when the
 client TLS certificate is successfully verified, and the client
-certificate fingerprint is listed on the server. This is enabled
-by default.
+certificate fingerprint is listed in $relay_clientcerts. This is
+enabled by default.
 .IP "\fB permit_tls_all_clientcerts \fR"
 Append the domain name in $myorigin or $mydomain when the
 client TLS certificate is successfully verified, regardless of
@@ -2679,6 +2680,28 @@ The numerical Postfix SMTP server response code when a remote SMTP
 client request is rejected by the "\fBreject\fR" restriction.
 .PP
 Do not change this unless you have a complete understanding of RFC 821.
+.SH relay_clientcerts (default: empty)
+The list of remote SMTP client certificates for which the
+Postfix SMTP server will allow access with the permit_tls_clientcerts
+feature.  This feature does not use certificate names, because
+Postfix list manipulation routines treat whitespace and some other
+characters as special.  Instead we use certificate fingerprints as
+they are difficult to fake but easy to use for lookup.
+.PP
+Postfix lookup tables are in the form of (key, value) pairs.
+Since we only need the key, the value can be chosen freely, e.g.
+the name of the user or host:
+D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+.fi
+.ad
+.ft R
 .SH relay_destination_concurrency_limit (default: $default_destination_concurrency_limit)
 The maximal number of parallel deliveries to the same destination
 via the relay message delivery transport. This limit is enforced
@@ -3030,6 +3053,8 @@ but this form is not recommended.
 An optional numerical network address that the SMTP client should
 bind to when making an IPv6 connection.
 .PP
+This feature is available in Postfix version 2.2 and later.
+.PP
 This can be specified in the main.cf file for all SMTP clients, or
 it can be specified in the master.cf file for a specific client,
 for example:
@@ -3051,8 +3076,6 @@ inet_interfaces documentation for more detail.
 .PP
 Note 2: address information may be enclosed inside <tt>[]</tt>,
 but this form is not recommended.
-.PP
-This feature is available in Postfix version 2.2 and later.
 .SH smtp_connect_timeout (default: 30s)
 The SMTP client time limit for completing a TCP connection, or
 zero (use the operating system built-in time limit).
@@ -3167,6 +3190,24 @@ A case insensitive list of EHLO keywords (pipelining, starttls,
 auth, etc.) that the SMTP client will ignore in the EHLO response
 from a remote SMTP server. Use the smtp_discard_ehlo_keyword_address_maps
 feature to discard EHLO keywords selectively.
+.SH smtp_enforce_tls (default: no)
+Enforcement mode: require that remote SMTP servers use TLS
+encryption, and never send mail in the clear.  This also requires
+that the remote SMTP server hostname matches the information in
+the remote server certificate, and that the remote SMTP server
+certificate was issued by a CA that is trusted by the Postfix SMTP
+client. If the certificate doesn't verify or the hostname doesn't
+match, delivery is deferred and mail stays in the queue.
+.PP
+The server hostname is matched against all names provided as
+dNSNames in the SubjectAlternativeName.  If no dNSNames are specified,
+the CommonName is checked.  The behavior may be changed with the
+smtp_tls_enforce_peername option.
+.PP
+This option is useful only if you are definitely sure that you
+will only connect to servers that support RFC 2487 _and_ that
+provide valid server certificates.  Typical use is for clients that
+send all their email to a dedicated mailhub.
 .SH smtp_helo_name (default: $myhostname)
 The hostname to send in the SMTP EHLO or HELO command.
 .PP
@@ -3371,6 +3412,9 @@ smtp_sasl_security_options = noplaintext
 .fi
 .ad
 .ft R
+.SH smtp_sasl_tls_security_options (default: $smtp_sasl_security_options)
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions.
 .SH smtp_send_xforward_command (default: no)
 Send the non-standard XFORWARD command when the Postfix SMTP server EHLO
 response announces XFORWARD support.
@@ -3403,6 +3447,229 @@ bounce the mail immediately. The default setting is incorrect, but
 it is what a lot of people expect to happen.
 .SH smtp_skip_quit_response (default: yes)
 Do not wait for the response to the SMTP QUIT command.
+.SH smtp_starttls_timeout (default: 300s)
+Time limit for Postfix SMTP client write and read operations
+during TLS startup and shutdown handshake procedures.
+.SH smtp_tls_CAfile (default: empty)
+The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP client certificate.  This is
+needed only when the CA certificate is not already present in the
+client certificate file.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_CAfile = /etc/postfix/CAcert.pem
+.fi
+.ad
+.ft R
+.SH smtp_tls_CApath (default: empty)
+Directory with PEM format certificate authority certificates
+that the Postfix SMTP client uses to verify a remote SMTP server
+certificate.  Don't forget to create the necessary "hash" links
+with, for example, "$OPENSSL_HOME/bin/c_rehash /etc/postfix/certs".
+.PP
+To use this option in chroot mode, this directory (or a copy)
+must be inside the chroot jail.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_CApath = /etc/postfix/certs
+.fi
+.ad
+.ft R
+.SH smtp_tls_cert_file (default: empty)
+File with the Postfix SMTP client RSA certificate in PEM format.
+This file may also contain the client private key, and these may
+be the same as the server certificate and key file.
+.PP
+In order to verify certificates, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s).
+.PP
+Example: the certificate for "client.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the client.pem file with "cat client_cert.pem intermediate_CA.pem
+root_CA.pem > client.pem".
+.PP
+If you want to accept remote SMTP server certificates issued
+by these CAs yourself, you can also add the CA certificates to the
+smtp_tls_CAfile, in which case it is not necessary to have them in
+the smtp_tls_cert_file or smtp_tls_dcert_file.
+.PP
+A certificate supplied here must be usable as SSL client certificate and
+hence pass the "openssl verify -purpose sslclient ..." test.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_cert_file = /etc/postfix/client.pem
+.fi
+.ad
+.ft R
+.SH smtp_tls_cipherlist (default: empty)
+Controls the Postfix SMTP client TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value.
+.SH smtp_tls_dcert_file (default: empty)
+File with the Postfix SMTP client DSA certificate in PEM format.
+This file may also contain the server private key.
+.PP
+See the discussion under smtp_tls_cert_file for more details.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
+.fi
+.ad
+.ft R
+.SH smtp_tls_dkey_file (default: $smtp_tls_dcert_file)
+File with the Postfix SMTP client DSA private key in PEM format.
+The private key must not be encrypted. In other words, the key must
+be accessible without password.
+.PP
+This file may be combined with the server certificate file
+specified with $smtp_tls_cert_file.
+.SH smtp_tls_enforce_peername (default: yes)
+When TLS encryption is enforced, require that the remote SMTP
+server hostname matches the information in the remote SMTP server
+certificate.  As of RFC 2487 the requirements for hostname checking
+for MTA clients are not specified.
+.PP
+This option can be set to "no" to disable strict peer name
+checking. This setting has no effect on sessions that are controlled
+via the smtp_tls_per_site table.
+.PP
+Disabling the hostname verification can make sense in closed
+environment where special CAs are created.  If not used carefully,
+this option opens the danger of a "man-in-the-middle" attack (the
+CommonName of this attacker will be logged).
+.SH smtp_tls_key_file (default: $smtp_tls_cert_file)
+File with the Postfix SMTP client RSA private key in PEM format.
+This file may be combined with the client certificate file specified
+with $smtp_tls_cert_file.
+.PP
+The private key must not be encrypted. In other words, the key
+must be accessible without password.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_key_file = $smtp_tls_cert_file
+.fi
+.ad
+.ft R
+.SH smtp_tls_loglevel (default: 0)
+Enable additional Postfix SMTP client logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.
+.IP ""
+0 Disable logging of TLS activity.
+.IP ""
+1 Log TLS handshake and certificate information.
+.IP ""
+2 Log levels during TLS negotiation.
+.IP ""
+3 Log hexadecimal and ASCII dump of TLS negotiation
+process.
+.IP ""
+4 Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS.
+.PP
+Use "smtp_tls_loglevel = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged.
+.SH smtp_tls_note_starttls_offer (default: no)
+Log the hostname of a remote SMTP server that offers STARTTLS,
+when TLS is not already enabled for that server.
+.PP
+The logfile record looks like:
+.PP
+.nf
+.na
+.ft C
+postfix/smtp[pid]:  Host offered STARTTLS: [name.of.host]
+.fi
+.ad
+.ft R
+.SH smtp_tls_per_site (default: empty)
+Optional lookup tables with the Postfix SMTP client TLS usage
+policy by next-hop domain name and by remote SMTP server hostname.
+.PP
+Table format:  domain names or server hostnames are specified
+on the left-hand side; no wildcards are allowed.  On the right hand
+side specify one of the following keywords:
+.IP "NONE"
+Don't use TLS at all.
+.IP "MAY"
+Try to use STARTTLS if offered, otherwise use
+the unencrypted connection. NOTE: STARTTLS can be used only if
+TLS is already enabled via main.cf, so that the client TLS engine
+is properly initialized at program startup.
+.IP "MUST"
+Require usage of STARTTLS, require that the
+remote SMTP server hostname matches the information in the remote
+SMTP server certificate, and require that the remote SMTP server
+certificate was issued by a trusted CA.
+.IP "MUST_NOPEERMATCH"
+Require usage of STARTTLS, but do
+not require that the remote SMTP server hostname matches the
+information in the remote SMTP server certificate, or that the
+server certificate was issued by a trusted CA.
+.PP
+Special hint for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:  specify local
+transport(5) table entries for sensitive domains with explicit
+smtp:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+smtp_tls_per_site table.
+.SH smtp_tls_scert_verifydepth (default: 5)
+The verification depth for remote SMTP server certificates. A
+depth of 1 is sufficient, if the certificate is directly issued by
+a CA listed in the CA files.  The default value (5) should suffice
+for longer chains (the root CA issues special CA which then issues
+the actual certificate...).
+.SH smtp_tls_session_cache_database (default: empty)
+Name of the file containing the optional Postfix SMTP client
+TLS session cache. Specify a database type that supports enumeration,
+such as \fBbtree\fR or \fBsdbm\fR; there is no need to support
+concurrent access.  The file is created if it does not exist.
+.PP
+NOTE: \fBdbm\fR databases are not suitable. TLS
+session objects are too large.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtp_tls_session_cache_database = btree:/var/postfix/smtp_scache
+.fi
+.ad
+.ft R
+.SH smtp_tls_session_cache_timeout (default: 3600s)
+The expiration time of Postfix SMTP client TLS session cache
+information.  A cache cleanup is performed periodically every
+$smtp_tls_session_cache_timeout seconds.
+.SH smtp_use_tls (default: no)
+Opportunistic mode: use TLS when a remote SMTP server announces
+STARTTLS support, otherwise send the mail in the clear. Beware:
+some SMTP servers offer STARTTLS even if it is not configured.  If
+the TLS handshake fails, and no other server is available, delivery
+is deferred and mail stays in the queue.  If this is a concern for
+you, use the smtp_tls_per_site feature instead.
 .SH smtp_xforward_timeout (default: 300s)
 The SMTP client time limit for sending the XFORWARD command, and
 for receiving the server response.
@@ -3627,6 +3894,16 @@ network or network address listed in  $mynetworks.
 .IP "\fBpermit_sasl_authenticated\fR"
 Permit the request when the client is successfully
 authenticated via the RFC 2554 (AUTH) protocol.
+.IP "\fBpermit_tls_all_clientcerts\fR"
+Permit the request when the remote SMTP client certificate is
+verified successfully.  This option must be used only if a special
+CA issues the certificates and only this CA is listed as trusted
+CA, otherwise all clients with a recognized certificate would be
+allowed to relay.
+.IP "\fBpermit_tls_clientcerts\fR"
+Permit the request when the remote SMTP client certificate is
+verified successfully, and the certificate fingerprint is listed
+in $relay_clientcerts.
 .IP "\fBreject_rbl_client \fIrbl_domain=d.d.d.d\fR\fR"
 Reject the request when the reversed client network address is
 listed with the A record "\fId.d.d.d\fR" under \fIrbl_domain\fR
@@ -3804,6 +4081,18 @@ applies in the context of the SMTP END-OF-DATA command.
 This feature is available in Postfix 2.2 and later.
 .PP
 See smtpd_data_restrictions for syntax details.
+.SH smtpd_enforce_tls (default: no)
+Enforcement mode: announce STARTTLS support to SMTP clients,
+and require that clients use TLS encryption.  According to RFC 2487
+this MUST NOT be applied in case of a publicly-referenced SMTP
+server.  This option is off by default and should be used only on
+dedicated servers.
+.PP
+Note 1: this mode implies "smtpd_tls_auth_only = yes".
+.PP
+Note 2: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private
+key. This is intended behavior.
 .SH smtpd_error_sleep_time (default: 1s)
 With Postfix 2.1 and later: the SMTP server response delay after
 a client has made more than $smtpd_soft_error_limit errors, and
@@ -4342,6 +4631,9 @@ smtpd_sasl_security_options = noanonymous, noplaintext
 .fi
 .ad
 .ft R
+.SH smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options)
+The SASL authentication security options that the Postfix SMTP
+server uses for TLS encrypted SMTP sessions.
 .SH smtpd_sender_login_maps (default: empty)
 Optional lookup table with the SASL login names that own sender
 (MAIL FROM) addresses.
@@ -4485,6 +4777,9 @@ delays all responses by $smtpd_error_sleep_time seconds.
 .IP \(bu
 With Postfix versions 2.0 and earlier, the Postfix SMTP
 server delays all responses by (number of errors) seconds.
+.SH smtpd_starttls_timeout (default: 300s)
+The time limit for Postfix SMTP server write and read operations
+during TLS startup and shutdown handshake procedures.
 .SH smtpd_timeout (default: 300s)
 The time limit for sending a Postfix SMTP server response and for
 receiving a remote SMTP client request.
@@ -4494,6 +4789,250 @@ to update the global ipc_timeout parameter.
 .PP
 Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
 The default time unit is s (seconds).
+.SH smtpd_tls_CAfile (default: empty)
+The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP server certificate.  This is
+needed only when the CA certificate is not already present in the
+server certificate file.  This file may also contain the CA
+certificates of other trusted CAs.  You must use this file for the
+list of trusted CAs if you want to use chroot-mode.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_CAfile = /etc/postfix/CAcert.pem
+.fi
+.ad
+.ft R
+.SH smtpd_tls_CApath (default: empty)
+Directory with PEM format certificate authority certificates
+that the Postfix SMTP server offers to remote SMTP clients for the
+purpose of client certificate verification.  Do not forget to create
+the necessary "hash" links with, for example, "$OPENSSL_HOME/bin/c_rehash
+/etc/postfix/certs".
+.PP
+To use this option in chroot mode, this directory (or a copy)
+must be inside the chroot jail. Please note that in this case the
+CA certificates are not offered to the client, so that e.g.  Netscape
+clients might not offer certificates issued by them.  Use of this
+feature is therefore not recommended.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_CApath = /etc/postfix/certs
+.fi
+.ad
+.ft R
+.SH smtpd_tls_ask_ccert (default: no)
+Ask a remote SMTP client for a client certificate. This
+information is needed for certificate based mail relaying with,
+for example, the permit_tls_clientcerts feature.
+.PP
+Some clients such as Netscape will either complain if no
+certificate is available (for the list of CAs in /etc/postfix/certs)
+or will offer multiple client certificates to choose from. This
+may be annoying, so this option is "off" by default.
+.SH smtpd_tls_auth_only (default: no)
+When TLS encryption is optional in the Postfix SMTP server, do
+not announce or accept SASL authentication over unencrypted
+connections.
+.SH smtpd_tls_ccert_verifydepth (default: 5)
+The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file.  The default value should also suffice for longer chains (the
+root CA issues special CA which then issues the actual certificate...).
+.SH smtpd_tls_cert_file (default: empty)
+File with the Postfix SMTP server RSA certificate in PEM format.
+This file may also contain the server private key.
+.PP
+Both RSA and DSA certificates are supported.  When both types
+are present, the cipher used determines which certificate will be
+presented to the client.  For Netscape and OpenSSL clients without
+special cipher choices the RSA certificate is preferred.
+.PP
+In order to verify a certificate, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s).
+.PP
+Example: the certificate for "server.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the server.pem file with "cat server_cert.pem intermediate_CA.pem
+root_CA.pem > server.pem".
+.PP
+If you want to accept certificates issued by these CAs yourself,
+you can also add the CA certificates to the smtpd_tls_CAfile, in
+which case it is not necessary to have them in the smtpd_tls_dcert_file
+or smtpd_tls_cert_file.
+.PP
+A certificate supplied here must be usable as SSL server
+certificate and hence pass the "openssl verify -purpose sslserver
+\&..." test.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_cert_file = /etc/postfix/server.pem
+.fi
+.ad
+.ft R
+.SH smtpd_tls_cipherlist (default: empty)
+Controls the Postfix SMTP server TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value.
+.SH smtpd_tls_dcert_file (default: empty)
+File with the Postfix SMTP server DSA certificate in PEM format.
+This file may also contain the server private key.
+.PP
+See the discussion under smtpd_tls_cert_file for more details.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
+.fi
+.ad
+.ft R
+.SH smtpd_tls_dh1024_param_file (default: empty)
+File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers.
+.PP
+Instead of using the exact same parameter sets as distributed
+with other TLS packages, it is more secure to generate your own
+set of parameters with something like the following command:
+.PP
+.nf
+.na
+.ft C
+openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
+.fi
+.ad
+.ft R
+.PP
+Your actual source for entropy may differ. Some systems have
+/dev/random; on other system you may consider using the "Entropy
+Gathering Daemon EGD", available at http://www.lothar.com/tech/crypto/.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+.fi
+.ad
+.ft R
+.SH smtpd_tls_dh512_param_file (default: empty)
+File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers.
+.PP
+See also the discussion under the smtpd_tls_dh1024_param_file
+configuration parameter.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
+.fi
+.ad
+.ft R
+.SH smtpd_tls_dkey_file (default: $smtpd_tls_dcert_file)
+File with the Postfix SMTP server DSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $smtpd_tls_dcert_file.
+.PP
+The private key must not be encrypted. In other words, the key
+must be accessible without password.
+.SH smtpd_tls_key_file (default: $smtpd_tls_cert_file)
+File with the Postfix SMTP server RSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $smtpd_tls_cert_file.
+.PP
+The private key must not be encrypted. In other words, the key
+must be accessible without password.
+.SH smtpd_tls_loglevel (default: 0)
+Enable additional Postfix SMTP server logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.
+.IP ""
+0 Disable logging of TLS activity.
+.IP ""
+1 Log TLS handshake and certificate information.
+.IP ""
+2 Log levels during TLS negotiation.
+.IP ""
+3 Log hexadecimal and ASCII dump of TLS negotiation
+process.
+.IP ""
+4 Also log hexadecimal and ASCII dump of complete
+transmission after STARTTLS.
+.PP
+Use "smtpd_tls_loglevel = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged.
+.SH smtpd_tls_received_header (default: no)
+Request that the Postfix SMTP server produces Received:  message
+headers that include information about the protocol and cipher used,
+as well as the client CommonName and client certificate issuer
+CommonName.  This is disabled by default, as the information may
+be modified in transit through other mail servers.  Only information
+that was recorded by the final destination can be trusted.
+.SH smtpd_tls_req_ccert (default: no)
+When TLS encryption is enforced, require a remote SMTP client
+certificate in order to allow TLS connections to proceed.  This
+option implies "smtpd_tls_ask_ccert = yes".
+.PP
+When TLS encryption is optional, remote SMTP clients can bypass
+the restriction by simply not using STARTTLS at all. For this reason
+a TLS connection will be handled as if only "smtpd_tls_ask_ccert
+= yes" is specified.
+.SH smtpd_tls_session_cache_database (default: empty)
+Name of the file containing the optional Postfix SMTP server
+TLS session cache. Specify a database type that supports enumeration,
+such as \fBbtree\fR or \fBsdbm\fR; there is no need to support
+concurrent access.  The file is created if it does not exist.
+.PP
+NOTE: \fBdbm\fR databases are not suitable. TLS
+session objects are too large.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+smtpd_tls_session_cache_database = btree:/var/postfix/smtpd_scache
+.fi
+.ad
+.ft R
+.SH smtpd_tls_session_cache_timeout (default: 3600s)
+The expiration time of Postfix SMTP server TLS session cache
+information.  A cache cleanup is performed periodically every
+$smtpd_tls_session_cache_timeout seconds.
+.SH smtpd_tls_wrappermode (default: no)
+Run the Postfix SMTP server in the non-standard "wrapper" mode,
+instead of using the STARTTLS command.
+.PP
+If you want to support this service, enable a special port in
+master.cf, and specify "-o smtpd_tls_wrappermode=yes" on the SMTP
+server's command line. Port 465 (smtps) was once chosen for this
+purpose.
+.SH smtpd_use_tls (default: no)
+Opportunistic mode: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption.
+.PP
+Note: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private
+key. This is intended behavior.
 .SH soft_bounce (default: no)
 Safety net to keep mail queued that would otherwise be returned to
 the sender.  This parameter disables locally-generated bounces,
@@ -4596,6 +5135,42 @@ a Postfix process has completed initialization. Errors during
 process initialization will be logged with the default name. Examples
 are errors while parsing the command line arguments, and errors
 while accessing the Postfix main.cf configuration file.
+.SH tls_daemon_random_bytes (default: 32)
+The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+process requests from the tlsmgr(8) server in order to seed its
+internal pseudo random number generator (PRNG).  The default of 32
+bytes (equivalent to 256 bits) is sufficient to generate a 128bit
+(or 168bit) session key.
+.SH tls_random_bytes (default: 32)
+The number of bytes that tlsmgr(8) reads from $tls_random_source
+when (re)seeding the in-memory pseudo random number generator (PRNG)
+pool. The default of 32 bytes (256 bits) is good enough for 128bit
+symmetric keys.  If using EGD or a device file, a maximum of 255
+bytes is read.
+.SH tls_random_exchange_name (default: ${config_directory}/prng_exch)
+Name of the pseudo random number generator (PRNG) state file
+that is maintained by tlsmgr(8). The file is created when it does
+not exist, and its length is fixed at 1024 bytes.
+.PP
+Since this file is modified by Postfix, it should probably be
+kept in the /var file system, instead of under $config_directory.
+The location should not be inside the chroot jail.
+.SH tls_random_prng_update_period (default: 3600s)
+The time between attempts by tlsmgr(8) to save the state of
+the pseudo random number generator (PRNG) to the file specified
+with $tls_random_exchange_name.
+.SH tls_random_reseed_period (default: 3600s)
+The maximal time between attempts by tlsmgr(8) to re-seed the
+in-memory pseudo random number generator (PRNG) pool from external
+sources.  The actual time between re-seeding attempts is calculated
+using the PRNG, and is between 0 and the time specified.
+.SH tls_random_source (default: see "postconf -d" output)
+The external entropy source for the in-memory tlsmgr(8) pseudo
+random number generator (PRNG) pool. Be sure to specify a non-blocking
+source.  If this source is not a regular file, the entropy source
+type must be prepended:  egd:/path/to/egd_socket for a source with
+EGD compatible socket interface, or dev:/path/to/device for a
+device file.
 .SH trace_service_name (default: trace)
 The name of the trace(8) service. This service maintains a record
 of mail deliveries and produces a mail delivery report when verbose
index 6812e568ac067d8f5bfdce166dbdbf07e6536f54..a6f6280cfc9dd5374f830d0a1c3d3c1f34bca6d9 100644 (file)
@@ -118,8 +118,8 @@ The directory with Postfix support programs and daemon programs.
 The external command to execute when a Postfix daemon program is
 invoked with the -D option.
 .IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives mail
-on.
+The network interface addresses that this mail system receives
+mail on.
 .IP "\fBinet_protocols (ipv4)\fR"
 The Internet protocols Postfix will attempt to use when making
 or accepting connections.
index 303b11d944d31ef94b0553ecfb8f7fd531989cd2..fdc479ee49feadcdfab32b9ca9671caec82c7a2e 100644 (file)
@@ -61,6 +61,7 @@ RFC 2046 (MIME: Media Types)
 RFC 2554 (AUTH command)
 RFC 2821 (SMTP protocol)
 RFC 2920 (SMTP Pipelining)
+RFC 3207 (STARTTLS command)
 .SH DIAGNOSTICS
 .ad
 .fi
@@ -178,6 +179,66 @@ Available in Postfix version 2.2 and later:
 .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR"
 If non-empty, a Postfix SMTP client filter for the remote SMTP
 server's list of offered SASL mechanisms.
+.SH "STARTTLS SUPPORT CONTROLS"
+.na
+.nf
+.ad
+.fi
+Detailed information about STARTTLS configuration may be found
+in the TLS_README document.
+.IP "\fBsmtp_use_tls (no)\fR"
+Opportunistic mode: use TLS when a remote SMTP server announces
+STARTTLS support, otherwise send the mail in the clear.
+.IP "\fBsmtp_enforce_tls (no)\fR"
+Enforcement mode: require that remote SMTP servers use TLS
+encryption, and never send mail in the clear.
+.IP "\fBsmtp_sasl_tls_security_options ($smtp_sasl_security_options)\fR"
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions.
+.IP "\fBsmtp_starttls_timeout (300s)\fR"
+Time limit for Postfix SMTP client write and read operations
+during TLS startup and shutdown handshake procedures.
+.IP "\fBsmtp_tls_CAfile (empty)\fR"
+The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP client certificate.
+.IP "\fBsmtp_tls_CApath (empty)\fR"
+Directory with PEM format certificate authority certificates
+that the Postfix SMTP client uses to verify a remote SMTP server
+certificate.
+.IP "\fBsmtp_tls_cert_file (empty)\fR"
+File with the Postfix SMTP client RSA certificate in PEM format.
+.IP "\fBsmtp_tls_cipherlist (empty)\fR"
+Controls the Postfix SMTP client TLS cipher selection scheme.
+.IP "\fBsmtp_tls_dcert_file (empty)\fR"
+File with the Postfix SMTP client DSA certificate in PEM format.
+.IP "\fBsmtp_tls_dkey_file ($smtp_tls_dcert_file)\fR"
+File with the Postfix SMTP client DSA private key in PEM format.
+.IP "\fBsmtp_tls_enforce_peername (yes)\fR"
+When TLS encryption is enforced, require that the remote SMTP
+server hostname matches the information in the remote SMTP server
+certificate.
+.IP "\fBsmtp_tls_key_file ($smtp_tls_cert_file)\fR"
+File with the Postfix SMTP client RSA private key in PEM format.
+.IP "\fBsmtp_tls_loglevel (0)\fR"
+Enable additional Postfix SMTP client logging of TLS activity.
+.IP "\fBsmtp_tls_note_starttls_offer (no)\fR"
+Log the hostname of a remote SMTP server that offers STARTTLS,
+when TLS is not already enabled for that server.
+.IP "\fBsmtp_tls_per_site (empty)\fR"
+Optional lookup tables with the Postfix SMTP client TLS usage
+policy by next-hop domain name and by remote SMTP server hostname.
+.IP "\fBsmtp_tls_scert_verifydepth (5)\fR"
+The verification depth for remote SMTP server certificates.
+.IP "\fBsmtp_tls_session_cache_database (empty)\fR"
+Name of the file containing the optional Postfix SMTP client
+TLS session cache.
+.IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
+The expiration time of Postfix SMTP client TLS session cache
+information.
+.IP "\fBtls_daemon_random_bytes (32)\fR"
+The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+process requests from the tlsmgr(8) server in order to seed its
+internal pseudo random number generator (PRNG).
 .SH "RESOURCE AND RATE CONTROLS"
 .na
 .nf
@@ -327,6 +388,7 @@ scache(8), connection cache server
 postconf(5), configuration parameters
 master(5), generic daemon options
 master(8), process manager
+tlsmgr(8), TLS session and PRNG management
 syslogd(8), system logging
 .SH "README FILES"
 .na
@@ -338,6 +400,7 @@ Use "\fBpostconf readme_directory\fR" or
 .na
 .nf
 SASL_README, Postfix SASL howto
+TLS_README, Postfix STARTTLS howto
 .SH "LICENSE"
 .na
 .nf
@@ -363,3 +426,10 @@ CV1 4LY, United Kingdom.
 Connection caching in cooperation with:
 Victor Duchovni
 Morgan Stanley
+
+TLS support originally by:
+Lutz Jaenicke
+BTU Cottbus
+Allgemeine Elektrotechnik
+Universitaetsplatz 3-4
+D-03044 Cottbus, Germany
index 5a37a5c3d9b8466a296ca8358da92bbe869d54e4..774cbd4124644ba1f7b6e0fa2a3442348d00af6b 100644 (file)
@@ -49,6 +49,7 @@ RFC 1985 (ETRN command)
 RFC 2554 (AUTH command)
 RFC 2821 (SMTP protocol)
 RFC 2920 (SMTP Pipelining)
+RFC 3207 (STARTTLS command)
 .SH DIAGNOSTICS
 .ad
 .fi
@@ -210,6 +211,78 @@ Optional lookup table with the SASL login names that own sender
 Available in Postfix version 2.1 and later:
 .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR"
 What SMTP clients Postfix will not offer AUTH support to.
+.SH "STARTTLS SUPPORT CONTROLS"
+.na
+.nf
+.ad
+.fi
+Detailed information about STARTTLS configuration may be
+found in the TLS_README document.
+.IP "\fBsmtpd_use_tls (no)\fR"
+Opportunistic mode: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption.
+.IP "\fBsmtpd_enforce_tls (no)\fR"
+Enforcement mode: announce STARTTLS support to SMTP clients,
+and require that clients use TLS encryption.
+.IP "\fBsmtpd_sasl_tls_security_options ($smtpd_sasl_security_options)\fR"
+The SASL authentication security options that the Postfix SMTP
+server uses for TLS encrypted SMTP sessions.
+.IP "\fBsmtpd_starttls_timeout (300s)\fR"
+The time limit for Postfix SMTP server write and read operations
+during TLS startup and shutdown handshake procedures.
+.IP "\fBsmtpd_tls_CAfile (empty)\fR"
+The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP server certificate.
+.IP "\fBsmtpd_tls_CAfile (empty)\fR"
+The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP server certificate.
+.IP "\fBsmtpd_tls_ask_ccert (no)\fR"
+Ask a remote SMTP client for a client certificate.
+.IP "\fBsmtpd_tls_auth_only (no)\fR"
+When TLS encryption is optional in the Postfix SMTP server, do
+not announce or accept SASL authentication over unencrypted
+connections.
+.IP "\fBsmtpd_tls_ccert_verifydepth (5)\fR"
+The verification depth for remote SMTP client certificates.
+.IP "\fBsmtpd_tls_cert_file (empty)\fR"
+File with the Postfix SMTP server RSA certificate in PEM format.
+.IP "\fBsmtpd_tls_cipherlist (empty)\fR"
+Controls the Postfix SMTP server TLS cipher selection scheme.
+.IP "\fBsmtpd_tls_dcert_file (empty)\fR"
+File with the Postfix SMTP server DSA certificate in PEM format.
+.IP "\fBsmtpd_tls_dh1024_param_file (empty)\fR"
+File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers.
+.IP "\fBsmtpd_tls_dh512_param_file (empty)\fR"
+File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers.
+.IP "\fBsmtpd_tls_dkey_file ($smtpd_tls_dcert_file)\fR"
+File with the Postfix SMTP server DSA private key in PEM format.
+.IP "\fBsmtpd_tls_key_file ($smtpd_tls_cert_file)\fR"
+File with the Postfix SMTP server RSA private key in PEM format.
+.IP "\fBsmtpd_tls_loglevel (0)\fR"
+Enable additional Postfix SMTP server logging of TLS activity.
+.IP "\fBsmtpd_tls_received_header (no)\fR"
+Request that the Postfix SMTP server produces Received:  message
+headers that include information about the protocol and cipher used,
+as well as the client CommonName and client certificate issuer
+CommonName.
+.IP "\fBsmtpd_tls_req_ccert (no)\fR"
+When TLS encryption is enforced, require a remote SMTP client
+certificate in order to allow TLS connections to proceed.
+.IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
+Name of the file containing the optional Postfix SMTP server
+TLS session cache.
+.IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
+The expiration time of Postfix SMTP server TLS session cache
+information.
+.IP "\fBsmtpd_tls_wrappermode (no)\fR"
+Run the Postfix SMTP server in the non-standard "wrapper" mode,
+instead of using the STARTTLS command.
+.IP "\fBtls_daemon_random_bytes (32)\fR"
+The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+process requests from the tlsmgr(8) server in order to seed its
+internal pseudo random number generator (PRNG).
 .SH "VERP SUPPORT CONTROLS"
 .na
 .nf
@@ -654,6 +727,7 @@ terminate the session with a 221 code.
 .nf
 anvil(8), connection/rate limiting
 cleanup(8), message canonicalization
+tlsmgr(8), TLS session and PRNG management
 trivial-rewrite(8), address resolver
 verify(8), address verification service
 postconf(5), configuration parameters
@@ -677,6 +751,7 @@ SMTPD_ACCESS_README, built-in access policies
 SMTPD_POLICY_README, external policy server
 SMTPD_PROXY_README, external before-queue content filter
 SASL_README, Postfix SASL howto
+TLS_README, Postfix STARTTLS howto
 VERP_README, Postfix XVERP extension
 XCLIENT_README, Postfix XCLIENT extension
 XFORWARD_README, Postfix XFORWARD extension
@@ -693,3 +768,10 @@ Wietse Venema
 IBM T.J. Watson Research
 P.O. Box 704
 Yorktown Heights, NY 10598, USA
+
+TLS support originally by:
+Lutz Jaenicke
+BTU Cottbus
+Allgemeine Elektrotechnik
+Universitaetsplatz 3-4
+D-03044 Cottbus, Germany
diff --git a/postfix/man/man8/tlsmgr.8 b/postfix/man/man8/tlsmgr.8
new file mode 100644 (file)
index 0000000..e475a2a
--- /dev/null
@@ -0,0 +1,168 @@
+.TH TLSMGR 8 
+.ad
+.fi
+.SH NAME
+tlsmgr
+\-
+Postfix TLS session cache and PRNG manager
+.SH "SYNOPSIS"
+.na
+.nf
+\fBtlsmgr\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+The tlsmgr(8) maintains the TLS session caches for Postfix
+SMTP client and server processes.  It periodically removes
+entries that have expired, and entries that are no longer
+compatible with the currently running Postfix version.
+
+The tlsmgr(8) also maintains the PRNG (pseudo random number
+generator) pool. This is queried by the smtpd(8) and smtp(8)
+processes to seed their internal PRNG pools.
+
+The tlsmgr(8)'s internal PRNG pool is initially seeded from
+an external source (EGD, /dev/urandom, or regular file).
+It is updated at configurable pseudo-random intervals with
+data from the external source. It is updated periodically
+with data from TLS session cache entries and with the time
+of day, and is updated with the time of day whenever a
+process requests tlsmgr(8) service.
+
+The tlsmgr(8) saves the PRNG state to an exchange file
+periodically and when the process terminates, and reads
+the exchange file when initializing its PRNG.
+.SH "SECURITY"
+.na
+.nf
+.ad
+.fi
+tlsmgr(8) is not security-sensitive. The code that maintains
+the external and internal PRNG pools does not "trust" the
+data that it manipulates, and the code that maintains the
+TLS session cache does not touch the contents of the cached
+entries, except for seeding its internal PRNG pool.
+
+The tlsmgr(8) can be run chrooted and with reduced privileges.
+At process startup it connects to the entropy source and
+exchange file, and creates or truncates the optional TLS
+session cache files.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems and transactions are logged to the syslog daemon.
+.SH BUGS
+.ad
+.fi
+There is no automatic means to limit the number of entries in the
+TLS session caches and/or the size of the TLS cache files.
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+Changes to \fBmain.cf\fR are not picked up automatically,
+because tlsmgr(8) is a persistent processes.  Use the
+command "\fBpostfix reload\fR" after a configuration change.
+
+The text below provides only a parameter summary. See
+postconf(5) for more details including examples.
+.SH "TLS SESSION CACHE"
+.na
+.nf
+.ad
+.fi
+.IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
+Name of the file containing the optional Postfix SMTP server
+TLS session cache.
+.IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
+The expiration time of Postfix SMTP server TLS session cache
+information.
+.IP "\fBsmtp_tls_session_cache_database (empty)\fR"
+Name of the file containing the optional Postfix SMTP client
+TLS session cache.
+.IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
+The expiration time of Postfix SMTP client TLS session cache
+information.
+.SH "PSEUDO RANDOM NUMBER GENERATOR"
+.na
+.nf
+.ad
+.fi
+.IP "\fBtls_random_source (see 'postconf -d' output)\fR"
+The external entropy source for the in-memory tlsmgr(8) pseudo
+random number generator (PRNG) pool.
+.IP "\fBtls_random_bytes (32)\fR"
+The number of bytes that tlsmgr(8) reads from $tls_random_source
+when (re)seeding the in-memory pseudo random number generator (PRNG)
+pool.
+.IP "\fBtls_random_exchange_name (${config_directory}/prng_exch)\fR"
+Name of the pseudo random number generator (PRNG) state file
+that is maintained by tlsmgr(8).
+.IP "\fBtls_random_prng_update_period (3600s)\fR"
+The time between attempts by tlsmgr(8) to save the state of
+the pseudo random number generator (PRNG) to the file specified
+with $tls_random_exchange_name.
+.IP "\fBtls_random_reseed_period (3600s)\fR"
+The maximal time between attempts by tlsmgr(8) to re-seed the
+in-memory pseudo random number generator (PRNG) pool from external
+sources.
+.SH "MISCELLANEOUS CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+The default location of the Postfix main.cf and master.cf
+configuration files.
+.IP "\fBdaemon_timeout (18000s)\fR"
+How much time a Postfix daemon process may take to handle a
+request before it is terminated by a built-in watchdog timer.
+.IP "\fBprocess_id (read-only)\fR"
+The process ID of a Postfix command or daemon process.
+.IP "\fBprocess_name (read-only)\fR"
+The process name of a Postfix command or daemon process.
+.IP "\fBsyslog_facility (mail)\fR"
+The syslog facility of Postfix logging.
+.IP "\fBsyslog_name (postfix)\fR"
+The mail system name that is prepended to the process name in syslog
+records, so that "smtpd" becomes, for example, "postfix/smtpd".
+.SH "SEE ALSO"
+.na
+.nf
+smtp(8) Postfix SMTP client
+smtpd(8) Postfix SMTP server
+postconf(5), configuration parameters
+master(5), generic daemon options
+master(8), process manager
+syslogd(8), system logging
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or
+"\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
+TLS_README, Postfix TLS configuration and operation
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH "AUTHOR(S)"
+.na
+.nf
+Lutz Jaenicke
+BTU Cottbus
+Allgemeine Elektrotechnik
+Universitaetsplatz 3-4
+D-03044 Cottbus, Germany
+
+Adapted by:
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
index fcb5bda729829ef7b09621ccd3b21e79809a0315..dca9e60edc57d6c113ae7e42d432a11ab23de9b5 100755 (executable)
@@ -352,7 +352,7 @@ while (<>) {
     s;\bsmtp_sasl_auth_enable\b;<a href="postconf.5.html#smtp_sasl_auth_enable">$&</a>;g;
     s;\bsmtp_sasl_mechanism_filter\b;<a href="postconf.5.html#smtp_sasl_mechanism_filter">$&</a>;g;
     s;\bsmtp_sasl_password_maps\b;<a href="postconf.5.html#smtp_sasl_password_maps">$&</a>;g;
-    s;\bsmtp_sasl_security_options\b;<a href="postconf.5.html#smtp_sasl_security_options">$&</a>;g;
+    s;\bsmtp_sasl_secu[-</Bb>]*\n* *[<Bb>]*rity_options\b;<a href="postconf.5.html#smtp_sasl_security_options">$&</a>;g;
     s;\bsmtp_send_xforward_command\b;<a href="postconf.5.html#smtp_send_xforward_command">$&</a>;g;
     s;\bsmtp_skip_4xx_greeting\b;<a href="postconf.5.html#smtp_skip_4xx_greeting">$&</a>;g;
     s;\bsmtp_skip_5xx_greeting\b;<a href="postconf.5.html#smtp_skip_5xx_greeting">$&</a>;g;
@@ -400,7 +400,7 @@ while (<>) {
     s;\bsmtpd_sasl_auth_enable\b;<a href="postconf.5.html#smtpd_sasl_auth_enable">$&</a>;g;
     s;\bsmtpd_sasl_exceptions_networks\b;<a href="postconf.5.html#smtpd_sasl_exceptions_networks">$&</a>;g;
     s;\bsmtpd_sasl_local_domain\b;<a href="postconf.5.html#smtpd_sasl_local_domain">$&</a>;g;
-    s;\bsmtpd_sasl_security_options\b;<a href="postconf.5.html#smtpd_sasl_security_options">$&</a>;g;
+    s;\bsmtpd_sasl_secu[-</Bb>]*\n* *[<Bb>]*rity_options\b;<a href="postconf.5.html#smtpd_sasl_security_options">$&</a>;g;
     s;\bsmtpd_sender_login_maps\b;<a href="postconf.5.html#smtpd_sender_login_maps">$&</a>;g;
     s;\bsmtpd_sender_restrictions\b;<a href="postconf.5.html#smtpd_sender_restrictions">$&</a>;g;
     s;\bsmtpd_soft_error_limit\b;<a href="postconf.5.html#smtpd_soft_error_limit">$&</a>;g;
@@ -446,6 +446,55 @@ while (<>) {
     s;\bvir[-</bB>]*\n*[ <bB>]*tual_transport\b;<a href="postconf.5.html#virtual_transport">$&</a>;g;
     s;\bvir[-</bB>]*\n*[ <bB>]*tual_uid_maps\b;<a href="postconf.5.html#virtual_uid_maps">$&</a>;g;
 
+    s;\bsmtp_enforce_tls\b;<a href="postconf.5.html#smtp_enforce_tls">$&</a>;g;
+    s;\bsmtp_sasl_tls_security_options\b;<a href="postconf.5.html#smtp_sasl_tls_security_options">$&</a>;g;
+    s;\bsmtp_sasl_tls_verified_security_options\b;<a href="postconf.5.html#smtp_sasl_tls_verified_security_options">$&</a>;g;
+    s;\bsmtp_starttls_timeout\b;<a href="postconf.5.html#smtp_starttls_timeout">$&</a>;g;
+    s;\bsmtp_tls_CAfile\b;<a href="postconf.5.html#smtp_tls_CAfile">$&</a>;g;
+    s;\bsmtp_tls_CApath\b;<a href="postconf.5.html#smtp_tls_CApath">$&</a>;g;
+    s;\bsmtp_tls_cert_file\b;<a href="postconf.5.html#smtp_tls_cert_file">$&</a>;g;
+    s;\bsmtp_tls_cipherlist\b;<a href="postconf.5.html#smtp_tls_cipherlist">$&</a>;g;
+    s;\bsmtp_tls_dcert_file\b;<a href="postconf.5.html#smtp_tls_dcert_file">$&</a>;g;
+    s;\bsmtp_tls_dkey_file\b;<a href="postconf.5.html#smtp_tls_dkey_file">$&</a>;g;
+    s;\bsmtp_tls_enforce_peername\b;<a href="postconf.5.html#smtp_tls_enforce_peername">$&</a>;g;
+    s;\bsmtp_tls_key_file\b;<a href="postconf.5.html#smtp_tls_key_file">$&</a>;g;
+    s;\bsmtp_tls_loglevel\b;<a href="postconf.5.html#smtp_tls_loglevel">$&</a>;g;
+    s;\bsmtp_tls_note_starttls_offer\b;<a href="postconf.5.html#smtp_tls_note_starttls_offer">$&</a>;g;
+    s;\bsmtp_tls_per_site\b;<a href="postconf.5.html#smtp_tls_per_site">$&</a>;g;
+    s;\bsmtp_tls_scert_verifydepth\b;<a href="postconf.5.html#smtp_tls_scert_verifydepth">$&</a>;g;
+    s;\bsmtp_tls_session_cache_database\b;<a href="postconf.5.html#smtp_tls_session_cache_database">$&</a>;g;
+    s;\bsmtp_tls_session_cache_timeout\b;<a href="postconf.5.html#smtp_tls_session_cache_timeout">$&</a>;g;
+    s;\bsmtp_use_tls\b;<a href="postconf.5.html#smtp_use_tls">$&</a>;g;
+    s;\bsmtpd_enforce_tls\b;<a href="postconf.5.html#smtpd_enforce_tls">$&</a>;g;
+    s;\bsmtpd_sasl_tls_security_options\b;<a href="postconf.5.html#smtpd_sasl_tls_security_options">$&</a>;g;
+    s;\bsmtpd_starttls_timeout\b;<a href="postconf.5.html#smtpd_starttls_timeout">$&</a>;g;
+    s;\bsmtpd_tls_CAfile\b;<a href="postconf.5.html#smtpd_tls_CAfile">$&</a>;g;
+    s;\bsmtpd_tls_CApath\b;<a href="postconf.5.html#smtpd_tls_CApath">$&</a>;g;
+    s;\bsmtpd_tls_ask_ccert\b;<a href="postconf.5.html#smtpd_tls_ask_ccert">$&</a>;g;
+    s;\bsmtpd_tls_auth_only\b;<a href="postconf.5.html#smtpd_tls_auth_only">$&</a>;g;
+    s;\bsmtpd_tls_ccert_verifydepth\b;<a href="postconf.5.html#smtpd_tls_ccert_verifydepth">$&</a>;g;
+    s;\bsmtpd_tls_cert_file\b;<a href="postconf.5.html#smtpd_tls_cert_file">$&</a>;g;
+    s;\bsmtpd_tls_cipherlist\b;<a href="postconf.5.html#smtpd_tls_cipherlist">$&</a>;g;
+    s;\bsmtpd_tls_dcert_file\b;<a href="postconf.5.html#smtpd_tls_dcert_file">$&</a>;g;
+    s;\bsmtpd_tls_dh1024_param_file\b;<a href="postconf.5.html#smtpd_tls_dh1024_param_file">$&</a>;g;
+    s;\bsmtpd_tls_dh512_param_file\b;<a href="postconf.5.html#smtpd_tls_dh512_param_file">$&</a>;g;
+    s;\bsmtpd_tls_dkey_file\b;<a href="postconf.5.html#smtpd_tls_dkey_file">$&</a>;g;
+    s;\bsmtpd_tls_key_file\b;<a href="postconf.5.html#smtpd_tls_key_file">$&</a>;g;
+    s;\bsmtpd_tls_loglevel\b;<a href="postconf.5.html#smtpd_tls_loglevel">$&</a>;g;
+    s;\bsmtpd_tls_received_header\b;<a href="postconf.5.html#smtpd_tls_received_header">$&</a>;g;
+    s;\bsmtpd_tls_req_ccert\b;<a href="postconf.5.html#smtpd_tls_req_ccert">$&</a>;g;
+    s;\bsmtpd_tls_session_cache_database\b;<a href="postconf.5.html#smtpd_tls_session_cache_database">$&</a>;g;
+    s;\bsmtpd_tls_session_cache_timeout\b;<a href="postconf.5.html#smtpd_tls_session_cache_timeout">$&</a>;g;
+    s;\bsmtpd_tls_wrappermode\b;<a href="postconf.5.html#smtpd_tls_wrappermode">$&</a>;g;
+    s;\bsmtpd_use_tls\b;<a href="postconf.5.html#smtpd_use_tls">$&</a>;g;
+    s;\btls_daemon_random_bytes\b;<a href="postconf.5.html#tls_daemon_random_bytes">$&</a>;g;
+    s;\btls_daemon_random_source\b;<a href="postconf.5.html#tls_daemon_random_source">$&</a>;g;
+    s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_bytes\b;<a href="postconf.5.html#tls_random_bytes">$&</a>;g;
+    s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_exchange_name\b;<a href="postconf.5.html#tls_random_exchange_name">$&</a>;g;
+    s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_prng_update_period\b;<a href="postconf.5.html#tls_random_prng_update_period">$&</a>;g;
+    s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_reseed_period\b;<a href="postconf.5.html#tls_random_reseed_period">$&</a>;g;
+    s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_source\b;<a href="postconf.5.html#tls_random_source">$&</a>;g;
     # Undo hyperlinks of manual pages with the same name as parameters.
 
     s/<a href="[^"]*">([^<]*)<\/a>\(/$1(/g;
@@ -475,6 +524,7 @@ while (<>) {
     s/[<bB>]*smtp[<\/bB>]*\(8\)/<a href="smtp.8.html">$&<\/a>/g;
     s/[<bB>]*smtpd[<\/bB>]*\(8\)/<a href="smtpd.8.html">$&<\/a>/g;
     s/[<bB>]*spawn[<\/bB>]*\(8\)/<a href="spawn.8.html">$&<\/a>/g;
+    s/[<bB>]*tlsmgr[<\/bB>]*\(8\)/<a href="tlsmgr.8.html">$&<\/a>/g;
     s/[<bB>]*trace[<\/bB>]*\(8\)/<a href="trace.8.html">$&<\/a>/g;
     s/[<bB>]*trivial- *<br> *rewrite[<\/bB>]*\(8\)/<a href="trivial-rewrite.8.html">$&<\/a>/g;
     s/[<bB>]*triv[-<\/bB>]*\n* *[<bB>]*ial-[<\/bB>]*\n* *[<bB>]*rewrite[<\/bB>]*\(8\)/<a href="trivial-rewrite.8.html">$&<\/a>/g;
@@ -523,7 +573,7 @@ while (<>) {
 
     # Hyperlink README document names
 
-    s/\b[A-Z_]*_README\b/<a href="$&.html">$&<\/a>/g;
+    s/\b[A-Z0-9_]*_README\b/<a href="$&.html">$&<\/a>/g;
     s/\bINSTALL\b/<a href="$&.html">$&<\/a>/g;
     s/\bOVERVIEW\b/<a href="$&.html">$&<\/a>/g;
     s/"type:table"/"<a href="DATABASE_README.html">type:table<\/a>"/g;
index b3820ddc20c8b7f9bb070cf8fe2913cbadafde1d..cf70acf0248b8e5948512ed808c4b828a591cc9c 100755 (executable)
@@ -58,6 +58,7 @@ queue_directory
 readme_directory
 sendmail_path
 smtpd_expansion_filter
+tls_random_source
 virtual_mailbox_lock
 EOF
 
index b092d0c849da53fe2a25d9d67564148d5ee1467f..4a0dc865abf203a724d018748bdedb5cebfa6d5d 100644 (file)
@@ -852,7 +852,8 @@ align="left">Default delivery method </th> <th>Availability
 <p> Once the trivial-rewrite(8) daemon has determined a default
 delivery method it searches the optional transport(5) table for
 information that overrides the message destination and/or delivery
-method.  Typical use of the transport(5) is to send mail to a system
+method.  Typical use of the transport(5) table is to send mail to
+a system
 that is not connected to the Internet, or to use a special SMTP
 client configuration for destinations that have special requirements.
 See, for example, the STANDARD_CONFIGURATION_README and UUCP_README
index 40fb4bf569c8f0be676184079a8ad50decea2f52..7c3431b8798c2a2f9afa9083a7626e2140b7a779 100644 (file)
@@ -257,13 +257,16 @@ Postfix 2.0 </td> </tr>
 <tr> <td> SASL authentication </td> <td>SASL_README</td> <td>
 Postfix 1.0 </td> </tr>
 
+<tr> <td> STARTTLS session encryption </td> <td>TLS_README</td> <td>
+Postfix 2.2 </td> </tr>
+
 </table>
 
 </blockquote>
 
-<p> Note: support for TLS (encrypted SMTP sessions and certificate
-based authentication) and for IP version 6 is still separate from
-Postfix but is expected to be merged soon. </p>
+<p> Note: IP version 6 support is compiled into Postfix on operating
+systems that have IPv6 support. See the IPV6_README file for details.
+</p>
 
 <h3>4.4 - Overriding built-in parameter default settings</h3>
 
index c5e18f55ed9d0de76a3ff7e91d28c214ee8ef095..cda9815e787b6e0089b6ebb58473856bf77a57b4 100644 (file)
@@ -31,6 +31,7 @@ HTML  = ../html/ADDRESS_CLASS_README.html \
        ../html/SMTPD_POLICY_README.html \
        ../html/SMTPD_PROXY_README.html \
        ../html/STANDARD_CONFIGURATION_README.html \
+       ../html/TLS_README.html \
        ../html/TUNING_README.html \
        ../html/UUCP_README.html ../html/ULTRIX_README.html \
        ../html/VERP_README.html ../html/VIRTUAL_README.html \
@@ -63,6 +64,7 @@ README        = ../README_FILES/ADDRESS_CLASS_README \
        ../README_FILES/SMTPD_ACCESS_README \
        ../README_FILES/SMTPD_POLICY_README ../README_FILES/SMTPD_PROXY_README \
        ../README_FILES/STANDARD_CONFIGURATION_README \
+       ../README_FILES/TLS_README \
        ../README_FILES/TUNING_README \
        ../README_FILES/UUCP_README ../README_FILES/ULTRIX_README \
        ../README_FILES/VERP_README ../README_FILES/VIRTUAL_README \
@@ -243,6 +245,9 @@ clobber:
 ../html/XFORWARD_README.html: XFORWARD_README.html
        $(POSTLINK) $? >$@
 
+../html/TLS_README.html: TLS_README.html
+       $(POSTLINK) $? >$@
+
 ../README_FILES/ADDRESS_CLASS_README: ADDRESS_CLASS_README.html
        $(HT2READ) $? >$@
 
@@ -372,6 +377,9 @@ clobber:
 ../README_FILES/XFORWARD_README: XFORWARD_README.html
        $(HT2READ) $? >$@
 
+../README_FILES/TLS_README: TLS_README.html
+       $(HT2READ) $? >$@
+
 ../README_FILES/AAAREADME: ../html/index.html $(MAKEAAA)
        $(MAKEAAA) ../html/index.html | $(HT2READ) >$@
 
diff --git a/postfix/proto/TLS_README.html b/postfix/proto/TLS_README.html
new file mode 100644 (file)
index 0000000..c29e8e9
--- /dev/null
@@ -0,0 +1,1389 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix TLS Support </title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix TLS Support
+</h1>
+
+<hr>
+
+<h2> WARNING </h2>
+
+<p> By turning on TLS support in Postfix, you not only get the
+ability to encrypt mail and to authenticate clients or servers.
+You also turn on thousands and thousands of lines of OpenSSL library
+code.  Assuming that OpenSSL is written as carefully as Wietse's
+own code, every 1000 lines introduce one additional bug into
+Postfix.  </p>
+
+<h2> Purpose of this document </h2>
+
+<p> This document describes how to build Postfix with Transport
+Layer Security (TLS) support in the Postfix SMTP client and Postfix
+SMTP server, and how to configure the TLS manager daemon that
+maintains the Pseudo Random Number Generator (PRNG) pool and the
+TLS session cache information. </p>
+
+<p> Topics covered in this document: </p>
+
+<ul>
+
+<li><a href="#build_tls">Building Postfix with TLS support</a>
+
+<li><a href="#server_tls">SMTP Server specific settings</a>
+
+<li> <a href="#client_tls">SMTP Client specific settings</a>
+
+<li><a href="#tlsmgr_controls"> TLS manager specific settings </a>
+
+<li><a href="#problems"> Reporting problems </a>
+
+<li><a href="#compat">Compatibility with Postfix < 2.2 TLS support</a>
+
+<li><a href="#credits"> Credits </a>
+
+</ul>
+
+<p> And last but not least, for the impatient: </p>
+
+<ul>
+
+<li><a href="#quick-start">Getting started, quick and dirty</a>
+
+</ul>
+
+<h2><a name="build_tls">Building Postfix with TLS support</a></h2>
+
+<p> To build Postfix with TLS support, first we need to generate
+the <tt>make(1)</tt> files with the necessary definitions. This is
+done by invoking the command "<tt>make makefiles</tt> in the Postfix
+top-level directory and with arguments as shown next. </p>
+
+<ul>
+
+<li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
+in directory <tt>/usr/include/openssl</tt>, and the OpenSSL libraries
+(such as <tt>libssl.so</tt> and <tt>libcrypto.so</tt>) are in
+directory <tt>/usr/lib</tt>:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS" AUXLIBS="-lssl -lcrypto"</b>
+</pre>
+</blockquote>
+
+<li> <p> If the OpenSSL include files (such as <tt>ssl.h</tt>) are
+in directory <tt>/usr/local/include/openssl</tt>, and the OpenSSL
+libraries (such as <tt>libssl.so</tt> and <tt>libcrypto.so</tt>)
+are in directory <tt>/usr/local/lib</tt>:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \
+    AUXLIBS="-L/usr/local/lib -lssl -lcrypto" </b>
+</pre>
+</blockquote>
+
+</ul>
+
+<p> If you need to apply other customizations (such as Berkeley DB
+databases, MySQL, PosgreSQL, LDAP or SASL), see the respective
+Postfix README documents, and combine their "<tt>make makefiles</tt>"
+instructions with the instructions above:  </p>
+
+<blockquote>
+<pre>
+% <b>make tidy</b> # if you have left-over files from a previous build
+% <b>make makefiles CCARGS="-DUSE_TLS \
+    <i>(other -D or -I options)</i>" \
+    AUXLIBS="-lssl -lcrypto \
+    <i>(other -l options for libraries in /usr/lib)</i> \
+    <i>(-L/path/name + -l options for other libraries)</i>"</b>
+</pre>
+</blockquote>
+
+<p> To complete the build process, see the Postfix INSTALL
+instructions. Postfix has TLS support turned off by default, so
+you can start using Postfix as soon as it is installed.  </p>
+
+<h2><a name="server_tls">SMTP Server specific settings</a></h2>
+
+<p> Topics covered in this section: </p>
+
+<ul>
+
+<li><a href="#server_cert_key">Server-side certificate and private
+key configuration </a>
+
+<li><a href="#server_logging"> Server-side TLS activity logging
+</a>
+
+<li><a href="#server_enable">Enabling TLS in the Postfix SMTP server </a>
+
+<li><a href="#server_vrfy_client">Client certificate verification</a>
+
+<li><a href="#server_tls_auth">Supporting AUTH over TLS only</a>
+
+<li><a href="#server_tls_cache">Server-side TLS session cache</a>
+
+<li><a href="#server_access">Server access control</a>
+
+<li><a href="#server_cipher">Server-side cipher controls</a>
+
+<li><a href="#server_misc"> Miscellaneous server controls</a>
+
+</ul>
+
+<h3><a name="server_cert_key">Server-side certificate and private
+key configuration </a> </h3>
+
+<p> In order to use TLS, the Postfix SMTP server needs a certificate
+and a private key. Both must be in "pem" format. The private key
+must not be encrypted, meaning:  the key must be accessible without
+password.  Both certificate and private key may be in the same
+file.  </p>
+
+<p> Both RSA and DSA certificates are supported. Typically you will
+only have RSA certificates issued by a commercial CA. In addition,
+the tools supplied with OpenSSL will by default issue RSA certificates.
+You can have both at the same time, in which case the cipher used
+determines which certificate is presented. For Netscape and OpenSSL
+clients without special cipher choices, the RSA certificate is
+preferred. </p>
+
+<p> In order for remote SMTP clients to check the Postfix SMTP
+server certificates, the CA certificate (in case of a certificate
+chain, all CA certificates) must be available.  You should add
+these certificates to the server certificate, the server certificate
+first, then the issuing CA(s).  </p>
+
+<p> Example: the certificate for "server.dom.ain" was issued by
+"intermediate CA" which itself has a certificate issued by "root
+CA".  Create the server.pem file with: </p>
+
+<blockquote>
+<pre>
+% <b>cat server_cert.pem intermediate_CA.pem &gt; server.pem</b>
+</pre>
+</blockquote>
+
+<p> A Postfix SMTP server certificate supplied here must be usable
+as SSL server certificate and hence pass the "openssl verify -purpose
+sslserver ..." test. </p>
+
+<p> A client that trusts the root CA has a local copy of the root
+CA certificate, so it is not necessary to include the root CA
+certificate here.  Leaving it out of the "server.pem" file reduces
+the overhead of the TLS exchange. </p>
+
+<p> If you want the Postfix SMTP server to accept remote SMTP client
+certificates issued by these CAs, append the root certificate to
+$smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory.  When
+you configure trust in a root CA, it is not necessary to explicitly trust
+intermediary CAs signed by the root CA, unless $smtpd_tls_verify_depth
+is less than the number of CAs in the certificate chain for the clients
+of interest. With a verify depth of 1 you can only verify certificates
+directly signed by a trusted CA, and all trusted intermediary CAs need to
+be configured explicitly. With a verify depth of 2 you can verify clients
+signed by a root CA or a direct intermediary CA (so long as the client
+is correctly configured to supply its intermediate CA certificate). </p>
+
+<p> RSA key and certificate examples: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_cert_file = /etc/postfix/server.pem
+    smtpd_tls_key_file = $smtpd_tls_cert_file
+</pre>
+</blockquote>
+
+<p> Their DSA counterparts: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
+    smtpd_tls_dkey_file = $smtpd_tls_dcert_file
+</pre>  
+</blockquote>
+
+<p> To verify a remote SMTP client certificate, the Postfix SMTP
+server needs to trust the certificates of the issuing certification
+authorities. These certificates in "pem" format can be stored in a
+single $smtpd_tls_CAfile or in multiple files, one CA per file in
+the $smtpd_tls_CApath directory. If you use a directory, don't forget
+to create the necessary "hash" links with: </p>
+
+<blockquote>
+<pre>
+# <b>$OPENSSL_HOME/bin/c_rehash <i>/path/to/directory</i> </b>
+</pre>
+</blockquote>
+
+<p> The $smtpd_tls_CAfile contains the CA certificates of one or
+more trusted CAs. The file is opened (with root privileges) before
+Postfix enters the optional chroot jail and so need not be accessible
+from inside the chroot jail. </p>
+
+<p> Additional trusted CAs can be specified via the $smtpd_tls_CApath
+directory, in which case the certificates are read (with $mail_owner
+privileges) from the files in the directory when the information
+is needed. Thus, the $smtpd_tls_CApath directory needs to be
+accessible inside the optional chroot jail. </p>
+
+<p> When you configure Postfix to request client certificates (by
+setting $smtpd_tls_asck_ccert = yes), any certificates in
+$smtpd_tls_CAfile are sent to the client, in order to allow it to
+choose an identity signed by a CA you trust. If no $smtpd_tls_CAfile
+is specified, no preferred CA list is sent, and the client is free
+to choose an identity signed by any CA. Many clients use a fixed
+identity regardless of the preferred CA list and you may be able
+to reduce TLS negotiation overhead by installing client CA certificates
+mostly or only in $smtpd_tls_CApath. In the latter case you need
+not specify a $smtpd_tls_CAfile. </p>
+
+<p> Note, that unless client certificates are used to allow greater
+access to TLS authenticated clients, it is best to not ask for
+client certificates at all, as in addition to increased overhead
+some clients (notably in some cases qmail) are unable to complete
+the TLS handshake when client certificates are requested. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_CAfile = /etc/postfix/CAcert.pem
+    smtpd_tls_CApath = /etc/postfix/certs
+</pre>
+</blockquote>
+
+<h3><a name="server_logging"> Server-side TLS activity logging </a> </h3>
+
+<p> To get additional information about Postfix SMTP server TLS
+activity you can increase the loglevel from 0..4. Each logging
+level also includes the information that is logged at a lower
+logging level. </p>
+
+<blockquote>
+
+<table>
+
+<tr> <td> 0 </td> <td> Disable logging of TLS activity.</td> </tr>
+
+<tr> <td> 1 </td> <td> Log TLS handshake and certificate information.
+</td> </tr>
+
+<tr> <td> 2 </td> <td> Log levels during TLS negotiation.  </td>
+</tr>
+
+<tr> <td> 3 </td> <td> Log hexadecimal and ASCII dump of TLS
+negotiation process </td> </tr>
+
+<tr> <td> 4 </td> <td> Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> Use loglevel 3 only in case of problems. Use of loglevel 4 is
+strongly discouraged. </p>
+
+<p> Example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_loglevel = 0
+</pre>
+</blockquote>
+
+<p> To include information about the protocol and cipher used as
+well as the client and issuer CommonName into the "Received:"
+message header, set the smtpd_tls_received_header variable to true.
+The default is no, as the information is not necessarily authentic.
+Only information recorded at the final destination is reliable,
+since the headers may be changed by intermediate servers. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_received_header = yes
+</pre>
+</blockquote>
+
+<h3><a name="server_enable">Enabling TLS in the Postfix SMTP server </a> </h3>
+
+<p> By default, TLS is disabled in the Postfix SMTP server, so no
+difference to plain Postfix is visible.  Explicitly switch it on
+using "smtpd_use_tls = yes". </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_use_tls = yes
+</pre>
+</blockquote>
+
+<p> With this, Postfix SMTP server announces STARTTLS support to
+SMTP clients, but does not require that clients use TLS encryption.
+</p>
+
+<p> Note: when an unprivileged user invokes "sendmail -bs", STARTTLS
+is never offered due to insufficient privileges to access the server
+private key. This is intended behavior. </p>
+
+<p> You can ENFORCE the use of TLS, so that the Postfix SMTP server
+announces STARTTLS and accepts no mail without TLS encryption, by
+setting "smtpd_enforce_tls = yes". According to RFC 2487 this MUST
+NOT be applied in case of a publicly-referenced Postfix SMTP server.
+This option is off by default and should only seldom be used. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_enforce_tls = yes
+</pre>
+</blockquote>
+
+<p> TLS is sometimes used in the non-standard "wrapper" mode where
+a server always uses TLS, instead of announcing STARTTLS support
+and waiting for clients to request TLS service. Some clients, namely
+Outlook [Express] prefer the "wrapper" mode.  This is true for OE
+(Win32 &lt; 5.0 and Win32 &gt;=5.0 when run on a port&lt;&gt;25
+and OE (5.01 Mac on all ports). </p>
+
+<p> It is strictly discouraged to use this mode from main.cf. If
+you want to support this service, enable a special port in master.cf
+and specify "-o smtpd_tls_wrappermode = yes" as an smtpd(8) command
+line option.  Port 465 (smtps) was once chosen for this feature.
+</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/master.cf:
+    smtps    inet  n       -       n       -       -       smtpd
+      -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
+</pre>
+</blockquote>
+
+<h3><a name="server_vrfy_client">Client certificate verification</a> </h3>
+
+<p> To receive a remote SMTP client certificate, the Postfix SMTP
+server must explicitly ask for one (any contents of $smtpd_tls_CAfile
+are also sent to the client as a hint for choosing a certificate
+from a suitable CA). Unfortunately, Netscape clients will either
+complain if no matching client certificate is available or will
+offer the user client a list of certificates to choose from.
+Additionally some MTAs (notably some versions of qmail) are unable
+to complete TLS negotiation when client certificates are requested,
+and abort the SMTP session. So this option is "off" by default.
+You will however need the certificate if you want to use certificate
+based relaying with, for example, the permit_tls_clientcerts
+feature.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_ask_ccert = no
+</pre>
+</blockquote>
+
+<p> You may also decide to REQUIRE a remote SMTP client certificate
+before allowing TLS connections.  This feature is included for
+completeness, and implies "smtpd_tls_ask_ccert = yes".  </p>
+
+<p> Please be aware, that this will inhibit TLS connections without
+a proper client certificate and that it makes sense only when
+non-TLS submission is disabled (smtpd_enforce_tls = yes). Otherwise,
+clients could bypass the restriction by simply not using STARTTLS
+at all. </p>
+
+<p> When TLS is not enforced, the connection will be handled as
+if only "smtpd_tls_ask_ccert = yes" is specified, and a warning is
+logged. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_req_ccert = no
+</pre>
+</blockquote>
+
+<p> A client certificate verification depth of 1 is sufficient if
+the certificate is directly issued by a CA listed in the CA file.
+The default value (5) should also suffice for longer chains (root
+CA issues special CA which then issues the actual certificate...)
+</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_ccert_verifydepth = 5
+</pre>
+</blockquote>
+
+<h3><a name="server_tls_auth">Supporting AUTH over TLS only</a></h3>
+
+<p> Sending AUTH data over an unencrypted channel poses a security
+risk. When TLS layer encryption is required (smtpd_enforce_tls =
+yes), the Postfix SMTP server will announce and accept AUTH only
+after the TLS layer has been activated with STARTTLS. When TLS
+layer encryption is optional (smtpd_enforce_tls = no), it may
+however still be useful to only offer AUTH when TLS is active. To
+maintain compatibility with non-TLS clients, the default is to
+accept AUTH without encryption. In order to change this behavior,
+set "smtpd_tls_auth_only = yes". </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_auth_only = no
+</pre>
+</blockquote>
+
+<h3><a name="server_tls_cache">Server-side TLS session cache</a> </h3>
+
+<p> The Postfix SMTP server and the remote SMTP client negotiate
+a session, which takes some computer time and network bandwidth.
+By default, this session information is cached only in the smtpd(8)
+process actually using this session and is lost when the process
+terminates.  To share the session information between multiple
+smtpd(8) processes, a persistent session cache can be used. You
+can specify any database type that can store objects of several
+kbytes and that supports the sequence operator. DBM databases are
+not suitable because they can only store small objects. The cache
+is maintained by the tlsmgr(8) process, so there is no problem with
+concurrent access. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
+</pre>
+</blockquote>
+
+<p> Cached Postfix SMTP server session information expires after
+a certain amount of time.  Postfix/TLS does not use the OpenSSL
+default of 300s, but a longer time of 3600sec (=1 hour). RFC 2246
+recommends a maximum of 24 hours.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_session_cache_timeout = 3600s
+</pre>
+</blockquote>
+
+<h3><a name="server_access">Server access control</a> </h3>
+
+<p> Postfix TLS support introduces two additional features for
+Postfix SMTP server access control:  </p>
+
+<blockquote>
+
+<dl>
+
+<dt> permit_tls_clientcerts </dt> <dd> <p> Allow the remote SMTP
+client SMTP request if the client certificate passes verification,
+and if its fingerprint is listed in the list of client certificates
+(see relay_clientcerts discussion below). </p> </dd>
+
+<dt> permit_tls_all_clientcerts </dt> <dd> <p> Allow the remote
+client SMTP request if the client certificate passes verification.
+</p> </dd>
+
+</dl>
+
+</blockquote>
+
+<p> The permit_tls_all_clientcerts feature must be used with caution,
+because it can result in too many access permissions.  Use this
+feature only if a special CA issues the client certificates, and
+only if this CA is listed as trusted CA. If other CAs are trusted,
+any owner of a valid client certificate would be authorized.
+The permit_tls_all_clientcerts feature can be practical for a
+specially created email relay server.  </p>
+
+<p> It is however recommended to stay with the permit_tls_clientcerts
+feature and list all certificates via $relay_clientcerts, as
+permit_tls_all_clientcerts does not permit any control when a
+certificate must no longer be used (e.g. an employee leaving). </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_recipient_restrictions = 
+        ... 
+        permit_tls_clientcerts 
+        reject_unauth_destination
+        ...
+</pre>
+</blockquote>
+
+<p> The Postfix list manipulation routines give special treatment
+to whitespace and some other characters, making the use of certificate
+names unpractical.  Instead we use the certificate fingerprints as
+they are difficult to fake but easy to use for lookup.  Postfix
+lookup tables are in the form of (key, value) pairs.  Since we only
+need the key, the value can be chosen freely, e.g.  the name of
+the user or host.</p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+
+/etc/postfix/relay_clientcerts:
+    D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
+</pre>
+</blockquote>
+
+<h3><a name="server_cipher">Server-side cipher controls</a> </h3>
+
+<p> To influence the Postfix SMTP server cipher selection scheme,
+you can give cipherlist string.  A detailed description would go
+to far here; please refer to the OpenSSL documentation.  If you
+don't know what to do with it, simply don't touch it and leave the
+(openssl-)compiled in default! </p>
+
+<p> DO NOT USE " to enclose the string, specify just the string!!! </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_cipherlist = DEFAULT
+</pre>
+</blockquote>
+
+<p> If you want to take advantage of ciphers with EDH, DH parameters
+are needed.  Instead of using the built-in DH parameters for both
+1024bit and 512bit, it is better to generate "own" parameters,
+since otherwise it would "pay" for a possible attacker to start a
+brute force attack against parameters that are used by everybody.
+For this reason, the parameters chosen are already different from
+those distributed with other TLS packages. </p>
+
+<p> To generate your own set of DH parameters, use: </p>
+
+<blockquote>
+<pre>
+% <b>openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024</b>
+% <b>openssl gendh -out /etc/postfix/dh_512.pem -2 -rand /var/run/egd-pool 512</b>
+</pre>
+</blockquote>
+
+<p> Examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+    smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
+</pre>
+</blockquote>
+
+<h3><a name="server_misc"> Miscellaneous server controls</a> </h3>
+
+<p> The smtpd_starttls_timeout parameter limits the time of Postfix
+SMTP server write and read operations during TLS startup and shutdown
+handshake procedures.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtpd_starttls_timeout = 300s
+</pre>
+</blockquote>
+
+<h2> <a name="client_tls">SMTP Client specific settings</a> </h2>
+
+<p> Topics covered in this section: </p>
+
+<ul>
+
+<li><a href="#client_cert_key">Client-side certificate and private
+key configuration </a>
+
+<li><a href="#client_logging"> Client-side TLS activity logging
+</a>
+
+<li><a href="#client_tls_cache">Client-side TLS session cache</a>
+
+<li><a href="#client_tls"> Enabling TLS in the Postfix SMTP client </a>
+
+<li><a href="#client_vrfy_server">Server certificate verification</a>
+
+<li> <a href="#client_cipher">Client-side cipher controls </a>
+
+<li> <a href="#client_misc"> Miscellaneous client controls </a>
+
+</ul>
+
+<h3><a name="client_cert_key">Client-side certificate and private
+key configuration </a> </h3>
+
+<p> During TLS startup negotiation the Postfix SMTP client may present
+a certificate to the remote SMTP server.  The Netscape client is
+rather clever here and lets the user select between only those
+certificates that match CA certificates offered by the remote SMTP
+server. As the Postfix SMTP client uses the "SSL_connect()" function
+from the OpenSSL package, this is not possible and we have to choose
+just one certificate.  So for now the default is to use _no_
+certificate and key unless one is explicitly specified here. </p>
+
+<p> Both RSA and DSA certificates are supported.  You can have both
+at the same time, in which case the cipher used determines which
+certificate is presented.  </p>
+
+<p> It is possible for the Postfix SMTP client to use the same
+key/certificate pair as the Postfix SMTP server.  If a certificate
+is to be presented, it must be in "pem" format. The private key
+must not be encrypted, meaning: it must be accessible without
+password. Both parts (certificate and private key) may be in the
+same file. </p>
+
+<p> In order for remote SMTP servers to verify the Postfix SMTP
+client certificates, the CA certificate (in case of a certificate
+chain, all CA certificates) must be available.  You should add
+these certificates to the client certificate, the client certificate
+first, then the issuing CA(s). </p>
+
+<p> Example: the certificate for "client.example.com" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the client.pem file with: </p>
+
+<blockquote>
+<pre>
+% <b>cat client_cert.pem intermediate_CA.pem &gt; client.pem </b>
+</pre>
+</blockquote>
+
+<p> A Postfix SMTP client certificate supplied here must be usable
+as SSL client certificate and hence pass the "openssl verify -purpose
+sslclient ..." test. </p>
+
+<p> A server that trusts the root CA has a local copy of the root
+CA certificate, so it is not necessary to include the root CA
+certificate here. Leaving it out of the "client.pem" file reduces
+the overhead of the TLS exchange. </p>
+
+<p> If you want the Postfix SMTP client to accept remote SMTP server
+certificates issued by these CAs, append the root certificate to
+$smtp_tls_CAfile or install it in the $smtp_tls_CApath directory.  When
+you configure trust in a root CA, it is not necessary to explicitly trust
+intermediary CAs signed by the root CA, unless $smtp_tls_verify_depth
+is less than the number of CAs in the certificate chain for the servers
+of interest. With a verify depth of 1 you can only verify certificates
+directly signed by a trusted CA, and all trusted intermediary CAs need to
+be configured explicitly. With a verify depth of 2 you can verify servers
+signed by a root CA or a direct intermediary CA (so long as the server
+is correctly configured to supply its intermediate CA certificate). </p>
+
+<p> RSA key and certificate examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_cert_file = /etc/postfix/client.pem
+    smtp_tls_key_file = $smtp_tls_cert_file
+</pre>
+</blockquote>
+
+<p> Their DSA counterparts: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
+    smtp_tls_dkey_file = $smtpd_tls_cert_file
+</pre>  
+</blockquote>
+
+<p> To verify a remote SMTP server certificate, the Postfix SMTP
+client needs to trust the certificates of the issuing certification
+authorities. These certificates in "pem" format can be stored in a
+single $smtp_tls_CAfile or in multiple files, one CA per file in
+the $smtp_tls_CApath directory. If you use a directory, don't forget
+to create the necessary "hash" links with: </p>
+
+<blockquote>
+<pre>
+# <b>$OPENSSL_HOME/bin/c_rehash <i>/path/to/directory</i> </b>
+</pre>
+</blockquote>
+
+<p> The $smtp_tls_CAfile contains the CA certificates of one or more
+trusted CAs. The file is opened (with root privileges) before Postfix
+enters the optional chroot jail and so need not be accessible from inside the
+chroot jail. </p>
+
+<p> Additional trusted CAs can be specified via the $smtp_tls_CApath
+directory, in which case the certificates are read (with $mail_owner
+privileges) from the files in the directory when the information
+is needed. Thus, the $smtp_tls_CApath directory needs to be accessible
+inside the optional chroot jail.  </p>
+
+<p> The choice between $smtp_tls_CAfile and $smtpd_tls_CApath is
+a space/time tradeoff. If there are many trusted CAs, the cost of
+preloading them all into memory may not pay off in reduced access time
+when the certificate is needed.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_CAfile = /etc/postfix/CAcert.pem
+    smtp_tls_CApath = /etc/postfix/certs
+</pre>
+</blockquote>
+
+<h3><a name="client_logging"> Client-side TLS activity logging </a> </h3>
+
+<p> To get additional information about Postfix SMTP client TLS
+activity you can increase the loglevel from 0..4. Each logging
+level also includes the information that is logged at a lower
+logging level. </p>
+
+<blockquote>
+
+<table>
+
+<tr> <td> 0 </td> <td> Disable logging of TLS activity.</td> </tr>
+
+<tr> <td> 1 </td> <td> Log TLS handshake and certificate information.
+</td> </tr>
+
+<tr> <td> 2 </td> <td> Log levels during TLS negotiation.  </td>
+</tr>
+
+<tr> <td> 3 </td> <td> Log hexadecimal and ASCII dump of TLS
+negotiation process </td> </tr>
+
+<tr> <td> 4 </td> <td> Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_loglevel = 0
+</pre>
+</blockquote>
+
+<h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3>
+
+<p> The remote SMTP server and the Postfix SMTP client negotiate a
+session, which takes some computer time and network bandwidth.  By
+default, this session information is cached only in the smtp(8)
+process actually using this session and is lost when the process
+terminates.  To share the session information between multiple
+smtp(8) processes, a persistent session cache can be used. You
+can specify any database type that can store objects of several
+kbytes and that supports the sequence operator. DBM databases are
+not suitable because they can only store small objects. The cache
+is maintained by the tlsmgr(8) process, so there is no problem with
+concurrent access. </p>
+
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_session_cache_database = btree:/etc/postfix/smtp_scache
+</pre>
+</blockquote>
+
+<p> Cached Postfix SMTP client session information expires after
+a certain amount of time.  Postfix/TLS does not use the OpenSSL
+default of 300s, but a longer time of 3600s (=1 hour). RFC 2246
+recommends a maximum of 24 hours.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_session_cache_timeout = 3600s
+</pre>
+</blockquote>
+
+<h3><a name="client_tls"> Enabling TLS in the Postfix SMTP client </a>
+</h3>
+
+<p> By default, TLS is disabled in the Postfix SMTP client, so no
+difference to plain Postfix is visible.  If you enable TLS, the
+Postfix SMTP client will send STARTTLS when TLS support is announced
+by the remote SMTP server. </p>
+
+<p> WARNING: MS Exchange servers will announce STARTTLS support
+even when the service is not configured, so that the TLS handshake
+will fail.  It may be wise to not use this option on your central
+mail hub, as you don't know in advance whether you are going to
+connect to such a host. Instead, use the smtp_tls_per_site
+recipient/site specific options that are described below. </p>
+
+<p> When the TLS handshake fails and no other server is available,
+the Postfix SMTP client defers the delivery attempt, and the mail
+stays in the queue.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_use_tls = yes
+</pre>
+</blockquote>
+
+<p> You can ENFORCE the use of TLS, so that the Postfix SMTP client
+will not deliver mail over unencrypted connections.  In this mode,
+the remote SMTP server hostname must match the information in the
+remote server certificate, and the server certificate must be issued
+by a CA that is trusted by the Postfix SMTP client.  If the remote
+server certificate doesn't verify or the remote SMTP server hostname
+doesn't match, and no other server is available, the delivery
+attempt is deferred and the mail stays in the queue.  </p>
+
+<p> The remote SMTP server hostname used in the check is beyond
+question, as it must be the principal hostname (no CNAME allowed
+here). Checks are performed against all names provided as dNSNames
+in the SubjectAlternativeName. If no dNSNames are specified, the
+CommonName is checked.  The behavior may be changed with the
+smtp_tls_enforce_peername option which is discussed below. </p>
+
+<p> This option is useful only if you know that you will only
+connect to servers that support RFC 2487 _and_ that present server
+certificates that meet the above requirements.  An example would
+be a client only sends email to one specific mailhub that offers
+the necessary STARTTLS support.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_enforce_tls = no
+</pre>
+</blockquote>
+
+<p> As of RFC 2487 the requirements for hostname checking for MTA
+clients are not set. When TLS is required (smtp_enforce_tls = yes),
+the option smtp_tls_enforce_peername can be set to "no" to disable
+strict remote SMTP server hostname checking. In this case, the mail
+delivery will proceed regardless of the CommonName etc. listed in
+the certificate. </p>
+
+<p> Note: the smtp_tls_enforce_peername setting has no effect on
+sessions that are controlled via the smtp_tls_per_site table.  </p>
+
+<p>  Disabling the remote SMTP server hostname verification can
+make sense in closed environment where special CAs are created.
+If not used carefully, this option opens the danger of a
+"man-in-the-middle" attack (the CommonName of this possible attacker
+is logged). </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_enforce_peername = yes
+</pre>
+</blockquote>
+
+<p> Generally, trying TLS can be a bad idea, as some servers offer
+STARTTLS but the negotiation will fail leading to unexplainable
+failures. Instead, it may be a good idea to choose the TLS usage
+policy based on the recipient or the mailhub to which you are
+connecting. </p>
+
+<p> Deciding the TLS usage policy per recipient may be difficult,
+since a single email delivery attempt can involve several recipients.
+Instead, use of TLS is controlled by the Postfix next-hop destination
+domain name and by the remote SMTP server hostname.  If either of these
+matches an entry in the smtp_tls_per_site table, appropriate action
+is taken.  </p>
+
+<p> The remote SMTP server hostname is simply the DNS name of the
+server that the Postfix SMTP client connects to.  The next-hop
+destination is Postfix specific.  By default, this is the domain
+name in the recipient address, but this information can be overruled
+by the transport(5) table or by the relayhost parameter setting.
+In these cases the relayhost etc. must be listed in the smtp_tls_per_site
+table, instead of the recipient domain name. </p>
+
+<p> Format of the table: domain or host names are specified on the
+left-hand side; no wildcards are allowed.  On the right hand side
+specify one of the following keywords:  </p>
+
+<blockquote>
+
+<dl>
+
+<dt> NONE </dt> <dd> Don't use TLS at all. </dd>
+
+<dt> MAY </dt> <dd> Try to use STARTTLS if offered, otherwise use
+the unencrypted connection. NOTE: STARTTLS can be used only if TLS
+is already enabled via main.cf, so that the client TLS engine is
+properly initialized at program startup. </dd>
+
+<dt> MUST </dt> <dd> Require usage of STARTTLS, require that the
+remote SMTP server hostname matches the information in the remote
+SMTP server certificate, and require that the remote SMTP server
+certificate was issued by a trusted CA. </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd> Require usage of STARTTLS, but do
+not require that the remote SMTP server hostname matches the
+information in the remote SMTP server certificate, or that the
+server certificate was issued by a trusted CA. </dd>
+
+</dl>
+
+</blockquote>
+
+<p> The actual TLS usage policy depends not only on whether the
+next-hop destination or remote SMTP server hostname are found in
+the smtp_tls_per_site table, but also on the smtp_enforce_tls
+setting:  </p>
+
+<ul>
+
+<li> <p> If no match was found, the policy is applied as specified
+with smtp_enforce_tls. </p>
+
+<li> <p> If a match was found, and the smtp_enforce_tls policy is
+"enforce", NONE explicitly switches it off; otherwise the "enforce"
+mode is used even for entries that specify MAY. </p>
+
+</ul>
+
+<p> Special hint for TLS enforcement mode:  since no secure DNS
+lookup mechanism is available, mail can be delivered to the wrong
+remote SMTP server. This is not prevented by specifying MUST for
+the next-hop domain name.  The recommended setup is:  specify local
+transport(5) table entries for sensitive domains with explicit
+smtp:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+smtp_tls_per_site table. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
+</pre>
+</blockquote>
+
+<p> As we decide on a "per site" basis whether or not to use TLS,
+it would be good to have a list of sites that offered "STARTTLS".
+We can collect it ourselves with this option. </p>
+
+<p> If the smtp_tls_note_starttls_offer feature is enabled and a
+server offers STARTTLS while TLS is not already enabled for that
+server, the Postfix SMTP client logs a line as follows: </p>
+
+<blockquote>
+<pre>
+postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]
+</pre>
+</blockquote>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_note_starttls_offer = yes
+</pre>
+</blockquote>
+
+<h3><a name="client_vrfy_server">Server certificate verification</a> </h3>
+
+<p> When verifying a remote SMTP server certificate, a verification
+depth of 1 is sufficient if the certificate is directly issued by
+a CA specified with smtp_tls_CAfile or smtp_tls_CApath.  The default
+value of 5 should also suffice for longer chains (root CA issues
+special CA which then issues the actual certificate...) </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_scert_verifydepth = 5
+</pre>
+</blockquote>
+
+<h3> <a name="client_cipher">Client-side cipher controls </a> </h3>
+
+<p> To influence the Postfix SMTP client cipher selection scheme,
+you can give cipherlist string.  A detailed description would go
+to far here; please refer to the OpenSSL documentation.  If you
+don't know what to do with it, simply don't touch it and leave the
+(openssl-)compiled in default! </p>
+
+<p> DO NOT USE " to enclose the string, specify just the string!!! </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_tls_cipherlist = DEFAULT
+</pre>
+</blockquote>
+
+<h3> <a name="client_misc"> Miscellaneous client controls </a> </h3>
+
+<p> The smtp_starttls_timeout parameter limits the time of Postfix
+SMTP client write and read operations during TLS startup and shutdown
+handshake procedures.  In case of problems the Postfix SMTP client
+tries the next network address on the mail exchanger list, and
+defers delivery if no alternative server is available. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_starttls_timeout = 300s
+</pre>
+</blockquote>
+
+<h2><a name="tlsmgr_controls"> TLS manager specific settings </a> </h2>
+
+<p> The security of cryptographic software such as TLS depends
+critically on the ability to generate unpredictable numbers for
+keys and other information. To this end, the tlsmgr(8) process
+maintains a Pseudo Random Number Generator (PRNG) pool.  This is
+queried by the smtp(8) and smtpd(8) processes when they initialize.
+By default, these daemons request 32 bytes, the equivalent to 256
+bits. This is more than sufficient to generate a 128bit (or 168bit)
+session key.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    tls_daemon_random_bytes = 32
+</pre>
+</blockquote>
+
+<p> In order to feed its in-memory PRNG pool, the tlsmgr(8) reads
+entropy from an external source, both at startup and during run-time.
+Specify a good entropy source, like EGD or /dev/urandom; be sure
+to only use non-blocking sources.  If the entropy source is not a
+regular file, you must prepend the source type to the source name:
+"dev:" for a device special file, or "egd:" for a source with EGD
+compatible socket interface.  </p>
+
+<p> Examples (specify only one in main.cf): </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    tls_random_source = dev:/dev/urandom
+    tls_random_source = egd:/var/run/egd-pool
+</pre>
+</blockquote>
+
+<p> By default, tlsmgr(8) reads 32 bytes from the external entropy
+source at each seeding event.  This amount (256bits) is more than
+sufficient for generating a 128bit symmetric key.  With EGD and
+device entropy sources, the tlsmgr(8) limits the amount of data
+read at each step to 255 bytes. If you specify a regular file as
+entropy source, a larger amount of data can be read.  </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    tls_random_bytes = 32
+</pre>
+</blockquote>
+
+<p> In order to update its in-memory PRNG pool, the tlsmgr(8)
+queries the external entropy source again after a pseudo-random
+amount of time. The time is calculated using the PRNG, and is
+between 0 and the maximal time specified with tls_random_reseed_period.
+The default maximal time interval is 1 hour. </p>
+
+<p> Example: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    tls_random_reseed_period = 3600s
+</pre>
+</blockquote>
+
+<p> The tlsmgr(8) process saves the PRNG state to a persistent
+exchange file at regular times and when the process terminates, so
+that it can recover the PRNG state the next time it starts up.
+This file is created when it does not exist. Its default location
+is under the Postfix configuration directory, which is not the
+proper place for information that is modified by Postfix.  Instead,
+the file location should probably be on the /var partition (but
+<b>not</b> inside the chroot jail).  </p>
+
+<p> Examples: </p>
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    tls_random_exchange_name = /etc/postfix/prng_exch
+    tls_random_prng_update_period = 3600s
+</pre>
+</blockquote>
+
+<h2><a name="quick-start">Getting started, quick and dirty</a></h2>
+
+<p> The following steps will get you started quickly. Because you
+sign your own Postfix public key certificate, you get TLS encryption
+but no TLS authentication.  This is sufficient for testing, and
+for exchanging email with sites that you have no trust relationship
+with.  For real authentication, your Postfix public key certificate
+needs to be signed by a recognized Certificate Authority, and
+Postfix needs to be configured with a list of public key certificates
+of Certificate Authorities, so that Postfix can verify the public key
+certificates of remote hosts. </p>
+
+<p> In the examples below, user input is shown in <b><tt>bold</tt></b>
+font, and a "<tt>#</tt>" prompt indicates a super-user shell. </p>
+
+<ul>
+
+<li> <p> Become your own Certificate Authority, so that you can
+sign your own public keys. This example uses the CA.pl script that
+ships with OpenSSL.  By default, OpenSSL installs this as
+<tt>/usr/local/ssl/misc/CA.pl</tt>, but your mileage may vary. 
+The script creates a private key in <tt>./demoCA/private/cakey.pem</tt>
+and a public key in <tt>./demoCA/cacert.pem</tt>.</p>
+
+<blockquote>
+<pre>
+% <b>/usr/local/ssl/misc/CA.pl -newca</b>
+CA certificate filename (or enter to create)
+
+Making CA certificate ...
+Using configuration from /etc/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+....................++++++
+.....++++++
+writing new private key to './demoCA/private/cakey.pem'
+Enter PEM pass phrase:<b>whatever</b>
+</pre>
+</blockquote>
+
+<li> <p> Create an unpassworded private key for host FOO and create
+an unsigned public key certificate. </p>
+
+<blockquote>
+<pre>
+% <b>openssl req -new -nodes -keyout FOO-key.pem -out FOO-req.pem -days 365</b>
+Using configuration from /etc/ssl/openssl.cnf
+Generating a 1024 bit RSA private key
+........................................++++++
+....++++++
+writing new private key to 'FOO-key.pem'
+-----
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:<b>US</b>
+State or Province Name (full name) [Some-State]:<b>New York</b>
+Locality Name (eg, city) []:<b>Westchester</b>
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:<b>Porcupine</b>
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:<b>FOO</b>
+Email Address []:<b>wietse@porcupine.org</b>
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:<b>whatever</b>
+An optional company name []:
+</pre>
+</blockquote>
+
+<li> <p> Sign the public key certificate for host FOO with the
+Certification Authority private key that we created a few
+steps ago. </p>
+
+<blockquote>
+<pre>
+% <b>openssl ca -out FOO-cert.pem -infiles FOO-req.pem</b>
+Uing configuration from /etc/ssl/openssl.cnf
+Enter PEM pass phrase:<b>whatever</b>
+Check that the request matches the signature
+Signature ok
+The Subjects Distinguished Name is as follows
+countryName           :PRINTABLE:'US'
+stateOrProvinceName   :PRINTABLE:'New York'
+localityName          :PRINTABLE:'Westchester'
+organizationName      :PRINTABLE:'Porcupine'
+commonName            :PRINTABLE:'FOO'
+emailAddress          :IA5STRING:'wietse@porcupine.org'
+Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365 days)
+Sign the certificate? [y/n]:<b>y</b>
+
+
+1 out of 1 certificate requests certified, commit? [y/n]<b>y</b>
+Write out database with 1 new entries
+Data Base Updated
+</pre>
+</blockquote>
+
+<li> <p> Install the host private key, the host public key certificate,
+and the Certification Authority certificate files.  This requires
+super-user privileges. </p>
+
+<blockquote>
+<pre>
+# <b>cp demoCA/cacert.pem FOO-key.pem FOO-cert.pem /etc/postfix</b>
+# <b>chmod 644 /etc/postfix/FOO-cert.pem /etc/postfix/cacert.pem</b>
+# <b>chmod 400 /etc/postfix/FOO-key.pem</b>
+</pre>
+</blockquote>
+
+<li> <p> Configure Postfix, by adding the following to
+<tt>/etc/postfix/main.cf</tt>. </p>
+
+<blockquote>
+<pre>
+smtp_tls_CAfile = /etc/postfix/cacert.pem
+smtp_tls_cert_file = /etc/postfix/FOO-cert.pem
+smtp_tls_key_file = /etc/postfix/FOO-key.pem
+smtp_tls_session_cache_database = btree:/var/run/smtp_tls_session_cache
+smtp_use_tls = yes
+smtpd_tls_CAfile = /etc/postfix/cacert.pem
+smtpd_tls_cert_file = /etc/postfix/FOO-cert.pem
+smtpd_tls_key_file = /etc/postfix/FOO-key.pem
+smtpd_tls_received_header = yes
+smtpd_tls_session_cache_database = btree:/var/run/smtpd_tls_session_cache
+smtpd_use_tls = yes
+tls_random_source = dev:/dev/urandom
+</pre>
+</blockquote>
+
+</ul>
+
+
+<h2> <a name="problems"> Reporting problems </a> </h2>
+
+<p> When reporting a problem, please be thorough in the report.
+Patches, when possible, are greatly appreciated too. </p>
+
+<p> Please differentiate when possible between: </p>
+
+<ul>
+
+<li> Problems in the TLS code: &lt;postfix_tls@aet.tu-cottbus.de&gt;
+
+<li> Problems in vanilla Postfix: &lt;postfix-users@postfix.org&gt;
+
+</ul>
+
+<h2><a name="compat">Compatibility with Postfix <2.2 TLS support</a></h2>
+
+<p> Postfix version 2.2 TLS support is based on the Postfix/TLS
+patch by Lutz J&auml;nicke, but differs in a few minor ways. </p>
+
+<ul>
+
+<li> <p> main.cf: Use <b>btree</b> instead of <b>sdbm</b> for TLS
+session cache databases. </p>
+
+<p> TLS session cache databases are now accessed only by the
+tlsmgr(8) process, so there are no more concurrency issues. Although
+Postfix has an <b>sdbm</b> client, the <b>sdbm</b> library (1000
+lines of code) is not included with Postfix. </p>
+
+<p> TLS session caches can use any database that can store objects
+of several kbytes or more, and that implements the sequence operation.
+In most cases, <b>btree</b> databases should be adequate.  </p>
+
+<p> NOTE:  You cannot use <b>dbm</b> databases. TLS session objects
+are too large. </p>
+
+<li> <p> master.cf: Specify <b>unix</b> instead of <b>fifo</b> as
+the tlsmgr service type. </p>
+
+<p> The smtp(8) and smtpd(8) processes now use a client-server
+protocol in order to access the tlsmgr(8) pseudo-random number
+generation (PRNG) pool, and in order to access the TLS session
+cache databases. Such a protocol cannot be run across fifos. </p>
+
+</ul>
+
+<h2><a name="credits">Credits </a> </h2>
+
+<ul>
+
+<li> TLS support for Postfix was originally developed by  Lutz
+J&auml;nicke at Cottbus Technical University.
+
+<li> Wietse Venema adopted the code, did some restructuring, and
+compiled this part of the documentation from Lutz's documents.
+
+</ul>
+
+</body>
+
+</html>
index 2cc9fa1d8c7f5d3715703e2f092cf635932207a9..2fb5fcb45a82c3e74e0a6e1279e3ced485ad7f62 100644 (file)
@@ -1558,7 +1558,8 @@ Note: you need to stop and start Postfix when this parameter changes.
 
 <p> When inet_interfaces specifies just one IPv4 and/or IPv6 address
 that is not a loopback address, the Postfix SMTP client will use
-this address as the IP source address for outbound mail. </p>
+this address as the IP source address for outbound mail. Support
+for IPv6 is available in Postfix version 2.2 and later. </p>
 
 <p>
 On a multi-homed firewall with separate Postfix instances listening on the
@@ -1602,6 +1603,8 @@ or accepting connections. Specify one or more of "ipv4" or "ipv6",
 separated by whitespace or commas. The form "all" is equivalent to
 "ipv4, ipv6". </p>
 
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
 <p> Note: you MUST stop and start Postfix after changing this
 parameter. </p>
 
@@ -1625,8 +1628,6 @@ Postfix will do DNS type AAAA record lookups. </p>
 client will attempt to connect via IPv6 before attempting to use
 IPv4.  </p>
 
-<p> This feature is available in Postfix version 2.2 and later. </p>
-
 <p>
 Examples:
 </p>
@@ -3354,6 +3355,8 @@ An optional numerical network address that the SMTP client should
 bind to when making an IPv6 connection.
 </p>
 
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
 <p>
 This can be specified in the main.cf file for all SMTP clients, or
 it can be specified in the master.cf file for a specific client,
@@ -3374,8 +3377,6 @@ inet_interfaces documentation for more detail. </p>
 <p> Note 2: address information may be enclosed inside <tt>[]</tt>,
 but this form is not recommended. </p>
 
-<p> This feature is available in Postfix version 2.2 and later. </p>
-
 %PARAM smtp_connection_cache_time_limit 2s
 
 <p> When SMTP connection caching is enabled, the amount of time that
@@ -4294,6 +4295,19 @@ network or network address listed in  $mynetworks. </dd>
 authenticated via the RFC 2554 (AUTH) protocol. </dd>
 
 
+<dt><b><a name="permit_tls_all_clientcerts">permit_tls_all_clientcerts</a></b></dt>
+
+<dd> Permit the request when the remote SMTP client certificate is
+verified successfully.  This option must be used only if a special
+CA issues the certificates and only this CA is listed as trusted
+CA, otherwise all clients with a recognized certificate would be
+allowed to relay.  </dd>
+
+<dt><b><a name="permit_tls_clientcerts">permit_tls_clientcerts</a></b></dt>
+
+<dd>Permit the request when the remote SMTP client certificate is
+verified successfully, and the certificate fingerprint is listed
+in $relay_clientcerts. </dd>
 <dt><b><a name="reject_rbl_client">reject_rbl_client <i>rbl_domain=d.d.d.d</i></a></b></dt>
 
 <dd>Reject the request when the reversed client network address is
@@ -7494,8 +7508,8 @@ protocol. This is enabled by default. </dd>
 
 <dd> Append the domain name in $myorigin or $mydomain when the
 client TLS certificate is successfully verified, and the client
-certificate fingerprint is listed on the server. This is enabled
-by default. </dd>
+certificate fingerprint is listed in $relay_clientcerts. This is
+enabled by default. </dd>
 
 <dt><b> permit_tls_all_clientcerts </b></dt>
 
@@ -7549,3 +7563,615 @@ authenticated. </p>
         permit_sasl_authenticated permit_tls_clientcerts
         check_address_map hash:/etc/postfix/pop-before-smtp 
 </pre>
+
+%PARAM smtpd_tls_cert_file
+
+<p> File with the Postfix SMTP server RSA certificate in PEM format.
+This file may also contain the server private key. </p>
+
+<p> Both RSA and DSA certificates are supported.  When both types
+are present, the cipher used determines which certificate will be
+presented to the client.  For Netscape and OpenSSL clients without
+special cipher choices the RSA certificate is preferred. </p>
+
+<p> In order to verify a certificate, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s).  </p>
+
+<p> Example: the certificate for "server.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the server.pem file with "cat server_cert.pem intermediate_CA.pem
+root_CA.pem &gt; server.pem". </p>
+
+<p> If you want to accept certificates issued by these CAs yourself,
+you can also add the CA certificates to the smtpd_tls_CAfile, in
+which case it is not necessary to have them in the smtpd_tls_dcert_file
+or smtpd_tls_cert_file. </p>
+
+<p> A certificate supplied here must be usable as SSL server
+certificate and hence pass the "openssl verify -purpose sslserver
+..." test. </p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_cert_file = /etc/postfix/server.pem
+</pre>
+
+%PARAM smtpd_tls_key_file $smtpd_tls_cert_file
+
+<p> File with the Postfix SMTP server RSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $smtpd_tls_cert_file. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+%PARAM smtpd_tls_dcert_file
+
+<p> File with the Postfix SMTP server DSA certificate in PEM format.
+This file may also contain the server private key. <p>
+
+<p> See the discussion under smtpd_tls_cert_file for more details.
+</p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
+</pre>
+
+%PARAM smtpd_tls_dkey_file $smtpd_tls_dcert_file
+
+<p> File with the Postfix SMTP server DSA private key in PEM format.
+This file may be combined with the server certificate file specified
+with $smtpd_tls_dcert_file. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+%PARAM smtpd_tls_CAfile
+
+<p> The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP server certificate.  This is
+needed only when the CA certificate is not already present in the
+server certificate file.  This file may also contain the CA
+certificates of other trusted CAs.  You must use this file for the
+list of trusted CAs if you want to use chroot-mode. </p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_CAfile = /etc/postfix/CAcert.pem
+</pre>
+
+%PARAM smtpd_tls_CApath
+
+<p> Directory with PEM format certificate authority certificates
+that the Postfix SMTP server offers to remote SMTP clients for the
+purpose of client certificate verification.  Do not forget to create
+the necessary "hash" links with, for example, "$OPENSSL_HOME/bin/c_rehash
+/etc/postfix/certs".  </p>
+
+<p> To use this option in chroot mode, this directory (or a copy)
+must be inside the chroot jail. Please note that in this case the
+CA certificates are not offered to the client, so that e.g.  Netscape
+clients might not offer certificates issued by them.  Use of this
+feature is therefore not recommended. </p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_CApath = /etc/postfix/certs
+</pre>
+
+%PARAM smtpd_tls_loglevel 0
+
+<p> Enable additional Postfix SMTP server logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.  </p>
+
+<dl compact>
+
+<dt> </dt> <dd> 0 Disable logging of TLS activity. </dd>
+
+<dt> </dt> <dd> 1 Log TLS handshake and certificate information. </dd>
+
+<dt> </dt> <dd> 2 Log levels during TLS negotiation. </dd>
+
+<dt> </dt> <dd> 3 Log hexadecimal and ASCII dump of TLS negotiation
+process.  </dd>
+
+<dt> </dt> <dd> 4 Also log hexadecimal and ASCII dump of complete
+transmission after STARTTLS. </dd>
+
+</dl>
+
+<p> Use "smtpd_tls_loglevel = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged. </p>
+
+%PARAM smtpd_tls_received_header no
+
+<p> Request that the Postfix SMTP server produces Received:  message
+headers that include information about the protocol and cipher used,
+as well as the client CommonName and client certificate issuer
+CommonName.  This is disabled by default, as the information may
+be modified in transit through other mail servers.  Only information
+that was recorded by the final destination can be trusted. </p>
+
+%PARAM smtpd_use_tls no
+
+<p> Opportunistic mode: announce STARTTLS support to SMTP clients,
+but do not require that clients use TLS encryption. </p>
+
+<p> Note: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private
+key. This is intended behavior. </p>
+
+%PARAM smtpd_enforce_tls no
+
+<p> Enforcement mode: announce STARTTLS support to SMTP clients,
+and require that clients use TLS encryption.  According to RFC 2487
+this MUST NOT be applied in case of a publicly-referenced SMTP
+server.  This option is off by default and should be used only on
+dedicated servers. </p>
+
+<p> Note 1: this mode implies "smtpd_tls_auth_only = yes". </p>
+
+<p> Note 2: when invoked via "sendmail -bs", Postfix will never offer
+STARTTLS due to insufficient privileges to access the server private  
+key. This is intended behavior. </p>
+
+%PARAM smtpd_tls_wrappermode no
+
+<p> Run the Postfix SMTP server in the non-standard "wrapper" mode,
+instead of using the STARTTLS command. </p>
+
+<p> If you want to support this service, enable a special port in
+master.cf, and specify "-o smtpd_tls_wrappermode=yes" on the SMTP
+server's command line. Port 465 (smtps) was once chosen for this
+purpose. </p>
+
+%PARAM smtpd_tls_ask_ccert no
+
+<p> Ask a remote SMTP client for a client certificate. This
+information is needed for certificate based mail relaying with,
+for example, the permit_tls_clientcerts feature. </p>
+
+<p> Some clients such as Netscape will either complain if no
+certificate is available (for the list of CAs in /etc/postfix/certs)
+or will offer multiple client certificates to choose from. This
+may be annoying, so this option is "off" by default. </p>
+
+%PARAM smtpd_tls_req_ccert no
+
+<p> When TLS encryption is enforced, require a remote SMTP client
+certificate in order to allow TLS connections to proceed.  This
+option implies "smtpd_tls_ask_ccert = yes". </p>
+
+<p> When TLS encryption is optional, remote SMTP clients can bypass
+the restriction by simply not using STARTTLS at all. For this reason
+a TLS connection will be handled as if only "smtpd_tls_ask_ccert
+= yes" is specified.  </p>
+
+%PARAM smtpd_tls_ccert_verifydepth 5
+
+<p> The verification depth for remote SMTP client certificates. A
+depth of 1 is sufficient if the issuing CA is listed in a local CA
+file.  The default value should also suffice for longer chains (the
+root CA issues special CA which then issues the actual certificate...).
+</p>
+
+%PARAM smtpd_tls_auth_only no
+
+<p> When TLS encryption is optional in the Postfix SMTP server, do
+not announce or accept SASL authentication over unencrypted
+connections. </p>
+
+%PARAM smtpd_tls_session_cache_database
+
+<p> Name of the file containing the optional Postfix SMTP server
+TLS session cache. Specify a database type that supports enumeration,
+such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+concurrent access.  The file is created if it does not exist.  </p>
+
+<p> NOTE: <b>dbm</b> databases are not suitable. TLS
+session objects are too large. </p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_session_cache_database = btree:/var/postfix/smtpd_scache
+</pre>
+
+%PARAM smtpd_tls_session_cache_timeout 3600s
+
+<p> The expiration time of Postfix SMTP server TLS session cache
+information.  A cache cleanup is performed periodically every
+$smtpd_tls_session_cache_timeout seconds.  </p>
+
+%PARAM relay_clientcerts
+
+<p> The list of remote SMTP client certificates for which the
+Postfix SMTP server will allow access with the permit_tls_clientcerts
+feature.  This feature does not use certificate names, because
+Postfix list manipulation routines treat whitespace and some other
+characters as special.  Instead we use certificate fingerprints as
+they are difficult to fake but easy to use for lookup. </p>
+
+<p> Postfix lookup tables are in the form of (key, value) pairs.
+Since we only need the key, the value can be chosen freely, e.g.
+the name of the user or host:
+D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home </p>
+
+<p> Example: </p>
+
+<pre>
+relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+</pre>
+
+%PARAM smtpd_tls_cipherlist
+
+<p> Controls the Postfix SMTP server TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value. </p>
+
+%PARAM smtpd_tls_dh1024_param_file
+
+<p> File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers. </p>
+
+<p> Instead of using the exact same parameter sets as distributed
+with other TLS packages, it is more secure to generate your own
+set of parameters with something like the following command:  </p>
+
+<pre>
+openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
+</pre>
+
+<p> Your actual source for entropy may differ. Some systems have
+/dev/random; on other system you may consider using the "Entropy
+Gathering Daemon EGD", available at http://www.lothar.com/tech/crypto/.
+</p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+</pre>
+
+%PARAM smtpd_tls_dh512_param_file
+
+<p> File with DH parameters that the Postfix SMTP server should
+use with EDH ciphers. </p>
+
+<p> See also the discussion under the smtpd_tls_dh1024_param_file
+configuration parameter.  </p>
+
+<p> Example: </p>
+
+<pre>
+smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
+</pre>
+
+%PARAM smtpd_starttls_timeout 300s
+
+<p> The time limit for Postfix SMTP server write and read operations
+during TLS startup and shutdown handshake procedures. </p>
+
+%PARAM smtp_tls_cert_file
+
+<p> File with the Postfix SMTP client RSA certificate in PEM format.
+This file may also contain the client private key, and these may
+be the same as the server certificate and key file. </p>
+
+<p> In order to verify certificates, the CA certificate (in case
+of a certificate chain, all CA certificates) must be available.
+You should add these certificates to the server certificate, the
+server certificate first, then the issuing CA(s). </p>
+
+<p> Example: the certificate for "client.dom.ain" was issued by
+"intermediate CA" which itself has a certificate of "root CA".
+Create the client.pem file with "cat client_cert.pem intermediate_CA.pem
+root_CA.pem &gt; client.pem". </p>
+
+<p> If you want to accept remote SMTP server certificates issued
+by these CAs yourself, you can also add the CA certificates to the
+smtp_tls_CAfile, in which case it is not necessary to have them in
+the smtp_tls_cert_file or smtp_tls_dcert_file. </p>
+
+<p> A certificate supplied here must be usable as SSL client certificate and
+hence pass the "openssl verify -purpose sslclient ..." test. </p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_cert_file = /etc/postfix/client.pem
+</pre>
+
+%PARAM smtp_tls_key_file $smtp_tls_cert_file
+
+<p> File with the Postfix SMTP client RSA private key in PEM format.
+This file may be combined with the client certificate file specified
+with $smtp_tls_cert_file. </p>
+
+<p> The private key must not be encrypted. In other words, the key
+must be accessible without password. </p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_key_file = $smtp_tls_cert_file
+</pre>
+
+%PARAM smtp_tls_CAfile
+
+<p> The file with the certificate of the certification authority
+(CA) that issued the Postfix SMTP client certificate.  This is
+needed only when the CA certificate is not already present in the
+client certificate file.  </p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_CAfile = /etc/postfix/CAcert.pem
+</pre>
+
+%PARAM smtp_tls_CApath
+
+<p> Directory with PEM format certificate authority certificates
+that the Postfix SMTP client uses to verify a remote SMTP server
+certificate.  Don't forget to create the necessary "hash" links
+with, for example, "$OPENSSL_HOME/bin/c_rehash /etc/postfix/certs".
+</p>
+
+<p> To use this option in chroot mode, this directory (or a copy) 
+must be inside the chroot jail. </p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_CApath = /etc/postfix/certs
+</pre>
+
+%PARAM smtp_tls_loglevel 0
+
+<p> Enable additional Postfix SMTP client logging of TLS activity.
+Each logging level also includes the information that is logged at
+a lower logging level.  </p>
+
+<dl compact>
+
+<dt> </dt> <dd> 0 Disable logging of TLS activity. </dd>
+
+<dt> </dt> <dd> 1 Log TLS handshake and certificate information. </dd>
+
+<dt> </dt> <dd> 2 Log levels during TLS negotiation. </dd>
+
+<dt> </dt> <dd> 3 Log hexadecimal and ASCII dump of TLS negotiation
+process.  </dd>
+
+<dt> </dt> <dd> 4 Log hexadecimal and ASCII dump of complete
+transmission after STARTTLS. </dd>
+
+</dl>
+
+<p> Use "smtp_tls_loglevel = 3" only in case of problems. Use of
+loglevel 4 is strongly discouraged. </p>
+
+%PARAM smtp_tls_session_cache_database
+
+<p> Name of the file containing the optional Postfix SMTP client
+TLS session cache. Specify a database type that supports enumeration,
+such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+concurrent access.  The file is created if it does not exist.  </p>
+
+<p> NOTE: <b>dbm</b> databases are not suitable. TLS
+session objects are too large. </p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_session_cache_database = btree:/var/postfix/smtp_scache
+</pre>
+
+%PARAM smtp_tls_session_cache_timeout 3600s
+
+<p> The expiration time of Postfix SMTP client TLS session cache
+information.  A cache cleanup is performed periodically every
+$smtp_tls_session_cache_timeout seconds.  </p>
+
+%PARAM smtp_use_tls no
+
+<p> Opportunistic mode: use TLS when a remote SMTP server announces
+STARTTLS support, otherwise send the mail in the clear. Beware:
+some SMTP servers offer STARTTLS even if it is not configured.  If
+the TLS handshake fails, and no other server is available, delivery
+is deferred and mail stays in the queue.  If this is a concern for
+you, use the smtp_tls_per_site feature instead.  </p>
+
+%PARAM smtp_enforce_tls no
+
+<p> Enforcement mode: require that remote SMTP servers use TLS
+encryption, and never send mail in the clear.  This also requires
+that the remote SMTP server hostname matches the information in
+the remote server certificate, and that the remote SMTP server
+certificate was issued by a CA that is trusted by the Postfix SMTP
+client. If the certificate doesn't verify or the hostname doesn't
+match, delivery is deferred and mail stays in the queue.  </p>
+
+<p> The server hostname is matched against all names provided as
+dNSNames in the SubjectAlternativeName.  If no dNSNames are specified,
+the CommonName is checked.  The behavior may be changed with the
+smtp_tls_enforce_peername option.  </p>
+
+<p> This option is useful only if you are definitely sure that you
+will only connect to servers that support RFC 2487 _and_ that
+provide valid server certificates.  Typical use is for clients that
+send all their email to a dedicated mailhub.  </p>
+
+%PARAM smtp_tls_enforce_peername yes
+
+<p> When TLS encryption is enforced, require that the remote SMTP
+server hostname matches the information in the remote SMTP server
+certificate.  As of RFC 2487 the requirements for hostname checking
+for MTA clients are not specified. </p>
+
+<p> This option can be set to "no" to disable strict peer name
+checking. This setting has no effect on sessions that are controlled
+via the smtp_tls_per_site table.  </p>
+
+<p> Disabling the hostname verification can make sense in closed
+environment where special CAs are created.  If not used carefully,
+this option opens the danger of a "man-in-the-middle" attack (the
+CommonName of this attacker will be logged). </p>
+
+%PARAM smtp_tls_per_site
+
+<p> Optional lookup tables with the Postfix SMTP client TLS usage
+policy by next-hop domain name and by remote SMTP server hostname.
+</p>
+
+<p> Table format:  domain names or server hostnames are specified
+on the left-hand side; no wildcards are allowed.  On the right hand
+side specify one of the following keywords:  </p>
+
+<dl>
+
+<dt> NONE </dt> <dd>Don't use TLS at all. </dd>
+
+<dt> MAY </dt> <dd>Try to use STARTTLS if offered, otherwise use
+the unencrypted connection. NOTE: STARTTLS can be used only if
+TLS is already enabled via main.cf, so that the client TLS engine
+is properly initialized at program startup. </dd>
+
+<dt> MUST </dt> <dd>Require usage of STARTTLS, require that the
+remote SMTP server hostname matches the information in the remote
+SMTP server certificate, and require that the remote SMTP server
+certificate was issued by a trusted CA. </dd>
+
+<dt> MUST_NOPEERMATCH </dt> <dd>Require usage of STARTTLS, but do
+not require that the remote SMTP server hostname matches the
+information in the remote SMTP server certificate, or that the
+server certificate was issued by a trusted CA. </dd>
+
+</dl>
+
+<p> Special hint for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:  specify local
+transport(5) table entries for sensitive domains with explicit
+smtp:[mailhost] destinations (since you can assure security of this
+table unlike DNS), then specify MUST for these mail hosts in the
+smtp_tls_per_site table. </p>
+
+%PARAM smtp_tls_scert_verifydepth 5
+
+<p> The verification depth for remote SMTP server certificates. A
+depth of 1 is sufficient, if the certificate is directly issued by
+a CA listed in the CA files.  The default value (5) should suffice
+for longer chains (the root CA issues special CA which then issues
+the actual certificate...). </p>
+
+%PARAM smtp_tls_note_starttls_offer no
+
+<p> Log the hostname of a remote SMTP server that offers STARTTLS,
+when TLS is not already enabled for that server. </p>
+
+<p> The logfile record looks like:  </p>
+
+<pre>
+postfix/smtp[pid]:  Host offered STARTTLS: [name.of.host]
+</pre>
+
+%PARAM smtp_tls_cipherlist
+
+<p> Controls the Postfix SMTP client TLS cipher selection scheme.
+For details, see the OpenSSL documentation. Note: do not use ""
+quotes around the parameter value. </p>
+
+%PARAM smtp_starttls_timeout 300s
+
+<p> Time limit for Postfix SMTP client write and read operations
+during TLS startup and shutdown handshake procedures. </p>
+
+%PARAM smtp_tls_dkey_file $smtp_tls_dcert_file
+
+<p> File with the Postfix SMTP client DSA private key in PEM format.
+The private key must not be encrypted. In other words, the key must
+be accessible without password. </p>
+
+<p> This file may be combined with the server certificate file
+specified with $smtp_tls_cert_file. </p>
+
+%PARAM smtp_tls_dcert_file
+
+<p> File with the Postfix SMTP client DSA certificate in PEM format.
+This file may also contain the server private key. </p>
+
+<p> See the discussion under smtp_tls_cert_file for more details.
+</p>
+
+<p> Example: </p>
+
+<pre>
+smtp_tls_dcert_file = /etc/postfix/client-dsa.pem
+</pre>
+
+%PARAM tls_random_exchange_name ${config_directory}/prng_exch
+
+<p> Name of the pseudo random number generator (PRNG) state file
+that is maintained by tlsmgr(8). The file is created when it does
+not exist, and its length is fixed at 1024 bytes.  </p>
+
+<p> Since this file is modified by Postfix, it should probably be
+kept in the /var file system, instead of under $config_directory.
+The location should not be inside the chroot jail. </p>
+
+%PARAM tls_random_source see "postconf -d" output
+
+<p> The external entropy source for the in-memory tlsmgr(8) pseudo
+random number generator (PRNG) pool. Be sure to specify a non-blocking
+source.  If this source is not a regular file, the entropy source
+type must be prepended:  egd:/path/to/egd_socket for a source with
+EGD compatible socket interface, or dev:/path/to/device for a
+device file.  </p>
+
+%PARAM tls_random_bytes 32
+
+<p> The number of bytes that tlsmgr(8) reads from $tls_random_source
+when (re)seeding the in-memory pseudo random number generator (PRNG)
+pool. The default of 32 bytes (256 bits) is good enough for 128bit
+symmetric keys.  If using EGD or a device file, a maximum of 255
+bytes is read. </p>
+
+%PARAM tls_random_reseed_period 3600s
+
+<p> The maximal time between attempts by tlsmgr(8) to re-seed the
+in-memory pseudo random number generator (PRNG) pool from external
+sources.  The actual time between re-seeding attempts is calculated
+using the PRNG, and is between 0 and the time specified.  </p>
+
+%PARAM tls_random_prng_update_period 3600s
+
+<p> The time between attempts by tlsmgr(8) to save the state of
+the pseudo random number generator (PRNG) to the file specified
+with $tls_random_exchange_name.  </p>
+
+%PARAM tls_daemon_random_bytes 32
+
+<p> The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+process requests from the tlsmgr(8) server in order to seed its
+internal pseudo random number generator (PRNG).  The default of 32
+bytes (equivalent to 256 bits) is sufficient to generate a 128bit
+(or 168bit) session key. </p>
+
+%PARAM smtp_sasl_tls_security_options $smtp_sasl_security_options
+
+<p> The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions. </p>
+
+%PARAM smtpd_sasl_tls_security_options $smtpd_sasl_security_options
+
+<p> The SASL authentication security options that the Postfix SMTP
+server uses for TLS encrypted SMTP sessions. </p>
index 3cffb4fb5edcaafe3df3f0877aae3bc8aa57274d..21a33534a5cf578e9a802d4f13bec001cccf545b 100644 (file)
@@ -835,6 +835,91 @@ Verisign
 Verisign's
 dd
 itd
+AU
+CAcert
+CAfile
+CApath
+CAs
+CNAME
+CommonName
+Cottbus
+DH
+DSA
+EE
+EGD
+GMT
+IA
+Lutz
+Lutz's
+NOPEERMATCH
+Nov
+OPENSSL
+PRNG
+PosgreSQL
+RSA
+SubjectAlternativeName
+Uing
+Widgits
+Wietse's
+aet
+cacert
+ccert
+certs
+cipherlist
+clientcerts
+cnf
+commonName
+compat
+cottbus
+countryName
+cp
+dNSNames
+dcert
+demoCA
+dh
+dkey
+dsa
+eg
+egd
+emailAddress
+exch
+fifos
+gendh
+infiles
+kbytes
+keyout
+lcrypto
+libcrypto
+libssl
+localityName
+loglevel
+lssl
+lutzpc
+misc
+newca
+nicke
+ok
+openssl
+organizationName
+peername
+pem
+prng
+req
+scache
+scert
+sdbm
+smtps
+ssl
+sslclient
+sslserver
+starttls
+stateOrProvinceName
+tlsmgr
+unencrypted
+unpassworded
+urandom
+verifydepth
+wrappermode
 AAAA
 DNSBL
 GETIFADDRS
index b33801f42e237f4297d860301a868a384b5f0401..fc830a3ae7cbd74580f013a999ca86532f845ab6 100644 (file)
@@ -86,7 +86,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
        resolve_local rewrite_clnt stream2rec string_list tok822_parse \
        quote_821_local mail_conf_time mime_state strip_addr \
        virtual8_maps verify_clnt xtext anvil_clnt scache ehlo_mask \
-       valid_mailhost_addr
+       valid_mailhost_addr own_inet_addr
 
 LIBS   = ../../lib/libutil.a
 LIB_DIR        = ../../lib
@@ -263,6 +263,9 @@ ehlo_mask: ehlo_mask.c $(LIB) $(LIBS)
 valid_mailhost_addr: valid_mailhost_addr.c $(LIB) $(LIBS)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
 
+own_inet_addr: own_inet_addr.c $(LIB) $(LIBS)
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
 tests: tok822_test mime_test mime_nest mime_8bit mime_dom mime_trunc \
        mime_cvt mime_cvt2 mime_cvt3 strip_addr_test tok822_limit_test \
        virtual8_test xtext_test scache_multi_test ehlo_mask_test \
index b05755355abda70d2775493ac98599dec27518e1..a43d5715cb5ec70f79274bcc61d958a4ae3b460a 100644 (file)
@@ -235,6 +235,33 @@ char   *var_verp_filter;
 int     var_in_flow_delay;
 char   *var_par_dom_match;
 char   *var_config_dirs;
+#ifdef USE_TLS
+char   *var_tls_rand_exch_name;
+char   *var_smtpd_tls_cert_file;
+char   *var_smtpd_tls_key_file;
+char   *var_smtpd_tls_dcert_file;
+char   *var_smtpd_tls_dkey_file;
+char   *var_smtpd_tls_CAfile;
+char   *var_smtpd_tls_CApath;
+char   *var_smtpd_tls_cipherlist;
+char   *var_smtpd_tls_dh512_param_file;
+char   *var_smtpd_tls_dh1024_param_file;
+int     var_smtpd_tls_loglevel;
+char   *var_smtpd_tls_scache_db;
+int     var_smtpd_tls_scache_timeout;
+char   *var_smtp_tls_cert_file;
+char   *var_smtp_tls_key_file;
+char   *var_smtp_tls_dcert_file;
+char   *var_smtp_tls_dkey_file;
+char   *var_smtp_tls_CAfile;
+char   *var_smtp_tls_CApath;
+char   *var_smtp_tls_cipherlist;
+int     var_smtp_tls_loglevel;
+char   *var_smtp_tls_scache_db;
+int     var_smtp_tls_scache_timeout;
+char   *var_tls_daemon_rand_source;
+int     var_tls_daemon_rand_bytes;
+#endif
 
 char   *var_import_environ;
 char   *var_export_environ;
@@ -483,6 +510,27 @@ void    mail_params_init()
        VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
        VAR_VERIFY_SERVICE, DEF_VERIFY_SERVICE, &var_verify_service, 1, 0,
        VAR_TRACE_SERVICE, DEF_TRACE_SERVICE, &var_trace_service, 1, 0,
+#ifdef USE_TLS
+       VAR_TLS_RAND_EXCH_NAME, DEF_TLS_RAND_EXCH_NAME, &var_tls_rand_exch_name, 0, 0,
+       VAR_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CERT_FILE, &var_smtpd_tls_cert_file, 0, 0,
+       VAR_SMTPD_TLS_KEY_FILE, DEF_SMTPD_TLS_KEY_FILE, &var_smtpd_tls_key_file, 0, 0,
+       VAR_SMTPD_TLS_DCERT_FILE, DEF_SMTPD_TLS_DCERT_FILE, &var_smtpd_tls_dcert_file, 0, 0,
+       VAR_SMTPD_TLS_DKEY_FILE, DEF_SMTPD_TLS_DKEY_FILE, &var_smtpd_tls_dkey_file, 0, 0,
+       VAR_SMTPD_TLS_CA_FILE, DEF_SMTPD_TLS_CA_FILE, &var_smtpd_tls_CAfile, 0, 0,
+       VAR_SMTPD_TLS_CA_PATH, DEF_SMTPD_TLS_CA_PATH, &var_smtpd_tls_CApath, 0, 0,
+       VAR_SMTPD_TLS_CLIST, DEF_SMTPD_TLS_CLIST, &var_smtpd_tls_cipherlist, 0, 0,
+       VAR_SMTPD_TLS_512_FILE, DEF_SMTPD_TLS_512_FILE, &var_smtpd_tls_dh512_param_file, 0, 0,
+       VAR_SMTPD_TLS_1024_FILE, DEF_SMTPD_TLS_1024_FILE, &var_smtpd_tls_dh1024_param_file, 0, 0,
+       VAR_SMTPD_TLS_SCACHE_DB, DEF_SMTPD_TLS_SCACHE_DB, &var_smtpd_tls_scache_db, 0, 0,
+       VAR_SMTP_TLS_CERT_FILE, DEF_SMTP_TLS_CERT_FILE, &var_smtp_tls_cert_file, 0, 0,
+       VAR_SMTP_TLS_KEY_FILE, DEF_SMTP_TLS_KEY_FILE, &var_smtp_tls_key_file, 0, 0,
+       VAR_SMTP_TLS_DCERT_FILE, DEF_SMTP_TLS_DCERT_FILE, &var_smtp_tls_dcert_file, 0, 0,
+       VAR_SMTP_TLS_DKEY_FILE, DEF_SMTP_TLS_DKEY_FILE, &var_smtp_tls_dkey_file, 0, 0,
+       VAR_SMTP_TLS_CA_FILE, DEF_SMTP_TLS_CA_FILE, &var_smtp_tls_CAfile, 0, 0,
+       VAR_SMTP_TLS_CA_PATH, DEF_SMTP_TLS_CA_PATH, &var_smtp_tls_CApath, 0, 0,
+       VAR_SMTP_TLS_CLIST, DEF_SMTP_TLS_CLIST, &var_smtp_tls_cipherlist, 0, 0,
+       VAR_SMTP_TLS_SCACHE_DB, DEF_SMTP_TLS_SCACHE_DB, &var_smtp_tls_scache_db, 0, 0,
+#endif
        0,
     };
     static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
@@ -505,6 +553,11 @@ void    mail_params_init()
        VAR_TOKEN_LIMIT, DEF_TOKEN_LIMIT, &var_token_limit, 1, 0,
        VAR_MIME_MAXDEPTH, DEF_MIME_MAXDEPTH, &var_mime_maxdepth, 1, 0,
        VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
+#ifdef USE_TLS
+       VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
+       VAR_SMTP_TLS_LOGLEVEL, DEF_SMTP_TLS_LOGLEVEL, &var_smtp_tls_loglevel, 0, 0,
+       VAR_TLS_DAEMON_RAND_BYTES, DEF_TLS_DAEMON_RAND_BYTES, &var_tls_daemon_rand_bytes, 1, 0,
+#endif
        0,
     };
     static CONFIG_TIME_TABLE time_defaults[] = {
@@ -517,6 +570,10 @@ void    mail_params_init()
        VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0,
        VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0,
        VAR_FLOCK_STALE, DEF_FLOCK_STALE, &var_flock_stale, 1, 0,
+#ifdef USE_TLS
+       VAR_SMTPD_TLS_SCACHTIME, DEF_SMTPD_TLS_SCACHTIME, &var_smtpd_tls_scache_timeout, 0, 0,
+       VAR_SMTP_TLS_SCACHTIME, DEF_SMTP_TLS_SCACHTIME, &var_smtp_tls_scache_timeout, 0, 0,
+#endif
        VAR_DAEMON_TIMEOUT, DEF_DAEMON_TIMEOUT, &var_daemon_timeout, 1, 0,
        VAR_IN_FLOW_DELAY, DEF_IN_FLOW_DELAY, &var_in_flow_delay, 0, 10,
        0,
index afcce39accde9c91826b7ea4453c99c01b3f0d26..170ddfbc595bc774bb71b48c152579fb902e1410 100644 (file)
@@ -569,6 +569,34 @@ extern bool var_stat_home_dir;
 #define DEF_DUP_FILTER_LIMIT   1000
 extern int var_dup_filter_limit;
 
+#define VAR_TLS_RAND_EXCH_NAME "tls_random_exchange_name"
+#define DEF_TLS_RAND_EXCH_NAME "${config_directory}/prng_exch"
+extern char *var_tls_rand_exch_name;
+
+#define VAR_TLS_RAND_SOURCE    "tls_random_source"
+#ifdef HAS_DEV_URANDOM
+#define DEF_TLS_RAND_SOURCE    "dev:/dev/urandom"
+#else
+#define DEF_TLS_RAND_SOURCE    ""
+#endif
+extern char *var_tls_rand_source;
+
+#define VAR_TLS_RAND_BYTES     "tls_random_bytes"
+#define DEF_TLS_RAND_BYTES     32
+extern int var_tls_rand_bytes;
+
+#define VAR_TLS_DAEMON_RAND_BYTES      "tls_daemon_random_bytes"
+#define DEF_TLS_DAEMON_RAND_BYTES      32
+extern int var_tls_daemon_rand_bytes;
+
+#define VAR_TLS_RESEED_PERIOD  "tls_random_reseed_period"
+#define DEF_TLS_RESEED_PERIOD  "3600s"
+extern int var_tls_reseed_period;
+
+#define VAR_TLS_PRNG_UPD_PERIOD        "tls_random_prng_update_period"
+#define DEF_TLS_PRNG_UPD_PERIOD "3600s"
+extern int var_tls_prng_upd_period;
+
  /*
   * Queue manager: relocated databases.
   */
@@ -845,6 +873,10 @@ extern int var_smtp_helo_tmout;
 #define DEF_SMTP_XFWD_TMOUT    "300s"
 extern int var_smtp_xfwd_tmout;
 
+#define VAR_SMTP_STARTTLS_TMOUT        "smtp_starttls_timeout"
+#define DEF_SMTP_STARTTLS_TMOUT        "300s"
+extern int var_smtp_starttls_tmout;
+
 #define VAR_SMTP_MAIL_TMOUT    "smtp_mail_timeout"
 #define DEF_SMTP_MAIL_TMOUT    "300s"
 extern int var_smtp_mail_tmout;
@@ -950,6 +982,10 @@ extern char *var_smtpd_banner;
 #define DEF_SMTPD_TMOUT                "300s"
 extern int var_smtpd_tmout;
 
+#define VAR_SMTPD_STARTTLS_TMOUT "smtpd_starttls_timeout"
+#define DEF_SMTPD_STARTTLS_TMOUT "300s"
+extern int var_smtpd_starttls_tmout;
+
 #define VAR_SMTPD_RCPT_LIMIT   "smtpd_recipient_limit"
 #define DEF_SMTPD_RCPT_LIMIT   1000
 extern int var_smtpd_rcpt_limit;
@@ -986,6 +1022,150 @@ extern char *var_smtpd_noop_cmds;
 #define DEF_SMTPD_FORBID_CMDS  "CONNECT GET POST"
 extern char *var_smtpd_forbid_cmds;
 
+#define VAR_SMTPD_TLS_WRAPPER  "smtpd_tls_wrappermode"
+#define DEF_SMTPD_TLS_WRAPPER  0
+extern bool var_smtpd_tls_wrappermode;
+
+#define VAR_SMTPD_USE_TLS      "smtpd_use_tls"
+#define DEF_SMTPD_USE_TLS      0
+extern bool var_smtpd_use_tls;
+
+#define VAR_SMTPD_ENFORCE_TLS  "smtpd_enforce_tls"
+#define DEF_SMTPD_ENFORCE_TLS  0
+extern bool var_smtpd_enforce_tls;
+
+#define VAR_SMTPD_TLS_AUTH_ONLY        "smtpd_tls_auth_only"
+#define DEF_SMTPD_TLS_AUTH_ONLY 0
+extern bool var_smtpd_tls_auth_only;
+
+#define VAR_SMTPD_TLS_ACERT    "smtpd_tls_ask_ccert"
+#define DEF_SMTPD_TLS_ACERT    0
+extern bool var_smtpd_tls_ask_ccert;
+
+#define VAR_SMTPD_TLS_RCERT    "smtpd_tls_req_ccert"
+#define DEF_SMTPD_TLS_RCERT    0
+extern bool var_smtpd_tls_req_ccert;
+
+#define VAR_SMTPD_TLS_CCERT_VD "smtpd_tls_ccert_verifydepth"
+#define DEF_SMTPD_TLS_CCERT_VD 5
+extern int var_smtpd_tls_ccert_vd;
+
+#define VAR_SMTPD_TLS_CERT_FILE        "smtpd_tls_cert_file"
+#define DEF_SMTPD_TLS_CERT_FILE        ""
+extern char *var_smtpd_tls_cert_file;
+
+#define VAR_SMTPD_TLS_KEY_FILE "smtpd_tls_key_file"
+#define DEF_SMTPD_TLS_KEY_FILE "$smtpd_tls_cert_file"
+extern char *var_smtpd_tls_key_file;
+
+#define VAR_SMTPD_TLS_DCERT_FILE "smtpd_tls_dcert_file"
+#define DEF_SMTPD_TLS_DCERT_FILE ""
+extern char *var_smtpd_tls_dcert_file;
+
+#define VAR_SMTPD_TLS_DKEY_FILE        "smtpd_tls_dkey_file"
+#define DEF_SMTPD_TLS_DKEY_FILE        "$smtpd_tls_dcert_file"
+extern char *var_smtpd_tls_dkey_file;
+
+#define VAR_SMTPD_TLS_CA_FILE  "smtpd_tls_CAfile"
+#define DEF_SMTPD_TLS_CA_FILE  ""
+extern char *var_smtpd_tls_CAfile;
+
+#define VAR_SMTPD_TLS_CA_PATH  "smtpd_tls_CApath"
+#define DEF_SMTPD_TLS_CA_PATH  ""
+extern char *var_smtpd_tls_CApath;
+
+#define VAR_SMTPD_TLS_CLIST    "smtpd_tls_cipherlist"
+#define DEF_SMTPD_TLS_CLIST    ""
+extern char *var_smtpd_tls_cipherlist;
+
+#define VAR_SMTPD_TLS_512_FILE "smtpd_tls_dh512_param_file"
+#define DEF_SMTPD_TLS_512_FILE ""
+extern char *var_smtpd_tls_dh512_param_file;
+
+#define VAR_SMTPD_TLS_1024_FILE        "smtpd_tls_dh1024_param_file"
+#define DEF_SMTPD_TLS_1024_FILE        ""
+extern char *var_smtpd_tls_dh1024_param_file;
+
+#define VAR_SMTPD_TLS_LOGLEVEL "smtpd_tls_loglevel"
+#define DEF_SMTPD_TLS_LOGLEVEL 0
+extern int var_smtpd_tls_loglevel;
+
+#define VAR_SMTPD_TLS_RECHEAD  "smtpd_tls_received_header"
+#define DEF_SMTPD_TLS_RECHEAD  0
+extern bool var_smtpd_tls_received_header;
+
+#define VAR_SMTPD_TLS_SCACHE_DB        "smtpd_tls_session_cache_database"
+#define DEF_SMTPD_TLS_SCACHE_DB        ""
+extern char *var_smtpd_tls_scache_db;
+
+#define VAR_SMTPD_TLS_SCACHTIME        "smtpd_tls_session_cache_timeout"
+#define DEF_SMTPD_TLS_SCACHTIME        "3600s"
+extern int var_smtpd_tls_scache_timeout;
+
+#define VAR_SMTP_TLS_PER_SITE  "smtp_tls_per_site"
+#define DEF_SMTP_TLS_PER_SITE  ""
+extern char *var_smtp_tls_per_site;
+
+#define VAR_SMTP_USE_TLS       "smtp_use_tls"
+#define DEF_SMTP_USE_TLS       0
+extern bool var_smtp_use_tls;
+
+#define VAR_SMTP_ENFORCE_TLS   "smtp_enforce_tls"
+#define DEF_SMTP_ENFORCE_TLS   0
+extern bool var_smtp_enforce_tls;
+
+#define VAR_SMTP_TLS_ENFORCE_PN        "smtp_tls_enforce_peername"
+#define DEF_SMTP_TLS_ENFORCE_PN        1
+extern bool var_smtp_tls_enforce_peername;
+
+#define VAR_SMTP_TLS_SCERT_VD  "smtp_tls_scert_verifydepth"
+#define DEF_SMTP_TLS_SCERT_VD  5
+extern int var_smtp_tls_scert_vd;
+
+#define VAR_SMTP_TLS_CERT_FILE "smtp_tls_cert_file"
+#define DEF_SMTP_TLS_CERT_FILE ""
+extern char *var_smtp_tls_cert_file;
+
+#define VAR_SMTP_TLS_KEY_FILE  "smtp_tls_key_file"
+#define DEF_SMTP_TLS_KEY_FILE  "$smtp_tls_cert_file"
+extern char *var_smtp_tls_key_file;
+
+#define VAR_SMTP_TLS_DCERT_FILE "smtp_tls_dcert_file"
+#define DEF_SMTP_TLS_DCERT_FILE ""
+extern char *var_smtp_tls_dcert_file;
+
+#define VAR_SMTP_TLS_DKEY_FILE "smtp_tls_dkey_file"
+#define DEF_SMTP_TLS_DKEY_FILE "$smtp_tls_dcert_file"
+extern char *var_smtp_tls_dkey_file;
+
+#define VAR_SMTP_TLS_CA_FILE   "smtp_tls_CAfile"
+#define DEF_SMTP_TLS_CA_FILE   ""
+extern char *var_smtp_tls_CAfile;
+
+#define VAR_SMTP_TLS_CA_PATH   "smtp_tls_CApath"
+#define DEF_SMTP_TLS_CA_PATH   ""
+extern char *var_smtp_tls_CApath;
+
+#define VAR_SMTP_TLS_CLIST     "smtp_tls_cipherlist"
+#define DEF_SMTP_TLS_CLIST     ""
+extern char *var_smtp_tls_cipherlist;
+
+#define VAR_SMTP_TLS_LOGLEVEL  "smtp_tls_loglevel"
+#define DEF_SMTP_TLS_LOGLEVEL  0
+extern int var_smtp_tls_loglevel;
+
+#define VAR_SMTP_TLS_NOTEOFFER "smtp_tls_note_starttls_offer"
+#define DEF_SMTP_TLS_NOTEOFFER 0
+extern bool var_smtp_tls_note_starttls_offer;
+
+#define VAR_SMTP_TLS_SCACHE_DB "smtp_tls_session_cache_database"
+#define DEF_SMTP_TLS_SCACHE_DB ""
+extern char *var_smtp_tls_scache_db;
+
+#define VAR_SMTP_TLS_SCACHTIME "smtp_tls_session_cache_timeout"
+#define DEF_SMTP_TLS_SCACHTIME "3600s"
+extern int var_smtp_tls_scache_timeout;
+
  /*
   * SASL authentication support, SMTP server side.
   */
@@ -1001,6 +1181,10 @@ extern char *var_smtpd_sasl_opts;
 #define DEF_SMTPD_SASL_APPNAME "smtpd"
 extern char *var_smtpd_sasl_appname;
 
+#define VAR_SMTPD_SASL_TLS_OPTS        "smtpd_sasl_tls_security_options"
+#define DEF_SMTPD_SASL_TLS_OPTS        "$smtpd_sasl_security_options"
+extern char *var_smtpd_sasl_tls_opts;
+
 #define VAR_SMTPD_SASL_REALM   "smtpd_sasl_local_domain"
 #define DEF_SMTPD_SASL_REALM   ""
 extern char *var_smtpd_sasl_realm;
@@ -1038,6 +1222,10 @@ extern char *var_smtp_sasl_opts;
 #define DEF_SMTP_SASL_MECHS    ""
 extern char *var_smtp_sasl_mechs;
 
+#define VAR_SMTP_SASL_TLS_OPTS "smtp_sasl_tls_security_options"
+#define DEF_SMTP_SASL_TLS_OPTS "$var_smtp_sasl_opts"
+extern char *var_smtp_sasl_tls_opts;
+
  /*
   * LMTP server. The soft error limit determines how many errors an LMTP
   * client may make before we start to slow down; the hard error limit
@@ -1323,6 +1511,10 @@ extern char *var_relay_rcpt_maps;
 #define DEF_RELAY_RCPT_CODE    550
 extern int var_relay_rcpt_code;
 
+#define VAR_RELAY_CCERTS       "relay_clientcerts"
+#define DEF_RELAY_CCERTS       ""
+extern char *var_smtpd_relay_ccerts;
+
 #define VAR_CLIENT_CHECKS      "smtpd_client_restrictions"
 #define DEF_CLIENT_CHECKS      ""
 extern char *var_client_checks;
@@ -1445,6 +1637,8 @@ extern int var_mul_rcpt_code;
 #define PERMIT_AUTH_DEST       "permit_auth_destination"
 #define REJECT_UNAUTH_DEST     "reject_unauth_destination"
 #define CHECK_RELAY_DOMAINS    "check_relay_domains"
+#define PERMIT_TLS_CLIENTCERTS "permit_tls_clientcerts"
+#define PERMIT_TLS_ALL_CLIENTCERTS     "permit_tls_all_clientcerts"
 #define VAR_RELAY_CODE         "relay_domains_reject_code"
 #define DEF_RELAY_CODE         554
 extern int var_relay_code;
index e48437381b628670d5d0a647ca213989f3a32219..cb58fdf306022e4d494f99aa72432dd4d42893e7 100644 (file)
@@ -42,6 +42,7 @@
 #define MAIL_SERVICE_LOCAL     "local"
 #define MAIL_SERVICE_PICKUP    "pickup"
 #define MAIL_SERVICE_QUEUE     "qmgr"
+#define MAIL_SERVICE_TLSMGR    "tlsmgr"
 #define MAIL_SERVICE_RESOLVE   "resolve"
 #define MAIL_SERVICE_REWRITE   "rewrite"
 #define MAIL_SERVICE_VIRTUAL   "virtual"
index eeb73cdb430502981e401b35fcfd43aee974d8de..8d5651d90004c7bc0e68b2d4aff1fcbfc963b319 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20050117"
+#define MAIL_RELEASE_DATE      "20050119"
 #define MAIL_VERSION_NUMBER    "2.2"
 
 #define VAR_MAIL_VERSION       "mail_version"
index d3b7d5aec9548273123363a16cd468ddede3c01e..31c0f44cd0a13f1fe1394c4b04e20847b509e646 100644 (file)
@@ -7,7 +7,7 @@
 /*     #include <own_inet_addr.h>
 /*
 /*     int     own_inet_addr(addr)
-/*     struct in_addr *addr;
+/*     struct sockaddr *addr;
 /*
 /*     INET_ADDR_LIST *own_inet_addr_list()
 /*
@@ -265,3 +265,38 @@ INET_ADDR_LIST *proxy_inet_addr_list(void)
 
     return (&proxy_list);
 }
+
+#ifdef TEST
+#include <inet_proto.h>
+
+static void inet_addr_list_print(INET_ADDR_LIST *list)
+{
+    MAI_HOSTADDR_STR hostaddr;
+    struct sockaddr_storage *sa;
+
+    for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
+       SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
+                            &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+       msg_info("%s", hostaddr.buf);
+    }
+}
+
+char   *var_inet_interfaces;
+
+int     main(int argc, char **argv)
+{
+    INET_PROTO_INFO *proto_info;
+    INET_ADDR_LIST *list;
+
+    if (argc != 3)
+       msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")",
+                 argv[0]);
+    msg_verbose = 10;
+    proto_info = inet_proto_init(argv[0], argv[1]);
+    var_inet_interfaces = argv[2];
+    list = own_inet_addr_list();
+    inet_addr_list_print(list);
+    return (0);
+}
+
+#endif
index 9c1476243539ae5751594db13d20464421a45dbe..c1589eb6ab7d11fb897adc745fb3638315d8b61a 100644 (file)
 /*     The external command to execute when a Postfix daemon program is
 /*     invoked with the -D option.
 /* .IP "\fBinet_interfaces (all)\fR"
-/*     The network interface addresses that this mail system receives mail
-/*     on.
+/*     The network interface addresses that this mail system receives
+/*     mail on.
 /* .IP "\fBinet_protocols (ipv4)\fR"
 /*     The Internet protocols Postfix will attempt to use when making
 /*     or accepting connections.
index 4f8722297e14bbbf1a2888d2e05c744fc0c6a10e..78f7856439e5aa0f9faf5797261641886d0b9e5b 100644 (file)
 /*     smtp(8), Postfix SMTP client
 /*     smtpd(8), Postfix SMTP server
 /*     spawn(8), run non-Postfix server
+/*     tlsmgr(8), Postfix TLS cache and randomness manager
 /*     trivial-rewrite(8), Postfix address rewriting
 /*     verify(8), Postfix address verification
 /*     virtual(8), Postfix virtual delivery agent
index ffbc92ed3e023cf2997d99b0bf1f2bf59681bc69..1ae2fe0894eca46b081ec5d24ac5968a95c7867d 100644 (file)
@@ -12,7 +12,8 @@ CFLAGS        = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= smtp_unalias
 PROG   = smtp
 INC_DIR        = ../../include
-LIBS   = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libdns.a ../../lib/libutil.a
+LIBS   = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \
+       ../../lib/libglobal.a ../../lib/libutil.a
 
 .c.o:; $(CC) $(CFLAGS) -c $*.c
 
@@ -84,6 +85,7 @@ smtp.o: ../../include/maps.h
 smtp.o: ../../include/mail_server.h
 smtp.o: smtp.h
 smtp.o: ../../include/htable.h
+smtp.o: ../../include/tls.h
 smtp.o: smtp_sasl.h
 smtp_addr.o: smtp_addr.c
 smtp_addr.o: ../../include/sys_defs.h
@@ -111,6 +113,7 @@ smtp_addr.o: ../../include/match_list.h
 smtp_addr.o: ../../include/match_ops.h
 smtp_addr.o: ../../include/maps.h
 smtp_addr.o: ../../include/dict.h
+smtp_addr.o: ../../include/tls.h
 smtp_addr.o: smtp_addr.h
 smtp_chat.o: smtp_chat.c
 smtp_chat.o: ../../include/sys_defs.h
@@ -139,6 +142,7 @@ smtp_chat.o: ../../include/match_list.h
 smtp_chat.o: ../../include/match_ops.h
 smtp_chat.o: ../../include/maps.h
 smtp_chat.o: ../../include/dict.h
+smtp_chat.o: ../../include/tls.h
 smtp_connect.o: smtp_connect.c
 smtp_connect.o: ../../include/sys_defs.h
 smtp_connect.o: ../../include/msg.h
@@ -174,6 +178,7 @@ smtp_connect.o: ../../include/match_list.h
 smtp_connect.o: ../../include/match_ops.h
 smtp_connect.o: ../../include/maps.h
 smtp_connect.o: ../../include/dict.h
+smtp_connect.o: ../../include/tls.h
 smtp_connect.o: smtp_addr.h
 smtp_connect.o: smtp_reuse.h
 smtp_proto.o: smtp_proto.c
@@ -215,6 +220,7 @@ smtp_proto.o: ../../include/scache.h
 smtp_proto.o: ../../include/string_list.h
 smtp_proto.o: ../../include/match_list.h
 smtp_proto.o: ../../include/match_ops.h
+smtp_proto.o: ../../include/tls.h
 smtp_proto.o: smtp_sasl.h
 smtp_rcpt.o: smtp_rcpt.c
 smtp_rcpt.o: ../../include/sys_defs.h
@@ -235,6 +241,7 @@ smtp_rcpt.o: ../../include/match_list.h
 smtp_rcpt.o: ../../include/match_ops.h
 smtp_rcpt.o: ../../include/maps.h
 smtp_rcpt.o: ../../include/dict.h
+smtp_rcpt.o: ../../include/tls.h
 smtp_reuse.o: smtp_reuse.c
 smtp_reuse.o: ../../include/sys_defs.h
 smtp_reuse.o: ../../include/msg.h
@@ -255,6 +262,7 @@ smtp_reuse.o: ../../include/match_list.h
 smtp_reuse.o: ../../include/match_ops.h
 smtp_reuse.o: ../../include/maps.h
 smtp_reuse.o: ../../include/dict.h
+smtp_reuse.o: ../../include/tls.h
 smtp_reuse.o: smtp_reuse.h
 smtp_reuse.o: ../../include/dns.h
 smtp_reuse.o: ../../include/sock_addr.h
@@ -281,6 +289,7 @@ smtp_sasl_glue.o: ../../include/htable.h
 smtp_sasl_glue.o: ../../include/deliver_request.h
 smtp_sasl_glue.o: ../../include/recipient_list.h
 smtp_sasl_glue.o: ../../include/scache.h
+smtp_sasl_glue.o: ../../include/tls.h
 smtp_sasl_glue.o: smtp_sasl.h
 smtp_sasl_proto.o: smtp_sasl_proto.c
 smtp_sasl_proto.o: ../../include/sys_defs.h
@@ -302,6 +311,7 @@ smtp_sasl_proto.o: ../../include/match_list.h
 smtp_sasl_proto.o: ../../include/match_ops.h
 smtp_sasl_proto.o: ../../include/maps.h
 smtp_sasl_proto.o: ../../include/dict.h
+smtp_sasl_proto.o: ../../include/tls.h
 smtp_sasl_proto.o: smtp_sasl.h
 smtp_session.o: smtp_session.c
 smtp_session.o: ../../include/sys_defs.h
@@ -315,8 +325,10 @@ smtp_session.o: ../../include/mime_state.h
 smtp_session.o: ../../include/header_opts.h
 smtp_session.o: ../../include/debug_peer.h
 smtp_session.o: ../../include/mail_params.h
-smtp_session.o: smtp.h
+smtp_session.o: ../../include/maps.h
+smtp_session.o: ../../include/dict.h
 smtp_session.o: ../../include/argv.h
+smtp_session.o: smtp.h
 smtp_session.o: ../../include/htable.h
 smtp_session.o: ../../include/deliver_request.h
 smtp_session.o: ../../include/recipient_list.h
@@ -324,8 +336,7 @@ smtp_session.o: ../../include/scache.h
 smtp_session.o: ../../include/string_list.h
 smtp_session.o: ../../include/match_list.h
 smtp_session.o: ../../include/match_ops.h
-smtp_session.o: ../../include/maps.h
-smtp_session.o: ../../include/dict.h
+smtp_session.o: ../../include/tls.h
 smtp_state.o: smtp_state.c
 smtp_state.o: ../../include/sys_defs.h
 smtp_state.o: ../../include/mymalloc.h
@@ -344,6 +355,7 @@ smtp_state.o: ../../include/match_list.h
 smtp_state.o: ../../include/match_ops.h
 smtp_state.o: ../../include/maps.h
 smtp_state.o: ../../include/dict.h
+smtp_state.o: ../../include/tls.h
 smtp_state.o: smtp_sasl.h
 smtp_trouble.o: smtp_trouble.c
 smtp_trouble.o: ../../include/sys_defs.h
@@ -370,6 +382,7 @@ smtp_trouble.o: ../../include/match_list.h
 smtp_trouble.o: ../../include/match_ops.h
 smtp_trouble.o: ../../include/maps.h
 smtp_trouble.o: ../../include/dict.h
+smtp_trouble.o: ../../include/tls.h
 smtp_unalias.o: smtp_unalias.c
 smtp_unalias.o: ../../include/sys_defs.h
 smtp_unalias.o: ../../include/htable.h
@@ -390,3 +403,4 @@ smtp_unalias.o: ../../include/match_list.h
 smtp_unalias.o: ../../include/match_ops.h
 smtp_unalias.o: ../../include/maps.h
 smtp_unalias.o: ../../include/dict.h
+smtp_unalias.o: ../../include/tls.h
index 9a09fcfd4133e3ffa1cd6925a4ef6d3910499ea8..b87b1f18e2bbc138654bcca905aabae26fdc01c9 100644 (file)
@@ -51,6 +51,7 @@
 /*     RFC 2554 (AUTH command)
 /*     RFC 2821 (SMTP protocol)
 /*     RFC 2920 (SMTP Pipelining)
+/*     RFC 3207 (STARTTLS command)
 /* DIAGNOSTICS
 /*     Problems and transactions are logged to \fBsyslogd\fR(8).
 /*     Corrupted message files are marked so that the queue manager can
 /* .IP "\fBsmtp_sasl_mechanism_filter (empty)\fR"
 /*     If non-empty, a Postfix SMTP client filter for the remote SMTP
 /*     server's list of offered SASL mechanisms.
+/* STARTTLS SUPPORT CONTROLS
+/* .ad
+/* .fi
+/*     Detailed information about STARTTLS configuration may be found
+/*     in the TLS_README document.
+/* .IP "\fBsmtp_use_tls (no)\fR"
+/*     Opportunistic mode: use TLS when a remote SMTP server announces
+/*     STARTTLS support, otherwise send the mail in the clear.
+/* .IP "\fBsmtp_enforce_tls (no)\fR"
+/*     Enforcement mode: require that remote SMTP servers use TLS
+/*     encryption, and never send mail in the clear.
+/* .IP "\fBsmtp_sasl_tls_security_options ($smtp_sasl_security_options)\fR"
+/*     The SASL authentication security options that the Postfix SMTP
+/*     client uses for TLS encrypted SMTP sessions.
+/* .IP "\fBsmtp_starttls_timeout (300s)\fR"
+/*     Time limit for Postfix SMTP client write and read operations
+/*     during TLS startup and shutdown handshake procedures.
+/* .IP "\fBsmtp_tls_CAfile (empty)\fR"
+/*     The file with the certificate of the certification authority
+/*     (CA) that issued the Postfix SMTP client certificate.
+/* .IP "\fBsmtp_tls_CApath (empty)\fR"
+/*     Directory with PEM format certificate authority certificates
+/*     that the Postfix SMTP client uses to verify a remote SMTP server
+/*     certificate.
+/* .IP "\fBsmtp_tls_cert_file (empty)\fR"
+/*     File with the Postfix SMTP client RSA certificate in PEM format.
+/* .IP "\fBsmtp_tls_cipherlist (empty)\fR"
+/*     Controls the Postfix SMTP client TLS cipher selection scheme.
+/* .IP "\fBsmtp_tls_dcert_file (empty)\fR"
+/*     File with the Postfix SMTP client DSA certificate in PEM format.
+/* .IP "\fBsmtp_tls_dkey_file ($smtp_tls_dcert_file)\fR"
+/*     File with the Postfix SMTP client DSA private key in PEM format.
+/* .IP "\fBsmtp_tls_enforce_peername (yes)\fR"
+/*     When TLS encryption is enforced, require that the remote SMTP
+/*     server hostname matches the information in the remote SMTP server
+/*     certificate.
+/* .IP "\fBsmtp_tls_key_file ($smtp_tls_cert_file)\fR"
+/*     File with the Postfix SMTP client RSA private key in PEM format.
+/* .IP "\fBsmtp_tls_loglevel (0)\fR"
+/*     Enable additional Postfix SMTP client logging of TLS activity.
+/* .IP "\fBsmtp_tls_note_starttls_offer (no)\fR"
+/*     Log the hostname of a remote SMTP server that offers STARTTLS,
+/*     when TLS is not already enabled for that server.
+/* .IP "\fBsmtp_tls_per_site (empty)\fR"
+/*     Optional lookup tables with the Postfix SMTP client TLS usage
+/*     policy by next-hop domain name and by remote SMTP server hostname.
+/* .IP "\fBsmtp_tls_scert_verifydepth (5)\fR"
+/*     The verification depth for remote SMTP server certificates.
+/* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
+/*     Name of the file containing the optional Postfix SMTP client
+/*     TLS session cache.
+/* .IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
+/*     The expiration time of Postfix SMTP client TLS session cache
+/*     information.
+/* .IP "\fBtls_daemon_random_bytes (32)\fR"
+/*     The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+/*     process requests from the tlsmgr(8) server in order to seed its
+/*     internal pseudo random number generator (PRNG).
 /* RESOURCE AND RATE CONTROLS
 /* .ad
 /* .fi
 /*     postconf(5), configuration parameters
 /*     master(5), generic daemon options
 /*     master(8), process manager
+/*     tlsmgr(8), TLS session and PRNG management
 /*     syslogd(8), system logging
 /* README FILES
 /* .ad
 /* .na
 /* .nf
 /*     SASL_README, Postfix SASL howto
+/*     TLS_README, Postfix STARTTLS howto
 /* LICENSE
 /* .ad
 /* .fi
 /*     Connection caching in cooperation with:
 /*     Victor Duchovni
 /*     Morgan Stanley
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
@@ -411,6 +479,17 @@ bool    var_smtp_cache_demand;
 char   *var_smtp_ehlo_dis_words;
 char   *var_smtp_ehlo_dis_maps;
 
+bool    var_smtp_use_tls;
+bool    var_smtp_enforce_tls;
+char   *var_smtp_tls_per_site;
+#ifdef USE_TLS
+int     var_smtp_starttls_tmout;
+char   *var_smtp_sasl_tls_opts;
+bool    var_smtp_tls_enforce_peername;
+int     var_smtp_tls_scert_vd;
+bool    var_smtp_tls_note_starttls_offer;
+#endif
+
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
   * the connection management routines.
@@ -421,6 +500,15 @@ STRING_LIST *smtp_cache_dest;
 SCACHE *smtp_scache;
 MAPS   *smtp_ehlo_dis_maps;
 
+#ifdef USE_TLS
+
+ /*
+  * OpenSSL client state.
+  */
+SSL_CTX *smtp_tls_ctx;
+
+#endif
+
 /* deliver_message - deliver message with extreme prejudice */
 
 static int deliver_message(const char *service, DELIVER_REQUEST *request)
@@ -551,6 +639,17 @@ static void pre_init(char *unused_name, char **unused_argv)
        msg_warn("%s is true, but SASL support is not compiled in",
                 VAR_SMTP_SASL_ENABLE);
 #endif
+    /*
+     * Initialize the TLS data before entering the chroot jail
+     */
+    if (var_smtp_use_tls || var_smtp_enforce_tls || var_smtp_tls_per_site[0]) {
+#ifdef USE_TLS
+       smtp_tls_ctx = tls_client_init(var_smtp_tls_scert_vd);
+       smtp_tls_list_init();
+#else
+       msg_warn("TLS has been selected, but TLS support is not compiled in");
+#endif
+    }
 
     /*
      * Flush client.
@@ -605,6 +704,9 @@ int     main(int argc, char **argv)
        VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
        VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
        VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
+#ifdef USE_TLS
+       VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
+#endif
        VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
        VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
        VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
@@ -614,6 +716,7 @@ int     main(int argc, char **argv)
        VAR_SCACHE_SERVICE, DEF_SCACHE_SERVICE, &var_scache_service, 1, 0,
        VAR_SMTP_EHLO_DIS_WORDS, DEF_SMTP_EHLO_DIS_WORDS, &var_smtp_ehlo_dis_words, 0, 0,
        VAR_SMTP_EHLO_DIS_MAPS, DEF_SMTP_EHLO_DIS_MAPS, &var_smtp_ehlo_dis_maps, 0, 0,
+       VAR_SMTP_TLS_PER_SITE, DEF_SMTP_TLS_PER_SITE, &var_smtp_tls_per_site, 0, 0,
        0,
     };
     static CONFIG_TIME_TABLE time_table[] = {
@@ -630,6 +733,9 @@ int     main(int argc, char **argv)
        VAR_SMTP_PIX_THRESH, DEF_SMTP_PIX_THRESH, &var_smtp_pix_thresh, 0, 0,
        VAR_SMTP_PIX_DELAY, DEF_SMTP_PIX_DELAY, &var_smtp_pix_delay, 1, 0,
        VAR_SMTP_CACHE_CONN, DEF_SMTP_CACHE_CONN, &var_smtp_cache_conn, 1, 0,
+#ifdef USE_TLS
+       VAR_SMTP_STARTTLS_TMOUT, DEF_SMTP_STARTTLS_TMOUT, &var_smtp_starttls_tmout, 1, 0,
+#endif
        0,
     };
     static CONFIG_INT_TABLE int_table[] = {
@@ -637,6 +743,9 @@ int     main(int argc, char **argv)
        VAR_SMTP_MXADDR_LIMIT, DEF_SMTP_MXADDR_LIMIT, &var_smtp_mxaddr_limit, 0, 0,
        VAR_SMTP_MXSESS_LIMIT, DEF_SMTP_MXSESS_LIMIT, &var_smtp_mxsess_limit, 0, 0,
        VAR_SMTP_REUSE_LIMIT, DEF_SMTP_REUSE_LIMIT, &var_smtp_reuse_limit, 1, 0,
+#ifdef USE_TLS
+       VAR_SMTP_TLS_SCERT_VD, DEF_SMTP_TLS_SCERT_VD, &var_smtp_tls_scert_vd, 0, 0,
+#endif
        0,
     };
     static CONFIG_BOOL_TABLE bool_table[] = {
@@ -651,6 +760,13 @@ int     main(int argc, char **argv)
        VAR_SMTP_DEFER_MXADDR, DEF_SMTP_DEFER_MXADDR, &var_smtp_defer_mxaddr,
        VAR_SMTP_SEND_XFORWARD, DEF_SMTP_SEND_XFORWARD, &var_smtp_send_xforward,
        VAR_SMTP_CACHE_DEMAND, DEF_SMTP_CACHE_DEMAND, &var_smtp_cache_demand,
+       VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls,
+       VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_tls,
+#ifdef USE_TLS
+       VAR_SMTP_TLS_ENFORCE_PN, DEF_SMTP_TLS_ENFORCE_PN, &var_smtp_tls_enforce_peername,
+       VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
+#endif
+
        0,
     };
 
index 9fe55b15a6095c8b461e870dde0232018b970ca6..0b08bc699e8f92bf3d482ff25dd902d6f5cd4e35 100644 (file)
 #include <string_list.h>
 #include <maps.h>
 
+ /*
+  * Postfix TLS library.
+  */
+#ifdef USE_TLS
+#include <tls.h>
+#endif
+
  /*
   * State information associated with each SMTP delivery request.
   * Session-specific state is stored separately.
@@ -123,6 +130,7 @@ typedef struct SMTP_STATE {
   * Misc flags.
   */
 #define SMTP_MISC_FLAG_LOOP_DETECT     (1<<0)
+#define        SMTP_MISC_FLAG_IN_STARTTLS      (1<<1)
 
 #define SMTP_MISC_FLAG_DEFAULT         SMTP_MISC_FLAG_LOOP_DETECT
 
@@ -146,6 +154,12 @@ extern STRING_LIST *smtp_cache_dest;       /* cached destinations */
 
 extern MAPS *smtp_ehlo_dis_maps;       /* ehlo keyword filter */
 
+#ifdef USE_TLS
+
+extern SSL_CTX *smtp_tls_ctx;          /* client-side TLS engine */
+
+#endif
+
  /*
   * smtp_session.c
   */
@@ -183,6 +197,17 @@ typedef struct SMTP_SESSION {
     sasl_callback_t *sasl_callbacks;   /* stateful callbacks */
 #endif
 
+    /*
+     * TLS related state.
+     */
+#ifdef USE_TLS
+    int     tls_use_tls;               /* can do TLS */
+    int     tls_enforce_tls;           /* must do TLS */
+    int     tls_enforce_peername;      /* cert must match */
+    TLScontext_t *tls_context;         /* TLS session state */
+    tls_info_t tls_info;               /* legacy */
+#endif
+
 } SMTP_SESSION;
 
 extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, const char *,
@@ -194,6 +219,11 @@ extern SMTP_SESSION *smtp_session_activate(int, VSTRING *, VSTRING *);
 #define SMTP_SESS_FLAG_NONE    0       /* no options */
 #define SMTP_SESS_FLAG_CACHE   (1<<0)  /* enable session caching */
 
+#ifdef USE_TLS
+extern void smtp_tls_list_init(void);
+
+#endif
+
  /*
   * smtp_connect.c
   */
@@ -293,4 +323,11 @@ extern void smtp_state_free(SMTP_STATE *);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
index 1da9afe0bd6cdb51eea31f4ea0d65bcc4367b7ed..184906e71aef0e539fe1a736fe6a795137f5e83f 100644 (file)
@@ -21,6 +21,7 @@
 /*     This module implements the client side of the SMTP protocol.
 /*
 /*     smtp_helo() performs the initial handshake with the SMTP server.
+/*     When TLS is enabled, this includes STARTTLS negotiations.
 /*
 /*     smtp_xfer() sends message envelope information followed by the
 /*     message data, and finishes the SMTP conversation. These operations
 /*     Connection caching in cooperation with:
 /*     Victor Duchovni
 /*     Morgan Stanley
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
@@ -209,7 +217,7 @@ char   *xfer_request[SMTP_STATE_LAST] = {
 
 /* smtp_helo - perform initial handshake with SMTP server */
 
-int     smtp_helo(SMTP_STATE *state, int misc_flags)
+int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
 {
     char   *myname = "smtp_helo";
     SMTP_SESSION *session = state->session;
@@ -232,60 +240,81 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
     const char *ehlo_words;
     int     discard_mask;
 
-    /*
-     * Prepare for disaster.
-     */
-    smtp_timeout_setup(state->session->stream, var_smtp_helo_tmout);
-    if ((except = vstream_setjmp(state->session->stream)) != 0)
-       return (smtp_stream_except(state, except,
-                                  "receiving the initial SMTP greeting"));
+#ifdef USE_TLS
+    static int smtp_start_tls(SMTP_STATE *, int);
+    int     saved_features = session->features;
 
-    /*
-     * Read and parse the server's SMTP greeting banner.
-     */
-    switch ((resp = smtp_chat_resp(session))->code / 100) {
-    case 2:
-       break;
-    case 5:
-       if (var_smtp_skip_5xx_greeting)
-           resp->code = 400;
-    default:
-       return (smtp_site_fail(state, resp->code,
-                              "host %s refused to talk to me: %s",
-                              session->namaddr,
-                              translit(resp->str, "\n", " ")));
-    }
+#endif
 
     /*
-     * XXX Some PIX firewall versions require flush before ".<CR><LF>" so it
-     * does not span a packet boundary. This hurts performance so it is not
-     * on by default.
+     * If not recursing after STARTTLS, examine the server greeting banner
+     * and decide if we are going to send EHLO as the next command.
      */
-    if (resp->str[strspn(resp->str, "20 *\t\n")] == 0)
-       session->features |= SMTP_FEATURE_MAYBEPIX;
+    if ((misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) {
 
-    /*
-     * See if we are talking to ourself. This should not be possible with the
-     * way we implement DNS lookups. However, people are known to sometimes
-     * screw up the naming service. And, mailer loops are still possible when
-     * our own mailer routing tables are mis-configured.
-     */
-    words = resp->str;
-    (void) mystrtok(&words, "- \t\n");
-    for (n = 0; (word = mystrtok(&words, " \t\n")) != 0; n++) {
-       if (n == 0 && strcasecmp(word, var_myhostname) == 0) {
-           if (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
-               msg_warn("host %s greeted me with my own hostname %s",
-                        session->namaddr, var_myhostname);
-       } else if (strcasecmp(word, "ESMTP") == 0)
+       /*
+        * Prepare for disaster.
+        */
+       smtp_timeout_setup(state->session->stream, var_smtp_helo_tmout);
+       if ((except = vstream_setjmp(state->session->stream)) != 0)
+           return (smtp_stream_except(state, except,
+                                   "receiving the initial SMTP greeting"));
+
+       /*
+        * Read and parse the server's SMTP greeting banner.
+        */
+       switch ((resp = smtp_chat_resp(session))->code / 100) {
+       case 2:
+           break;
+       case 5:
+           if (var_smtp_skip_5xx_greeting)
+               resp->code = 400;
+       default:
+           return (smtp_site_fail(state, resp->code,
+                                  "host %s refused to talk to me: %s",
+                                  session->namaddr,
+                                  translit(resp->str, "\n", " ")));
+       }
+
+       /*
+        * XXX Some PIX firewall versions require flush before ".<CR><LF>" so
+        * it does not span a packet boundary. This hurts performance so it
+        * is not on by default.
+        */
+       if (resp->str[strspn(resp->str, "20 *\t\n")] == 0)
+           session->features |= SMTP_FEATURE_MAYBEPIX;
+
+       /*
+        * See if we are talking to ourself. This should not be possible with
+        * the way we implement DNS lookups. However, people are known to
+        * sometimes screw up the naming service. And, mailer loops are still
+        * possible when our own mailer routing tables are mis-configured.
+        */
+       words = resp->str;
+       (void) mystrtok(&words, "- \t\n");
+       for (n = 0; (word = mystrtok(&words, " \t\n")) != 0; n++) {
+           if (n == 0 && strcasecmp(word, var_myhostname) == 0) {
+               if (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
+                   msg_warn("host %s greeted me with my own hostname %s",
+                            session->namaddr, var_myhostname);
+           } else if (strcasecmp(word, "ESMTP") == 0)
+               session->features |= SMTP_FEATURE_ESMTP;
+       }
+       if (var_smtp_always_ehlo
+           && (session->features & SMTP_FEATURE_MAYBEPIX) == 0)
            session->features |= SMTP_FEATURE_ESMTP;
+       if (var_smtp_never_ehlo
+           || (session->features & SMTP_FEATURE_MAYBEPIX) != 0)
+           session->features &= ~SMTP_FEATURE_ESMTP;
     }
-    if (var_smtp_always_ehlo
-       && (session->features & SMTP_FEATURE_MAYBEPIX) == 0)
+
+    /*
+     * If recursing after STARTTLS, there is no server greeting banner.
+     * Always send EHLO as the next command.
+     */
+    else {
        session->features |= SMTP_FEATURE_ESMTP;
-    if (var_smtp_never_ehlo
-       || (session->features & SMTP_FEATURE_MAYBEPIX) != 0)
-       session->features &= ~SMTP_FEATURE_ESMTP;
+    }
 
     /*
      * Return the compliment. Fall back to SMTP if our ESMTP recognition
@@ -352,6 +381,11 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
                            session->size_limit = off_cvt_string(word);
                    }
                }
+#ifdef USE_TLS
+           } else if (strcasecmp(word, "STARTTLS") == 0) {
+               if ((discard_mask & EHLO_MASK_STARTTLS) == 0)
+                   session->features |= SMTP_FEATURE_STARTTLS;
+#endif
 #ifdef USE_SASL_AUTH
            } else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0) {
                if ((discard_mask & EHLO_MASK_AUTH) == 0)
@@ -385,6 +419,9 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
      * we are reading in the responses. In addition to TCP buffering we have
      * to be aware of application-level buffering by the vstream module,
      * which is limited to a couple kbytes.
+     * 
+     * XXX No need to do this before and after STARTTLS, but it's not a big deal
+     * if we do.
      */
     if (session->features & SMTP_FEATURE_PIPELINING) {
        optlen = sizeof(session->sndbufsize);
@@ -406,6 +443,97 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
        session->sndbufsize = 0;
     }
 
+#ifdef USE_TLS
+
+    /*
+     * Skip this part if we already sent STARTTLS.
+     */
+    if ((misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) {
+
+       /*
+        * Optionally log unused STARTTLS opportunities.
+        */
+       if ((session->features & SMTP_FEATURE_STARTTLS) &&
+           (var_smtp_tls_note_starttls_offer) &&
+           (!(session->tls_enforce_tls || session->tls_use_tls)))
+           msg_info("Host offered STARTTLS: [%s]", session->host);
+
+       /*
+        * Decide whether or not to send STARTTLS.
+        */
+       if ((session->features & SMTP_FEATURE_STARTTLS) != 0
+           && smtp_tls_ctx != 0
+           && (session->tls_use_tls || session->tls_enforce_tls)) {
+
+           /*
+            * Prepare for disaster.
+            */
+           smtp_timeout_setup(state->session->stream, var_smtp_starttls_tmout);
+           if ((except = vstream_setjmp(state->session->stream)) != 0)
+               return (smtp_stream_except(state, except,
+                                       "receiving the STARTTLS response"));
+
+           /*
+            * Send STARTTLS. Recurse when the server accepts STARTTLS, after
+            * resetting the SASL and EHLO features lists.
+            * 
+            * XXX Reset the SASL mechanism list to avoid spurious warnings. We
+            * need a routine to reset the list instead of groping data here.
+            * 
+            * XXX Should not there be an smtp_sasl_tls_security_options feature
+            * to allow different mechanisms across TLS tunnels than across
+            * plain-text connections?
+            */
+           smtp_chat_cmd(session, "STARTTLS");
+           if ((resp = smtp_chat_resp(session))->code / 100 == 2) {
+#ifdef USE_SASL_AUTH
+               if (session->sasl_mechanism_list) {
+                   myfree(session->sasl_mechanism_list);
+                   session->sasl_mechanism_list = 0;
+               }
+#endif
+               session->features = saved_features;
+               misc_flags |= SMTP_MISC_FLAG_IN_STARTTLS;
+               return (smtp_start_tls(state, misc_flags));
+           }
+
+           /*
+            * Give up if we must use TLS but the server rejects STARTTLS
+            * although support for it was announced in the EHLO response.
+            */
+           session->features &= ~SMTP_FEATURE_STARTTLS;
+           if (session->tls_enforce_tls)
+               return (smtp_site_fail(state, resp->code,
+                   "TLS is required, but host %s refused to start TLS: %s",
+                                      session->namaddr,
+                                      translit(resp->str, "\n", " ")));
+           /* Else try to continue in plain-text mode. */
+       }
+
+       /*
+        * Give up if we must use TLS but can't for various reasons.
+        * 
+        * 200412 Be sure to provide the default clause at the bottom of this
+        * block. When TLS is required we must never, ever, end up in
+        * plain-text mode.
+        */
+       if (session->tls_enforce_tls) {
+           if (!(session->features & SMTP_FEATURE_STARTTLS)) {
+               return (smtp_site_fail(state, 450,
+                         "TLS is required, but was not offered by host %s",
+                                      session->namaddr));
+           } else if (smtp_tls_ctx == 0) {
+               return (smtp_site_fail(state, 450,
+                    "TLS is required, but our TLS engine is unavailable"));
+           } else {
+               msg_warn("%s: TLS is required but unavailable, don't know why",
+                        myname);
+               return (smtp_site_fail(state, 450,
+                                    "TLS is required, but not available"));
+           }
+       }
+    }
+#endif
 #ifdef USE_SASL_AUTH
     if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH))
        return (smtp_sasl_helo_login(state));
@@ -414,6 +542,102 @@ int     smtp_helo(SMTP_STATE *state, int misc_flags)
     return (0);
 }
 
+#ifdef USE_TLS
+
+/* smtp_start_tls - turn on TLS and recurse into the HELO dialog */
+
+static int smtp_start_tls(SMTP_STATE *state, int misc_flags)
+{
+    SMTP_SESSION *session = state->session;
+
+    /*
+     * Turn off SMTP connection caching. When the TLS handshake succeeds, we
+     * can't reuse the SMTP connection. Reason: we can't turn off TLS in one
+     * process, save the connection to the cache which is shared with all
+     * SMTP clients, migrate the connection to another SMTP client, and
+     * resume TLS there. When the TLS handshake fails, we can't reuse the
+     * SMTP connection either, because the conversation is in an unknown
+     * state.
+     */
+    session->reuse_count = 0;
+
+    /*
+     * The actual TLS handshake may succeed, but tls_client_start() may fail
+     * anyway, for example because server certificate verification is
+     * required but failed, or because enforce_peername is required but the
+     * names listed in the server certificate don't match the peer hostname.
+     * 
+     * XXX When tls_client_start() fails then we don't know what state the SMTP
+     * connection is in, so we give up on this connection even if we are not
+     * required to use TLS.
+     * 
+     * XXX Other tests for specific combinations of required/failed behavior
+     * follow below AFTER the tls_client_start() call. These tests should be
+     * done inside tls_client_start() or its call-backs, to keep the SMTP
+     * client code clean (as it is in the SMTP server).
+     */
+    session->tls_context =
+       tls_client_start(smtp_tls_ctx, session->stream,
+                        var_smtp_starttls_tmout,
+                        session->tls_enforce_peername,
+                        session->host,
+                        &(session->tls_info));
+    if (session->tls_context == 0)
+       return (smtp_site_fail(state, 450,
+                              "Cannot start TLS: handshake failure"));
+
+    /*
+     * Give up when TLS is required, we can parse the server certificate's
+     * CommonName field, but server certificate verification failed.
+     * 
+     * In enforce_peername state, the handshake would already have been
+     * terminated by the certificate verification call-back routine, so the
+     * check here is for logging only.
+     * 
+     * XXX It appears that the CommonName field is used as an indicator that a
+     * server certificate is available. If the latter is what we want, then
+     * we should test for that instead.
+     */
+    if (session->tls_info.peer_CN != NULL) {
+       if (!session->tls_info.peer_verified) {
+           msg_info("Server certificate could not be verified");
+           if (session->tls_enforce_tls) {
+               tls_client_stop(smtp_tls_ctx, session->stream,
+                               var_smtp_starttls_tmout, 1,
+                               &(session->tls_info));
+               return (smtp_site_fail(state, 450,
+                         "TLS failure: Cannot verify server certificate"));
+           }
+       }
+    }
+
+    /*
+     * Give up when TLS is required but no server certificate is available
+     * (or we could not parse the certificate's CommonName) field.
+     * 
+     * XXX The test below is not accurate: the server hostname verification may
+     * use the dNSNames instead of the CommonName. We really should be
+     * testing if a certificate is available.
+     */
+    else {
+       if (session->tls_enforce_tls) {
+           tls_client_stop(smtp_tls_ctx, session->stream,
+                           var_smtp_starttls_tmout, 1,
+                           &(session->tls_info));
+           return (smtp_site_fail(state, 450,
+                            "TLS failure: Cannot verify server hostname"));
+       }
+    }
+
+    /*
+     * At this point we have to re-negotiate the "EHLO" to reget the
+     * feature-list.
+     */
+    return (smtp_helo(state, misc_flags));
+}
+
+#endif
+
 /* smtp_text_out - output one header/body record */
 
 static void smtp_text_out(void *context, int rec_type,
index 7c391092b5af9d9e98e8b121a705d5ad5becfb3b..75e7b6dcf7f4cfa0a1bb376c6f8e432540942bf6 100644 (file)
 /*     and initializes it with the given stream and destination, host name
 /*     and address information.  The host name and address strings are
 /*     copied. The port is in network byte order.
+/*     When TLS is enabled, smtp_session_alloc() looks up the
+/*     per-site TLS policies for TLS enforcement and certificate
+/*     verification.  The resulting policy is stored into the
+/*     SMTP_SESSION object.
 /*
 /*     smtp_session_free() destroys an SMTP_SESSION structure and its
 /*     members, making memory available for reuse. It will handle the
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
 
 #include <sys_defs.h>
 #include <stdlib.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
 
 /* Utility library. */
 
 #include <mime_state.h>
 #include <debug_peer.h>
 #include <mail_params.h>
+#include <maps.h>
 
 /* Application-specific. */
 
 
 /*#define msg_verbose 1*/
 
+#ifdef USE_TLS
+
+ /*
+  * Per-site policies can override main.cf settings.
+  * 
+  * XXX 200412 This does not work as some people may expect. A policy that
+  * specifies "use TLS" in a policy file while TLS is turned off in main.cf
+  * cannot work, because there is no OpenSSL context for creating sessions
+  * (that context exists only if TLS is enabled via main.cf settings; the
+  * OpenSSL context is created at process initialization time and cannot be
+  * created on the fly).
+  */
+typedef struct {
+    int     dont_use;                  /* don't use TLS */
+    int     use;                       /* useless, see above */
+    int     enforce;                   /* must always use TLS */
+    int     enforce_peername;          /* must verify certificate name */
+} SMTP_TLS_SITE_POLICY;
+
+static MAPS *tls_per_site;             /* lookup table(s) */
+
+/* smtp_tls_list_init - initialize per-site policy lists */
+
+void    smtp_tls_list_init(void)
+{
+    tls_per_site = maps_create(VAR_SMTP_TLS_PER_SITE, var_smtp_tls_per_site,
+                              DICT_FLAG_LOCK);
+}
+
+/* smtp_tls_site_policy - look up per-site TLS policy */
+
+static void smtp_tls_site_policy(SMTP_TLS_SITE_POLICY *policy,
+                                        const char *site_name,
+                                        const char *site_class)
+{
+    const char *lookup;
+    char   *lookup_key;
+
+    /*
+     * Initialize the default policy.
+     */
+    policy->dont_use = 0;
+    policy->use = 0;
+    policy->enforce = 0;
+    policy->enforce_peername = 0;
+
+    /*
+     * Look up a non-default policy.
+     */
+    lookup_key = lowercase(mystrdup(site_name));
+    if ((lookup = maps_find(tls_per_site, lookup_key, 0)) != 0) {
+       if (!strcasecmp(lookup, "NONE"))
+           policy->dont_use = 1;
+       else if (!strcasecmp(lookup, "MAY"))
+           policy->use = 1;
+       else if (!strcasecmp(lookup, "MUST"))
+           policy->enforce = policy->enforce_peername = 1;
+       else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
+           policy->enforce = 1;
+       else
+           msg_warn("Table %s: ignoring unknown TLS policy '%s' for %s %s",
+                    var_smtp_tls_per_site, lookup, site_class, site_name);
+    }
+    myfree(lookup_key);
+}
+
+#endif
+
 /* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
 
 SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
@@ -114,6 +199,12 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
 {
     SMTP_SESSION *session;
 
+#ifdef USE_TLS
+    SMTP_TLS_SITE_POLICY host_policy;
+    SMTP_TLS_SITE_POLICY rcpt_policy;
+
+#endif
+
     session = (SMTP_SESSION *) mymalloc(sizeof(*session));
     session->stream = stream;
     session->dest = mystrdup(dest);
@@ -144,6 +235,46 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
     smtp_sasl_connect(session);
 #endif
 
+#ifdef USE_TLS
+    session->tls_use_tls = session->tls_enforce_tls = 0;
+    session->tls_enforce_peername = 0;
+    session->tls_context = 0;
+    session->tls_info = tls_info_zero;
+
+    /*
+     * Override the main.cf TLS policy with an optional per-site policy.
+     */
+    if (smtp_tls_ctx != 0) {
+       smtp_tls_site_policy(&host_policy, host, "receiving host");
+       smtp_tls_site_policy(&rcpt_policy, dest, "recipient domain");
+
+       /*
+        * Set up TLS enforcement for this session.
+        */
+       if ((var_smtp_enforce_tls && !host_policy.dont_use && !rcpt_policy.dont_use)
+           || host_policy.enforce || rcpt_policy.enforce)
+           session->tls_enforce_tls = session->tls_use_tls = 1;
+
+       /*
+        * Set up peername checking for this session.
+        * 
+        * We want to make sure that a MUST* entry in the tls_per_site table
+        * always has precedence. MUST always must lead to a peername check,
+        * MUST_NOPEERMATCH must always disable it. Only when no explicit
+        * setting has been found, the default will be used. There is the
+        * case left, that both "host" and "recipient" settings conflict. In
+        * this case, the "host" setting wins.
+        */
+       if (host_policy.enforce && host_policy.enforce_peername)
+           session->tls_enforce_peername = 1;
+       else if (rcpt_policy.enforce && rcpt_policy.enforce_peername)
+           session->tls_enforce_peername = 1;
+       else if (var_smtp_enforce_tls && var_smtp_tls_enforce_peername)
+           session->tls_enforce_peername = 1;
+       else if ((var_smtp_use_tls && !host_policy.dont_use && !rcpt_policy.dont_use) || host_policy.use || rcpt_policy.use)
+           session->tls_use_tls = 1;
+    }
+#endif
     debug_peer_check(host, addr);
     return (session);
 }
@@ -152,6 +283,15 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
 
 void    smtp_session_free(SMTP_SESSION *session)
 {
+#ifdef USE_TLS
+    if (session->stream) {
+       vstream_fflush(session->stream);
+       if (session->tls_context)
+           tls_client_stop(smtp_tls_ctx, session->stream,
+                           var_smtp_starttls_tmout, 0,
+                           &(session->tls_info));
+    }
+#endif
     if (session->stream)
        vstream_fclose(session->stream);
     myfree(session->dest);
index f847ce1a430a8ae07753b7f5cf796e8f11a39e9b..39ae9b1c2c9ec98bc5a0667b29ff09ceb7e8615c 100644 (file)
@@ -13,7 +13,8 @@ CFLAGS        = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= smtpd_token smtpd_check
 PROG   = smtpd
 INC_DIR        = ../../include
-LIBS   = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libdns.a ../../lib/libutil.a
+LIBS   = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libdns.a \
+       ../../lib/libglobal.a ../../lib/libutil.a
 
 .c.o:; $(CC) $(CFLAGS) -c $*.c
 
@@ -158,6 +159,7 @@ smtpd.o: ../../include/valid_mailhost_addr.h
 smtpd.o: ../../include/mail_server.h
 smtpd.o: smtpd_token.h
 smtpd.o: smtpd.h
+smtpd.o: ../../include/tls.h
 smtpd.o: smtpd_check.h
 smtpd.o: smtpd_chat.h
 smtpd.o: smtpd_sasl_proto.h
@@ -187,6 +189,7 @@ smtpd_chat.o: ../../include/mail_error.h
 smtpd_chat.o: ../../include/name_mask.h
 smtpd_chat.o: smtpd.h
 smtpd_chat.o: ../../include/mail_stream.h
+smtpd_chat.o: ../../include/tls.h
 smtpd_chat.o: smtpd_chat.h
 smtpd_check.o: smtpd_check.c
 smtpd_check.o: ../../include/sys_defs.h
@@ -244,6 +247,7 @@ smtpd_check.o: ../../include/is_header.h
 smtpd_check.o: ../../include/valid_mailhost_addr.h
 smtpd_check.o: smtpd.h
 smtpd_check.o: ../../include/mail_stream.h
+smtpd_check.o: ../../include/tls.h
 smtpd_check.o: smtpd_sasl_glue.h
 smtpd_check.o: smtpd_check.h
 smtpd_peer.o: smtpd_peer.c
@@ -265,6 +269,7 @@ smtpd_peer.o: ../../include/valid_hostname.h
 smtpd_peer.o: smtpd.h
 smtpd_peer.o: ../../include/argv.h
 smtpd_peer.o: ../../include/mail_stream.h
+smtpd_peer.o: ../../include/tls.h
 smtpd_proxy.o: smtpd_proxy.c
 smtpd_proxy.o: ../../include/sys_defs.h
 smtpd_proxy.o: ../../include/msg.h
@@ -286,6 +291,7 @@ smtpd_proxy.o: ../../include/attr.h
 smtpd_proxy.o: smtpd.h
 smtpd_proxy.o: ../../include/argv.h
 smtpd_proxy.o: ../../include/mail_stream.h
+smtpd_proxy.o: ../../include/tls.h
 smtpd_proxy.o: smtpd_proxy.h
 smtpd_sasl_glue.o: smtpd_sasl_glue.c
 smtpd_sasl_glue.o: ../../include/sys_defs.h
@@ -303,6 +309,7 @@ smtpd_sasl_glue.o: ../../include/vstream.h
 smtpd_sasl_glue.o: smtpd.h
 smtpd_sasl_glue.o: ../../include/argv.h
 smtpd_sasl_glue.o: ../../include/mail_stream.h
+smtpd_sasl_glue.o: ../../include/tls.h
 smtpd_sasl_glue.o: smtpd_sasl_glue.h
 smtpd_sasl_glue.o: smtpd_chat.h
 smtpd_sasl_proto.o: smtpd_sasl_proto.c
@@ -322,6 +329,7 @@ smtpd_sasl_proto.o: ../../include/name_mask.h
 smtpd_sasl_proto.o: smtpd.h
 smtpd_sasl_proto.o: ../../include/argv.h
 smtpd_sasl_proto.o: ../../include/mail_stream.h
+smtpd_sasl_proto.o: ../../include/tls.h
 smtpd_sasl_proto.o: smtpd_token.h
 smtpd_sasl_proto.o: smtpd_chat.h
 smtpd_sasl_proto.o: smtpd_sasl_proto.h
@@ -344,6 +352,7 @@ smtpd_state.o: smtpd.h
 smtpd_state.o: ../../include/vstring.h
 smtpd_state.o: ../../include/argv.h
 smtpd_state.o: ../../include/mail_stream.h
+smtpd_state.o: ../../include/tls.h
 smtpd_state.o: smtpd_chat.h
 smtpd_state.o: smtpd_sasl_glue.h
 smtpd_token.o: smtpd_token.c
@@ -366,3 +375,4 @@ smtpd_xforward.o: smtpd.h
 smtpd_xforward.o: ../../include/vstring.h
 smtpd_xforward.o: ../../include/argv.h
 smtpd_xforward.o: ../../include/mail_stream.h
+smtpd_xforward.o: ../../include/tls.h
index fb8aa610fc7b1bbe5b37ff99146ef94804be7d3f..b338e32871576848c0e7d5b75775e3b926571676 100644 (file)
@@ -39,6 +39,7 @@
 /*     RFC 2554 (AUTH command)
 /*     RFC 2821 (SMTP protocol)
 /*     RFC 2920 (SMTP Pipelining)
+/*     RFC 3207 (STARTTLS command)
 /* DIAGNOSTICS
 /*     Problems and transactions are logged to \fBsyslogd\fR(8).
 /*
 /*     Available in Postfix version 2.1 and later:
 /* .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR"
 /*     What SMTP clients Postfix will not offer AUTH support to.
+/* STARTTLS SUPPORT CONTROLS
+/* .ad
+/* .fi
+/*     Detailed information about STARTTLS configuration may be
+/*     found in the TLS_README document.
+/* .IP "\fBsmtpd_use_tls (no)\fR"
+/*     Opportunistic mode: announce STARTTLS support to SMTP clients,
+/*     but do not require that clients use TLS encryption.
+/* .IP "\fBsmtpd_enforce_tls (no)\fR"
+/*     Enforcement mode: announce STARTTLS support to SMTP clients,
+/*     and require that clients use TLS encryption.
+/* .IP "\fBsmtpd_sasl_tls_security_options ($smtpd_sasl_security_options)\fR"
+/*     The SASL authentication security options that the Postfix SMTP
+/*     server uses for TLS encrypted SMTP sessions.
+/* .IP "\fBsmtpd_starttls_timeout (300s)\fR"
+/*     The time limit for Postfix SMTP server write and read operations
+/*     during TLS startup and shutdown handshake procedures.
+/* .IP "\fBsmtpd_tls_CAfile (empty)\fR"
+/*     The file with the certificate of the certification authority
+/*     (CA) that issued the Postfix SMTP server certificate.
+/* .IP "\fBsmtpd_tls_CAfile (empty)\fR"
+/*     The file with the certificate of the certification authority
+/*     (CA) that issued the Postfix SMTP server certificate.
+/* .IP "\fBsmtpd_tls_ask_ccert (no)\fR"
+/*     Ask a remote SMTP client for a client certificate.
+/* .IP "\fBsmtpd_tls_auth_only (no)\fR"
+/*     When TLS encryption is optional in the Postfix SMTP server, do
+/*     not announce or accept SASL authentication over unencrypted
+/*     connections.
+/* .IP "\fBsmtpd_tls_ccert_verifydepth (5)\fR"
+/*     The verification depth for remote SMTP client certificates.
+/* .IP "\fBsmtpd_tls_cert_file (empty)\fR"
+/*     File with the Postfix SMTP server RSA certificate in PEM format.
+/* .IP "\fBsmtpd_tls_cipherlist (empty)\fR"
+/*     Controls the Postfix SMTP server TLS cipher selection scheme.
+/* .IP "\fBsmtpd_tls_dcert_file (empty)\fR"
+/*     File with the Postfix SMTP server DSA certificate in PEM format.
+/* .IP "\fBsmtpd_tls_dh1024_param_file (empty)\fR"
+/*     File with DH parameters that the Postfix SMTP server should
+/*     use with EDH ciphers.
+/* .IP "\fBsmtpd_tls_dh512_param_file (empty)\fR"
+/*     File with DH parameters that the Postfix SMTP server should
+/*     use with EDH ciphers.
+/* .IP "\fBsmtpd_tls_dkey_file ($smtpd_tls_dcert_file)\fR"
+/*     File with the Postfix SMTP server DSA private key in PEM format.
+/* .IP "\fBsmtpd_tls_key_file ($smtpd_tls_cert_file)\fR"
+/*     File with the Postfix SMTP server RSA private key in PEM format.
+/* .IP "\fBsmtpd_tls_loglevel (0)\fR"
+/*     Enable additional Postfix SMTP server logging of TLS activity.
+/* .IP "\fBsmtpd_tls_received_header (no)\fR"
+/*     Request that the Postfix SMTP server produces Received:  message
+/*     headers that include information about the protocol and cipher used,
+/*     as well as the client CommonName and client certificate issuer
+/*     CommonName.
+/* .IP "\fBsmtpd_tls_req_ccert (no)\fR"
+/*     When TLS encryption is enforced, require a remote SMTP client
+/*     certificate in order to allow TLS connections to proceed.
+/* .IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
+/*     Name of the file containing the optional Postfix SMTP server
+/*     TLS session cache.
+/* .IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
+/*     The expiration time of Postfix SMTP server TLS session cache
+/*     information.
+/* .IP "\fBsmtpd_tls_wrappermode (no)\fR"
+/*     Run the Postfix SMTP server in the non-standard "wrapper" mode,
+/*     instead of using the STARTTLS command.
+/* .IP "\fBtls_daemon_random_bytes (32)\fR"
+/*     The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+/*     process requests from the tlsmgr(8) server in order to seed its
+/*     internal pseudo random number generator (PRNG).
 /* VERP SUPPORT CONTROLS
 /* .ad
 /* .fi
 /* SEE ALSO
 /*     anvil(8), connection/rate limiting
 /*     cleanup(8), message canonicalization
+/*     tlsmgr(8), TLS session and PRNG management
 /*     trivial-rewrite(8), address resolver
 /*     verify(8), address verification service
 /*     postconf(5), configuration parameters
 /*     SMTPD_POLICY_README, external policy server
 /*     SMTPD_PROXY_README, external before-queue content filter
 /*     SASL_README, Postfix SASL howto
+/*     TLS_README, Postfix STARTTLS howto
 /*     VERP_README, Postfix XVERP extension
 /*     XCLIENT_README, Postfix XCLIENT extension
 /*     XFORWARD_README, Postfix XFORWARD extension
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
@@ -826,6 +906,22 @@ char   *var_local_rwr_clients;
 char   *var_smtpd_ehlo_dis_words;
 char   *var_smtpd_ehlo_dis_maps;
 
+bool    var_smtpd_use_tls;
+bool    var_smtpd_enforce_tls;
+bool    var_smtpd_tls_wrappermode;
+
+#ifdef USE_TLS
+char   *var_smtpd_relay_ccerts;
+int     var_smtpd_starttls_tmout;
+bool    var_smtpd_tls_auth_only;
+bool    var_smtpd_tls_ask_ccert;
+bool    var_smtpd_tls_req_ccert;
+int     var_smtpd_tls_ccert_vd;
+bool    var_smtpd_tls_received_header;
+char   *var_smtpd_sasl_tls_opts;
+
+#endif
+
  /*
   * Silly little macros.
   */
@@ -888,9 +984,18 @@ static void chat_reset(SMTPD_STATE *, int);
  /*
   * Reasons for losing the client.
   */
-#define REASON_TIMEOUT                 "timeout"
-#define REASON_LOST_CONNECTION         "lost connection"
-#define REASON_ERROR_LIMIT             "too many errors"
+#define REASON_TIMEOUT         "timeout"
+#define REASON_LOST_CONNECTION "lost connection"
+#define REASON_ERROR_LIMIT     "too many errors"
+
+#ifdef USE_TLS
+
+ /*
+  * TLS initialization status.
+  */
+static SSL_CTX *smtpd_tls_ctx;
+
+#endif
 
 #ifdef USE_SASL_AUTH
 
@@ -1069,9 +1174,18 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            ENQUEUE_FIX_REPLY(state, reply_buf, "VRFY");
     if ((discard_mask & EHLO_MASK_ETRN) == 0)
        ENQUEUE_FIX_REPLY(state, reply_buf, "ETRN");
+#ifdef USE_TLS
+    if ((discard_mask & EHLO_MASK_STARTTLS) == 0)
+       if ((state->tls_use_tls || state->tls_enforce_tls) && (!state->tls_context))
+           ENQUEUE_FIX_REPLY(state, reply_buf, "STARTTLS");
+#endif
 #ifdef USE_SASL_AUTH
     if ((discard_mask & EHLO_MASK_AUTH) == 0) {
-       if (var_smtpd_sasl_enable && !sasl_client_exception(state)) {
+       if (var_smtpd_sasl_enable && !sasl_client_exception(state)
+#ifdef USE_TLS
+           && (!state->tls_auth_only || state->tls_context)
+#endif
+           ) {
            ENQUEUE_FMT_REPLY(state, reply_buf, "AUTH %s",
                              state->sasl_mechanism_list);
            if (var_broken_auth_clients)
@@ -1712,6 +1826,41 @@ static void rcpt_reset(SMTPD_STATE *state)
     state->rcpt_overshoot = 0;
 }
 
+#ifdef USE_TLS
+
+/* CN_sanitize - make sure, the CN-string is well behaved */
+
+static void CN_sanitize(VSTRING *CNstring)
+{
+    unsigned char *cp;
+    int     ch;
+    int     pc;
+
+    /*
+     * Postfix Received: headers can be configured to include a comment with
+     * the CN (CommonName) of the peer and its issuer. To avoid problems with
+     * RFC 822 etc. syntax, we limit the CN information to printable ASCII
+     * text, and neutralize characters that affect comment parsing: the
+     * backslash and unbalanced parentheses.
+     */
+    for (pc = 0, cp = (unsigned char *) STR(CNstring); (ch = *cp) != 0; cp++) {
+       if (!ISASCII(ch) || !ISPRINT(ch) || ch == '\\') {
+           *cp = '?';
+       } else if (ch == '(') {
+           pc++;
+       } else if (ch == ')') {
+           if (pc > 0)
+               pc--;
+           else
+               *cp = '?';
+       }
+    }
+    while (pc-- > 0)
+       VSTRING_ADDCH(CNstring, ')');
+}
+
+#endif
+
 /* data_cmd - process DATA command */
 
 static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
@@ -1730,6 +1879,12 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     int     out_error;
     char  **cpp;
 
+#ifdef USE_TLS
+    VSTRING *peer_CN;
+    VSTRING *issuer_CN;
+
+#endif
+
     /*
      * Sanity checks. With ESMTP command pipelining the client can send DATA
      * before all recipients are rejected, so don't report that as a protocol
@@ -1811,6 +1966,39 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
                    "Received: from %s (%s [%s])",
                    state->helo_name ? state->helo_name : state->name,
                    state->name, state->rfc_addr);
+#ifdef USE_TLS
+       if (var_smtpd_tls_received_header && state->tls_context) {
+           out_fprintf(out_stream, REC_TYPE_NORM,
+                       "\t(using %s with cipher %s (%d/%d bits))",
+                     state->tls_info.protocol, state->tls_info.cipher_name,
+                       state->tls_info.cipher_usebits,
+                       state->tls_info.cipher_algbits);
+
+#define VSTRING_STRDUP(s) vstring_strcpy(vstring_alloc(strlen(s) + 1), (s))
+
+           if (state->tls_info.peer_CN) {
+               peer_CN = VSTRING_STRDUP(state->tls_info.peer_CN);
+               CN_sanitize(peer_CN);
+               issuer_CN = VSTRING_STRDUP(state->tls_info.issuer_CN);
+               CN_sanitize(issuer_CN);
+               if (state->tls_info.peer_verified)
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                       "\t(Client CN \"%s\", Issuer \"%s\" (verified OK))",
+                               STR(peer_CN), STR(issuer_CN));
+               else
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                      "\t(Client CN \"%s\", Issuer \"%s\" (not verified))",
+                               STR(peer_CN), STR(issuer_CN));
+               vstring_free(issuer_CN);
+               vstring_free(peer_CN);
+           } else if (var_smtpd_tls_ask_ccert)
+               out_fprintf(out_stream, REC_TYPE_NORM,
+                           "\t(Client did not present a certificate)");
+           else
+               out_fprintf(out_stream, REC_TYPE_NORM,
+                           "\t(No client certificate requested)");
+       }
+#endif
        if (state->rcpt_count == 1 && state->recipient) {
            out_fprintf(out_stream, REC_TYPE_NORM,
                        state->cleanup ? "\tby %s (%s) with %s id %s" :
@@ -2575,6 +2763,116 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
     }
 }
 
+#ifdef USE_TLS
+
+/* smtpd_start_tls -turn on TLS or force disconnect */
+
+static void smtpd_start_tls(SMTPD_STATE *state)
+{
+
+    /*
+     * Wrapper mode uses a dedicated port and always requires TLS.
+     * 
+     * XXX In non-wrapper mode, it is possible to require client certificate
+     * verification without requiring TLS. Since certificates can be verified
+     * only while TLS is turned on, this means that Postfix will happily
+     * perform SMTP transactions when the client does not use the STARTTLS
+     * command. For this reason, Postfix does not require client certificate
+     * verification unless TLS is required.
+     */
+    state->tls_context =
+       tls_server_start(smtpd_tls_ctx, state->client,
+                        var_smtpd_starttls_tmout,
+                        state->name, state->addr, &(state->tls_info),
+                      (var_smtpd_tls_req_ccert && state->tls_enforce_tls));
+
+    /*
+     * When the TLS handshake fails, the conversation is in an unknown state.
+     * There is nothing we can do except to disconnect from the client.
+     */
+    if (state->tls_context == 0)
+       vstream_longjmp(state->client, SMTP_ERR_EOF);
+
+    /*
+     * When TLS is turned on, we may offer AUTH methods that would not be
+     * offered within a plain-text session.
+     */
+#ifdef USE_SASL_AUTH
+    if (var_smtpd_sasl_enable
+       && strcmp(var_smtpd_sasl_tls_opts, var_smtpd_sasl_opts) != 0) {
+       smtpd_sasl_auth_reset(state);
+       smtpd_sasl_disconnect(state);
+       smtpd_sasl_connect(state, VAR_SMTPD_SASL_TLS_OPTS,
+                          var_smtpd_sasl_tls_opts);
+    }
+#endif
+}
+
+/* starttls_cmd - respond to STARTTLS */
+
+static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
+{
+    if (argc != 1) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "501 Syntax: STARTTLS");
+       return (-1);
+    }
+    if (state->tls_context != 0) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "554 Error: TLS already active");
+       return (-1);
+    }
+    if (state->tls_use_tls == 0) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "502 Error: command not implemented");
+       return (-1);
+    }
+    if (smtpd_tls_ctx == 0) {
+       smtpd_chat_reply(state, "454 TLS not available due to local problem");
+       return (-1);
+    }
+    smtpd_chat_reply(state, "220 Ready to start TLS");
+    smtp_flush(state->client);
+
+    /*
+     * Reset all inputs to the initial state.
+     * 
+     * XXX RFC 2487 does not forbid the use of STARTTLS while mail transfer is
+     * in progress, so we have to allow it even when it makes no sense.
+     */
+    helo_reset(state);
+    mail_reset(state);
+    rcpt_reset(state);
+
+    /*
+     * Turn on TLS, using code that is shared with TLS wrapper mode. This
+     * code does not return when the handshake fails.
+     */
+    smtpd_start_tls(state);
+    return (0);
+}
+
+/* tls_reset - undo STARTTLS */
+
+static void tls_reset(SMTPD_STATE *state)
+{
+    int     failure = 0;
+
+    /*
+     * Don't waste time when we lost contact.
+     */
+    if (state->tls_context) {
+       if (vstream_feof(state->client) || vstream_ferror(state->client))
+           failure = 1;
+       vstream_fflush(state->client);          /* NOT: smtp_flush() */
+       tls_server_stop(smtpd_tls_ctx, state->client, var_smtpd_starttls_tmout,
+                       failure, &(state->tls_info));
+       state->tls_context = 0;
+    }
+}
+
+#endif
+
  /*
   * The table of all SMTP commands that we know. Set the junk limit flag on
   * any command that can be repeated an arbitrary number of times without
@@ -2586,11 +2884,15 @@ typedef struct SMTPD_CMD {
     int     flags;
 } SMTPD_CMD;
 
-#define SMTPD_CMD_FLAG_LIMIT    (1<<0) /* limit usage */
+#define SMTPD_CMD_FLAG_LIMIT   (1<<0)  /* limit usage */
+#define SMTPD_CMD_FLAG_PRE_TLS (1<<1)  /* allow before STARTTLS */
 
 static SMTPD_CMD smtpd_cmd_table[] = {
-    "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
-    "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
+    "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS,
+    "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS,
+#ifdef USE_TLS
+    "STARTTLS", starttls_cmd, SMTPD_CMD_FLAG_PRE_TLS,
+#endif
 #ifdef USE_SASL_AUTH
     "AUTH", smtpd_sasl_auth_cmd, 0,
 #endif
@@ -2598,10 +2900,10 @@ static SMTPD_CMD smtpd_cmd_table[] = {
     "RCPT", rcpt_cmd, 0,
     "DATA", data_cmd, 0,
     "RSET", rset_cmd, SMTPD_CMD_FLAG_LIMIT,
-    "NOOP", noop_cmd, SMTPD_CMD_FLAG_LIMIT,
+    "NOOP", noop_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS,
     "VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
     "ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
-    "QUIT", quit_cmd, 0,
+    "QUIT", quit_cmd, SMTPD_CMD_FLAG_PRE_TLS,
     "XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT,
     "XFORWARD", xforward_cmd, SMTPD_CMD_FLAG_LIMIT,
     0,
@@ -2660,6 +2962,20 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
 
     case 0:
 
+       /*
+        * In TLS wrapper mode, turn on TLS using code that is shared with
+        * the STARTTLS command. This code does not return when the handshake
+        * fails.
+        * 
+        * XXX We must start TLS before we can apply the connection and rate
+        * limits, because otherwise there is no way to report transgressions
+        * to the client.  This is unfortunate.
+        */
+#ifdef USE_TLS
+       if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode)
+           smtpd_start_tls(state);
+#endif
+
        /*
         * XXX The client connection count/rate control must be consistent in
         * its use of client address information in connect and disconnect
@@ -2751,6 +3067,16 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
                state->error_count++;
                continue;
            }
+#ifdef USE_TLS
+           if (state->tls_enforce_tls &&
+               !state->tls_context &&
+               (cmdp->flags & SMTPD_CMD_FLAG_PRE_TLS) == 0) {
+               smtpd_chat_reply(state,
+                                "530 Must issue a STARTTLS command first");
+               state->error_count++;
+               continue;
+           }
+#endif
            state->where = cmdp->name;
            if (cmdp->action(state, argc, argv) != 0)
                state->error_count++;
@@ -2798,6 +3124,9 @@ static void smtpd_proto(SMTPD_STATE *state, const char *service)
      * Cleanup whatever information the client gave us during the SMTP
      * dialog.
      */
+#ifdef USE_TLS
+    tls_reset(state);
+#endif
     helo_reset(state);
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)
@@ -2832,6 +3161,28 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
     smtpd_state_init(&state, stream, service);
     msg_info("connect from %s[%s]", state.name, state.addr);
 
+    /*
+     * With TLS wrapper mode, we run on a dedicated port and turn on TLS
+     * before actually speaking the SMTP protocol. This implies TLS enforce
+     * mode.
+     * 
+     * With non-wrapper mode, TLS enforce mode implies that we don't advertise
+     * AUTH before the client issues STARTTLS.
+     */
+#ifdef USE_TLS
+    if (!SMTPD_STAND_ALONE((&state))) {
+       if (var_smtpd_tls_wrappermode) {
+           state.tls_use_tls = 1;
+           state.tls_enforce_tls = 1;
+       } else {
+           state.tls_use_tls = var_smtpd_use_tls | var_smtpd_enforce_tls;
+           state.tls_enforce_tls = var_smtpd_enforce_tls;
+       }
+       if (var_smtpd_tls_auth_only || state.tls_enforce_tls)
+           state.tls_auth_only = 1;
+    }
+#endif
+
     /*
      * XCLIENT must not override its own access control.
      */
@@ -2909,6 +3260,23 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
                 VAR_SMTPD_SASL_ENABLE);
 #endif
 
+    /*
+     * Keys can only be loaded when running with suitable permissions. When
+     * called from "sendmail -bs" this is not the case, but STARTTLS is not
+     * used in this scenario anyhow.
+     */
+    if (getuid() == 0 || getuid() == var_owner_uid) {
+       if (var_smtpd_use_tls || var_smtpd_enforce_tls
+           || var_smtpd_tls_wrappermode)
+#ifdef USE_TLS
+           smtpd_tls_ctx =
+               tls_server_init(var_smtpd_tls_ccert_vd,
+                               var_smtpd_tls_ask_ccert);
+#else
+           msg_warn("TLS has been selected, but TLS support is not compiled in");
+#endif
+    }
+
     /*
      * flush client.
      */
@@ -2933,7 +3301,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
      * recipient checks, address mapping, header_body_checks?.
      */
     smtpd_input_transp_mask =
-    input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
+       input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
 
     /*
      * Sanity checks. The queue_minfree value should be at least as large as
@@ -2992,6 +3360,9 @@ int     main(int argc, char **argv)
        VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
        VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
        VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
+#endif
+#ifdef USE_TLS
+       VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
 #endif
        0,
     };
@@ -3003,6 +3374,9 @@ int     main(int argc, char **argv)
        VAR_SMTPD_POLICY_TMOUT, DEF_SMTPD_POLICY_TMOUT, &var_smtpd_policy_tmout, 1, 0,
        VAR_SMTPD_POLICY_IDLE, DEF_SMTPD_POLICY_IDLE, &var_smtpd_policy_idle, 1, 0,
        VAR_SMTPD_POLICY_TTL, DEF_SMTPD_POLICY_TTL, &var_smtpd_policy_ttl, 1, 0,
+#ifdef USE_TLS
+       VAR_SMTPD_STARTTLS_TMOUT, DEF_SMTPD_STARTTLS_TMOUT, &var_smtpd_starttls_tmout, 1, 0,
+#endif
        0,
     };
     static CONFIG_BOOL_TABLE bool_table[] = {
@@ -3016,6 +3390,15 @@ int     main(int argc, char **argv)
        VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
        VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from,
        VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt,
+       VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
+       VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
+       VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode,
+#ifdef USE_TLS
+       VAR_SMTPD_TLS_AUTH_ONLY, DEF_SMTPD_TLS_AUTH_ONLY, &var_smtpd_tls_auth_only,
+       VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
+       VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
+       VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
+#endif
        0,
     };
     static CONFIG_STR_TABLE str_table[] = {
@@ -3062,6 +3445,10 @@ int     main(int argc, char **argv)
        VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 0, 0,
        VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
        VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
+#ifdef USE_TLS
+       VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0,
+       VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0,
+#endif
        0,
     };
     static CONFIG_RAW_TABLE raw_table[] = {
index 45b9c9c6fcbcca2233c164cbbef2b7c5b775c23c..a789fb7b36c29023170636cc32c4f80558ed4a06 100644 (file)
   */
 #include <mail_stream.h>
 
+ /*
+  * Postfix TLS library.
+  */
+#ifdef USE_TLS
+#include <tls.h>
+#endif
+
  /*
   * Variables that keep track of conversation state. There is only one SMTP
   * conversation at a time, so the state variables can be made global. And
@@ -142,6 +149,18 @@ typedef struct SMTPD_STATE {
      * XFORWARD server state.
      */
     SMTPD_XFORWARD_ATTR xforward;      /* up-stream logging info */
+
+    /*
+     * TLS related state.
+     */
+#ifdef USE_TLS
+    int     tls_use_tls;               /* can use TLS */
+    int     tls_enforce_tls;           /* must use TLS */
+    int     tls_auth_only;             /* use SASL over TLS only */
+    TLScontext_t *tls_context;         /* TLS session state */
+    tls_info_t tls_info;               /* legacy */
+#endif
+
 } SMTPD_STATE;
 
 #define SMTPD_STATE_XFORWARD_INIT  (1<<0)      /* xforward preset done */
@@ -269,4 +288,11 @@ extern int smtpd_input_transp_mask;
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
index 47345514b87ebc774c1eef918e168968c4372183..cc3e901ec34e0fee78f42609cdbbfabefdc6dcbe 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
 #include <string_list.h>
 #include <namadr_list.h>
 #include <domain_list.h>
-#include <string_list.h>
 #include <mail_params.h>
 #include <rewrite_clnt.h>
 #include <resolve_clnt.h>
@@ -284,6 +290,9 @@ static MAPS *smtpd_sender_login_maps;
 static DOMAIN_LIST *relay_domains;
 static NAMADR_LIST *mynetworks;
 static NAMADR_LIST *perm_mx_networks;
+#ifdef USE_TLS
+static MAPS *relay_ccerts;
+#endif
 
  /*
   * How to do parent domain wildcard matching, if any.
@@ -590,6 +599,10 @@ void    smtpd_check_init(void)
     perm_mx_networks =
        namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
                         var_perm_mx_networks);
+#ifdef USE_TLS
+    relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_smtpd_relay_ccerts,
+                              DICT_FLAG_LOCK);
+#endif
 
     /*
      * Pre-parse and pre-open the recipient maps.
@@ -1103,6 +1116,36 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
 
 static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
 
+/* permit_tls_clientcerts - OK/DUNNO for message relaying */
+
+#ifdef USE_TLS
+static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
+{
+    char   *low_name;
+    const char *found;
+
+    if (state->tls_info.peer_verified && permit_all_certs) {
+       if (msg_verbose)
+           msg_info("Relaying allowed for all verified client certificates");
+       return(SMTPD_CHECK_OK);
+    }
+
+    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
+       low_name = lowercase(mystrdup(state->tls_info.peer_fingerprint));
+       found = maps_find(relay_ccerts, low_name, DICT_FLAG_FIXED);
+       myfree(low_name);
+       if (found) {
+           if (msg_verbose)
+               msg_info("Relaying allowed for certified client: %s", found);
+           return (SMTPD_CHECK_OK);
+       } else if (msg_verbose)
+           msg_info("relay_clientcerts: No match for fingerprint '%s'",
+                    state->tls_info.peer_fingerprint);
+    }
+    return (SMTPD_CHECK_DUNNO);
+}
+#endif
+
 /* check_relay_domains - OK/FAIL for message relaying */
 
 static int check_relay_domains(SMTPD_STATE *state, char *recipient,
@@ -3312,6 +3355,12 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
                                          SMTPD_CHECK_OK, SMTPD_CHECK_DUNNO);
 #else
                msg_warn("restriction `%s' ignored: no SASL support", name);
+#endif
+#ifdef USE_TLS
+       } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
+         status = permit_tls_clientcerts(state, 1);
+       } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
+         status = permit_tls_clientcerts(state, 0);
 #endif
        } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
            if (state->recipient)
@@ -4130,6 +4179,11 @@ char   *var_etrn_checks = "";
 char   *var_data_checks = "";
 char   *var_eod_checks = "";
 char   *var_relay_domains = "";
+
+#ifdef USE_TLS
+char   *var_relay_ccerts = "";
+
+#endif
 char   *var_mynetworks = "";
 char   *var_notify_classes = "";
 
index 8d20e2dc838ef23de7a92c20cc3269a885a0cfa1..60b2ace13ce35b064455bd0cf54383aa8557ce7f 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
@@ -129,6 +136,13 @@ int     smtpd_sasl_auth_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "503 Error: authentication not enabled");
        return (-1);
     }
+#ifdef USE_TLS
+    if (state->tls_auth_only && !state->tls_context) {
+       state->error_mask |= MAIL_ERROR_PROTOCOL;
+       smtpd_chat_reply(state, "538 Encryption required for requested authentication mechanism");
+       return (-1);
+    }
+#endif
     if (state->sasl_username) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        smtpd_chat_reply(state, "503 Error: already authenticated");
index e51739f851cbe5577128242b4f7f88e20f86faeb..d8116b2809cdec04564f07e28d33de5aa9e4afd8 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     TLS support originally by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
 /*--*/
 
 /* System library. */
@@ -116,6 +123,13 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->instance = vstring_alloc(10);
     state->seqno = 0;
     state->rewrite_context = 0;
+#ifdef USE_TLS
+    state->tls_use_tls = 0;
+    state->tls_enforce_tls = 0;
+    state->tls_auth_only = 0;
+    state->tls_context = 0;
+    state->tls_info = tls_info_zero;
+#endif
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
diff --git a/postfix/src/tls/.indent.pro b/postfix/src/tls/.indent.pro
new file mode 120000 (symlink)
index 0000000..5c837ec
--- /dev/null
@@ -0,0 +1 @@
+../../.indent.pro
\ No newline at end of file
diff --git a/postfix/src/tls/Makefile.in b/postfix/src/tls/Makefile.in
new file mode 100644 (file)
index 0000000..591b6f8
--- /dev/null
@@ -0,0 +1,233 @@
+SHELL  = /bin/sh
+SRCS   = tls_prng_dev.c tls_prng_egd.c tls_prng_file.c \
+       tls_prng_exch.c tls_stream.c tls_bio_ops.c tls_misc.c tls_dh.c \
+       tls_rsa.c tls_verify.c tls_certkey.c tls_session.c tls_temp.c \
+       tls_client.c tls_server.c tls_scache.c tls_mgr.c tls_seed.c
+OBJS   = tls_prng_dev.o tls_prng_egd.o tls_prng_file.o \
+       tls_prng_exch.o tls_stream.o tls_bio_ops.o tls_misc.o tls_dh.o \
+       tls_rsa.o tls_verify.o tls_certkey.o tls_session.o tls_temp.o \
+       tls_client.o tls_server.o tls_scache.o tls_mgr.o tls_seed.o
+HDRS   = tls.h tls_prng.h tls_scache.h tls_mgr.h
+TESTSRC        = 
+DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+INCL   =
+LIB    = libtls.a
+TESTPROG= tls_dh tls_mgr
+
+LIBS   = ../../lib/libglobal.a ../../lib/libutil.a
+LIB_DIR        = ../../lib
+INC_DIR        = ../../include
+MAKES  =
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+all: $(LIB)
+
+Makefile: Makefile.in
+       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+
+test:  $(TESTPROG)
+
+$(LIB):        $(OBJS)
+       $(AR) $(ARFL) $(LIB) $?
+       $(RANLIB) $(LIB)
+
+$(LIB_DIR)/$(LIB): $(LIB)
+       cp $(LIB) $(LIB_DIR)
+       $(RANLIB) $(LIB_DIR)/$(LIB)
+
+update: $(LIB_DIR)/$(LIB) $(HDRS)
+       -for i in $(HDRS); \
+       do \
+         cmp -s $$i $(INC_DIR)/$$i 2>/dev/null || cp $$i $(INC_DIR); \
+       done
+       cd $(INC_DIR); chmod 644 $(HDRS)
+
+printfck: $(OBJS) $(PROG)
+       rm -rf printfck
+       mkdir printfck
+       cp *.h printfck
+       sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+       set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+       cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+       lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+       rm -f *.o $(LIB) *core $(TESTPROG) junk
+       rm -rf printfck
+
+tidy:  clean
+
+tls_dh:        $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+tls_mgr: $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+depend: $(MAKES)
+       (sed '1,/^# do not edit/!d' Makefile.in; \
+       set -e; for i in [a-z][a-z0-9]*.c; do \
+           $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+           -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
+       done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+tls_bio_ops.o: tls_bio_ops.c
+tls_bio_ops.o: ../../include/sys_defs.h
+tls_bio_ops.o: ../../include/msg.h
+tls_bio_ops.o: ../../include/iostuff.h
+tls_bio_ops.o: tls.h
+tls_bio_ops.o: ../../include/vstream.h
+tls_bio_ops.o: ../../include/vbuf.h
+tls_bio_ops.o: ../../include/vstring.h
+tls_certkey.o: tls_certkey.c
+tls_certkey.o: ../../include/sys_defs.h
+tls_certkey.o: ../../include/msg.h
+tls_certkey.o: tls.h
+tls_certkey.o: ../../include/vstream.h
+tls_certkey.o: ../../include/vbuf.h
+tls_certkey.o: ../../include/vstring.h
+tls_client.o: tls_client.c
+tls_client.o: ../../include/sys_defs.h
+tls_client.o: ../../include/mymalloc.h
+tls_client.o: ../../include/vstring.h
+tls_client.o: ../../include/vbuf.h
+tls_client.o: ../../include/vstream.h
+tls_client.o: ../../include/stringops.h
+tls_client.o: ../../include/msg.h
+tls_client.o: ../../include/mail_params.h
+tls_client.o: tls_mgr.h
+tls_client.o: tls.h
+tls_dh.o: tls_dh.c
+tls_dh.o: ../../include/sys_defs.h
+tls_dh.o: ../../include/msg.h
+tls_dh.o: tls.h
+tls_dh.o: ../../include/vstream.h
+tls_dh.o: ../../include/vbuf.h
+tls_dh.o: ../../include/vstring.h
+tls_mgr.o: tls_mgr.c
+tls_mgr.o: ../../include/sys_defs.h
+tls_mgr.o: ../../include/msg.h
+tls_mgr.o: ../../include/vstream.h
+tls_mgr.o: ../../include/vbuf.h
+tls_mgr.o: ../../include/vstring.h
+tls_mgr.o: ../../include/attr.h
+tls_mgr.o: ../../include/attr_clnt.h
+tls_mgr.o: ../../include/mail_params.h
+tls_mgr.o: ../../include/mail_proto.h
+tls_mgr.o: ../../include/iostuff.h
+tls_mgr.o: tls_mgr.h
+tls_misc.o: tls_misc.c
+tls_misc.o: ../../include/sys_defs.h
+tls_misc.o: ../../include/vstream.h
+tls_misc.o: ../../include/vbuf.h
+tls_misc.o: ../../include/msg.h
+tls_misc.o: ../../include/mymalloc.h
+tls_misc.o: ../../include/vstring.h
+tls_misc.o: tls.h
+tls_prng_dev.o: tls_prng_dev.c
+tls_prng_dev.o: ../../include/sys_defs.h
+tls_prng_dev.o: ../../include/msg.h
+tls_prng_dev.o: ../../include/mymalloc.h
+tls_prng_dev.o: ../../include/connect.h
+tls_prng_dev.o: ../../include/iostuff.h
+tls_prng_dev.o: tls_prng.h
+tls_prng_egd.o: tls_prng_egd.c
+tls_prng_egd.o: ../../include/sys_defs.h
+tls_prng_egd.o: ../../include/msg.h
+tls_prng_egd.o: ../../include/mymalloc.h
+tls_prng_egd.o: ../../include/connect.h
+tls_prng_egd.o: ../../include/iostuff.h
+tls_prng_egd.o: tls_prng.h
+tls_prng_exch.o: tls_prng_exch.c
+tls_prng_exch.o: ../../include/sys_defs.h
+tls_prng_exch.o: ../../include/msg.h
+tls_prng_exch.o: ../../include/mymalloc.h
+tls_prng_exch.o: ../../include/iostuff.h
+tls_prng_exch.o: ../../include/myflock.h
+tls_prng_exch.o: tls_prng.h
+tls_prng_file.o: tls_prng_file.c
+tls_prng_file.o: ../../include/sys_defs.h
+tls_prng_file.o: ../../include/msg.h
+tls_prng_file.o: ../../include/mymalloc.h
+tls_prng_file.o: ../../include/connect.h
+tls_prng_file.o: ../../include/iostuff.h
+tls_prng_file.o: tls_prng.h
+tls_rsa.o: tls_rsa.c
+tls_rsa.o: ../../include/sys_defs.h
+tls_rsa.o: tls.h
+tls_rsa.o: ../../include/vstream.h
+tls_rsa.o: ../../include/vbuf.h
+tls_rsa.o: ../../include/vstring.h
+tls_scache.o: tls_scache.c
+tls_scache.o: ../../include/sys_defs.h
+tls_scache.o: ../../include/msg.h
+tls_scache.o: ../../include/dict.h
+tls_scache.o: ../../include/vstream.h
+tls_scache.o: ../../include/vbuf.h
+tls_scache.o: ../../include/argv.h
+tls_scache.o: ../../include/stringops.h
+tls_scache.o: ../../include/vstring.h
+tls_scache.o: ../../include/mymalloc.h
+tls_scache.o: ../../include/hex_code.h
+tls_scache.o: ../../include/myflock.h
+tls_scache.o: tls_scache.h
+tls_seed.o: tls_seed.c
+tls_seed.o: ../../include/sys_defs.h
+tls_seed.o: ../../include/msg.h
+tls_seed.o: ../../include/vstring.h
+tls_seed.o: ../../include/vbuf.h
+tls_seed.o: tls_mgr.h
+tls_seed.o: tls.h
+tls_seed.o: ../../include/vstream.h
+tls_server.o: tls_server.c
+tls_server.o: ../../include/sys_defs.h
+tls_server.o: ../../include/mymalloc.h
+tls_server.o: ../../include/vstring.h
+tls_server.o: ../../include/vbuf.h
+tls_server.o: ../../include/vstream.h
+tls_server.o: ../../include/dict.h
+tls_server.o: ../../include/argv.h
+tls_server.o: ../../include/stringops.h
+tls_server.o: ../../include/msg.h
+tls_server.o: ../../include/hex_code.h
+tls_server.o: ../../include/mail_params.h
+tls_server.o: tls_mgr.h
+tls_server.o: tls.h
+tls_session.o: tls_session.c
+tls_session.o: ../../include/sys_defs.h
+tls_session.o: ../../include/vstream.h
+tls_session.o: ../../include/vbuf.h
+tls_session.o: ../../include/msg.h
+tls_session.o: ../../include/mymalloc.h
+tls_session.o: tls.h
+tls_session.o: ../../include/vstring.h
+tls_stream.o: tls_stream.c
+tls_stream.o: ../../include/sys_defs.h
+tls_stream.o: ../../include/iostuff.h
+tls_stream.o: ../../include/vstream.h
+tls_stream.o: ../../include/vbuf.h
+tls_stream.o: ../../include/msg.h
+tls_stream.o: tls.h
+tls_stream.o: ../../include/vstring.h
+tls_temp.o: tls_temp.c
+tls_temp.o: ../../include/sys_defs.h
+tls_temp.o: tls.h
+tls_temp.o: ../../include/vstream.h
+tls_temp.o: ../../include/vbuf.h
+tls_temp.o: ../../include/vstring.h
+tls_verify.o: tls_verify.c
+tls_verify.o: ../../include/sys_defs.h
+tls_verify.o: ../../include/msg.h
+tls_verify.o: tls.h
+tls_verify.o: ../../include/vstream.h
+tls_verify.o: ../../include/vbuf.h
+tls_verify.o: ../../include/vstring.h
diff --git a/postfix/src/tls/TLS_ACKNOWLEDGEMENTS b/postfix/src/tls/TLS_ACKNOWLEDGEMENTS
new file mode 100644 (file)
index 0000000..93c93d5
--- /dev/null
@@ -0,0 +1,56 @@
+- Walcir Fontanini <walcir@densis.fee.unicamp.br>
+  * tested on Solaris 2.5 and and reported missing "snprintf()"
+    -> was fixed in pfixtls-0.1.2
+  * contributed the script to add fingerprints
+       contributed/fp.csh
+
+- Matti Aarnio <matti.aarnio@sonera.fi> (www.zmailer.org)
+  * updated pfixtls_dump to need fewer strcat and strcpy calls.
+
+- Cerebus <cerebus@sackheads.org>
+  * Missing variable initialization in client mode enable STARTTLS
+    negotiation even when not wanted.
+    -> fixed in pfixtls-0.2.8 
+
+- Bodo Moeller <bode@openssl.org>
+  * The SSL connection was not shut down at the end of the session, because
+    SSL_CTX_set_quiet_shutdown() was set. This however did not mean "do a
+    quiet shutdown" but "do not shutdown SSL".
+    -> fixed in pfixtls-0.3.3
+
+- Jeff Johnson <jeff@websitefactory.net>
+  * noted that the patch code will not compile with SSL disabled anymore,
+    because a Â´#ifdef HAS_SSL #endif´ encapsulation was missing in
+    smtp/smtp_connect.c. This must have been in since the very beginning
+    of client mode support (0.2.x).
+    -> fixed in 0.3.6
+
+- Craig Sanders <craig@taz.net.au>
+  * noted that the Received: header does not contain sufficient information
+    whether a client certificate was not requested or not presented.
+    He also reminded me that the session cache must be cleared when
+    experimenting with the setup and certificates, what is not explained
+    in the documenation.
+    -> fixed in 0.4.4
+
+- Claus Assmann <ca+tls@esmtp.org>
+  * pointed out that the Received: header logging about the TLS state violated
+    RFC822. The TLS information must be in comment form "(info)".
+    -> fixed in 0.6.3
+
+- Wietse Venema <wietse@porcupine.org>
+  * uncounted important suggestions to start the integration into the Postfix
+    mainstream code.
+  * code adjustments in the dict_*() database code to allow easier inclusion
+    and use for session caching, and this is only the beginning :-)
+    -> started reprogramming Postfix/TLS to fit both Wietse's and my
+       requirements as of 0.6.0
+
+- Damien Miller <djm@mindrot.org>
+  * Found mismatch between documentation and code with regard to logging.
+    -> fixed in 0.6.6
+
+- Deti Fliegl <fliegl@cs.tum.edu>
+  * Provided an initial patch to support SubjectAlternativeName/dNSName
+    checks.
+    -> added in 0.8.14
diff --git a/postfix/src/tls/TLS_CHANGES b/postfix/src/tls/TLS_CHANGES
new file mode 100644 (file)
index 0000000..62a529e
--- /dev/null
@@ -0,0 +1,2418 @@
+2004/09/12     == Released 0.8.19 ==
+
+2004/09/01
+  - Finished updating the code by adjusting to postfix-2.2-20040829
+    and started using it at my own site.
+
+2004/08/01
+  - Started adjusting the patch to postfix-2.2-20040729.
+
+2004/06/21     == Re-released 0.8.18 ==
+
+2004/06/21
+  - Postfix 2.1.3 has been released. Shortlived 2.1.2 did bring an
+    incompatibel change (patch conflict) which has been resolved.
+  - Fixed some typos in the tlsmgr.8 manual page (Chris Pepper
+    <pepper@reppep.com>).
+
+2004/04/27     == Re-released 0.8.18 ==
+
+2004/04/27
+  - Postfix 2.1.0 has been released. Some minor patch conflicts with respect
+    to the actual code and build environment.
+  - Due to the restructuring of the documentation the old sample-*.cf
+    files are no longer available.
+    Took documentation already adopted by Wietse for the 2.1-RC2-IPV6+TLS
+    snapshot.
+
+2004/02/09     == Re-released 0.8.18 ==
+
+2004/02/09
+  - Postfix 2.0.18-20040205 is available, patchkit applies without
+    problems.
+
+2004/02/02     == Release 0.8.18 ==
+
+2004/02/02
+  - Incorporated Luca Berra's information into the patchkit and ran tests
+    with my own versions.
+
+2004/02/01
+  - Reports about server side SMTP failure with Carsten's patch can be
+    found on postfix-users.
+    'Luca Berra' <bluca@comedia.it> informs, that he discoverd another
+    failure of the GNU patch program with a misplaced patch hunk in
+    smtpd.c
+
+2004/01/30
+  - Edited in additional #ifdef USE_TLS conditionals. If the TLS patch
+    is applied but not activated (USE_TLS is not defined), a warning is
+    printed as soon as TLS shall be used.
+
+2004/01/23
+  - Postfix 2.0.18-20040122 is now available. Several patch conflicts occur.
+    Even more: one hunk of the patch (which is provided in unified diff)
+    fails in smtp.c and causes a segmentation violation.
+    Carsten Hoeger <choeger@suse.de> provides an adapted patch kit.
+
+2004/01/02     == Released 0.8.17 ==
+
+2004/01/02
+  - Postfix-2.0.16-20031231 is released. No patch conflicts.
+  - Changed autoresponder for TLS tests to "The Postfix Book" echo
+    responder (provided by Patrick Koetter and Ralf Hildebrandt).
+
+2003/12/30
+  - Postfix-2.0.16-20031226 is released. No patch conflicts.
+
+2003/12/26
+  - Postfix-2.0.16-20031224 is released. Resolved patch conflicts.
+
+2003/12/16
+  - Postfix-2.0.16-20031215 is released. Resolved patch conflicts.
+  - src/global/pfixtls.c: changed occurance of "ssize_t" to "size_t"
+    as some quite old operating systems do no have ssize_t
+    (Reported by Klaus Jaehne <kj@uue.org> for SunOS 4.1.4).
+  - src/global/pfixtls.c: both the client and the server engine did
+    print out messages even when tls_loglevel was set to 0 (reported
+    by Florian Effenberger <florian@effenberger.org>): evaluate loglevel
+    before printing any message.
+
+2003/11/17     == Re-released 0.8.16 ==
+
+2003/11/17
+  - Postfix 2.0.16-20031113 is released. Some minor patch conflicts.
+
+2003/10/27     == Re-released 0.8.16 ==
+
+2003/10/24
+  - Postfix 2.0.16-20031022 is released. Some minor patch conflicts.
+
+2003/09/23     == Re-released 0.8.16 ==
+
+2003/09/23
+  - Postfix 2.0.16 and 2.0.16-20030921 are now available.
+    Resolved some minor patch conflicts.
+
+2003/09/10     == Released 0.8.16 ==
+
+2003/09/09
+  - Postfix 2.0.15 has been released including another workaround for
+    select() on Solaris problems. It contains additional code to catch
+    EAGAIN on read() in the timed_read() routine (and the respective
+    precautions in timed_write()
+  - Note: this fix is not yet part of Postfix 2.0.14-20030812.
+  - Added corresponding code to pfixtls_timed_read()/_write().
+  - Changed SSL wrappermode behaviour: use smtpd_sasl_tls_security_options
+    instead of smtpd_sasl_security_options as is to be expected because TLS
+    is active. (Bug reported by Bob Snyder <rsnyder@toontown.erial.nj.us>.)
+
+2003/08/29      == Re-released 0.8.15 ==
+
+2003/08/29
+  - Adapted patchkit to Postfix 2.0.14. No patch conflicts.
+
+2003/07/17     == Re-released 0.8.15a (-20030715 only) ==
+
+2003/07/16
+  - Experimental version Postfix 2.0.14-20030715 is released, including
+    the SASL changes. Resolved some minor patch conflicts.
+
+2003/07/11     == Released 0.8.15a (-20030706 only) ==
+
+2003/07/11
+  - Received error report about about TLS failing with the new smtpd_proxy
+    feature including instructions on how to reproduce.
+    (Did receive an earlier report on 2003/07/09, that however indicated other
+    setup problems, so that the actual problem was not visible.)
+  - Analysis: when introducing the new smtpd_proxy feature, different mechnisms
+    where introduced to either write to the cleanup daemon (as before) or to
+    the smtpd_proxy connection. Functions and streams are now expressed in
+    out_fprintf() function pointers etc. being assigned accordingly.
+    When updating to 0.8.15/2.0.13-20030706 this change was missed and the
+    routine adding the TLS information to the Received: headers did use the
+    older rec_fprintf() functions etc. This did work fine for the traditional
+    connection to the cleanup service, but naturally failed for smtpd_proxy
+    (with a segmentation violation).
+    Solution: access out_stream via the according pointers.
+  - The 2.0.13 stable version is not affected.
+
+2003/07/08     == Released 0.8.15 ==
+
+2003/07/07
+  - Postfix 2.0.13 and 2.0.13-20030706 are released.
+    Patchkit for 2.0.13 applies cleanly.
+    Patchkit for 2.0.13-20030607 requires several adaptations (patch conflicts,
+    no functional changes).
+  - Slightly modified SASL interface code (smpt[d]_sasl_glue layer) to
+    allow setting the security policy during session setup instead of
+    process start. This allows to actually choose SASL mechanisms available
+    depending on the availability of TLS encryption and authentication.
+    New parameters: smtpd_sasl_tls_security_options,
+    smtp_sasl_tls_security_options, smtp_sasl_tls_verified_security_options
+  - Submitted change to SASL interface to Wietse, who accepted the change
+    as part of the Snapshot line.
+
+2003/06/19     == Released 0.8.14 ==
+
+2003/06/19
+  - Add support for SubjectAlternativeName "dNSName" entries in certificate
+    checking (applies for client mode only).
+    If the client connects to the server, it does check the list of dNSName
+    entries against the expected hostname (therefore allowing the server to
+    have multiple identities). As described in RFC2818 (HTTP over TLS),
+    CommonName (CN) entries are only checked, if no dNSName entries are found
+    at all.
+    Initial patch proposed by Deti Fliegl <fliegl@cs.tum.edu>, reworked to
+    follow the RFC2818 rules and some cleanup.
+
+2003/06/18
+  - Checked out similar settings, found another missing entry:
+    var_smtp_scert_vd was missing src/smtp/smtp.c.
+  - Renamed HAS_SSL to USE_TLS for compilation (have to use -DUSE_SSL
+    in the future). Currently pfixtls.h will take care of setting
+    USE_TLS, when HAS_SSL has been defined.
+
+2003/06/17
+  - Received bug reports about Postfix/TLS failing (connection closing)
+    after having finished the "STARTTLS"/"220 Ready to start TLS"
+    dialogue. (Actually the first report came in via private mail on
+    2003/06/12, but the information was too diffuse to track down).
+    Tracking down became possible after it became clear, that only Solaris
+    systems are affected.
+    Analysis:
+    * As of 2003/06/09 postfix uses non-blocking socket I/O for the SMTP
+      connection on Solaris platforms. This requires using "select()" style
+      waiting before read() or write() access (which are not prepared EAGAIN
+      or EWOULDBLOCK in the Postfix case and therefore indicate error).
+    * As the var_smtpd_starttls_tmout variable is not correctly initialized
+      (value is 0), the select() style function is not called, therefore
+      read() fails with EAGAIN and the connection is closed due to a
+      presumed error condition.
+    * The initialization of the variable should be done in the time_table[]
+      list during main().
+      The entry however was lost during the patch adaptation from 0.7.13e
+      to 0.7.14-snap20020107 on 2002/01/07.
+    Impact:
+    * On Solaris systems, STARTTLS fails during handshake (server only).
+    * On other systems, the TLS negotiation phase is not protected by the
+      smtpd_starttls_tmout (default 300s) value and may hang until the
+      watchdog kills smtpd, if the client does not continue the handshake.
+    Restored var_smtpd_starttls_tmout variable initialization.
+
+2003/06/12     == Re-released 0.8.13 ==
+
+2003/06/11
+  - Adapted to snapshot 2.0.12-20030611. No patch conflicts.
+
+2003/06/11
+  - Adapted to snapshot 2.0.11-20030609. One minor patch conflict.
+
+2003/05/23     == Re-released 0.8.13 ==
+
+2003/05/23
+  - First release against snapshot 2.0.10-20030523.
+
+2003/04/26     == Re-released 0.8.13 ==
+
+2003/04/26
+  - Updated patchkit to apply to Postfix 2.0.9.
+  - Updated patchkit-name to reflect the release of OpenSSL 0.9.7b.
+
+2003/03/06     == Re-released 0.8.13 ==
+
+2003/03/06
+  - Postfix 2.0.6 has been released. No patch conflicts.
+
+2003/03/02     == Re-released 0.8.13 ==
+
+2003/03/02
+  - Postfix 2.0.4 has been released. "patch" should work with some warnings
+    about moved line numbers.
+  - OpenSSL 0.9.7a has been released. No visible changes with respect to
+    Postfix/TLS.
+
+2003/01/26     == Re-released 0.8.13 ==
+
+2003/01/26
+  - Postfix 2.0.3 has been released. One minor patch-conflict.
+
+2003/01/13     == Released 0.8.13 ==
+
+2003/01/13
+  - Postfix 2.0.1 has been released. Some minor patch conflicts resolved.
+  - Added HOWTO documents contributed by Justin Davies <justin@palmcoder.net>
+    to the contribution area.
+  - Added RFC3207 (SMTP Service Extension for Secure SMTP over Transport Layer
+    Security) to the documentation. RFC3207 is the successor of RFC2487.
+  - Updated TODO list to reflect release ideas up to the release of
+    Postfix/TLS 0.9.0. (Or will it finally be 1.0.0? :-)
+
+2002/12/30
+  - OpenSSL 0.9.7 has been released. Postfix/TLS works best with the new
+    0.9.7 release.
+
+2002/12/24     == Re-released 0.8.12 ==
+
+2002/12/24
+  - Postfix 2.0.0.1 has been released. Resolved one minor patch conflict.
+
+2002/12/20     == Re-released 0.8.12 ==
+
+2002/12/20
+  - Postfix snapshot 1.1.12-20021214 has been released. Resolved minor
+    patch conflicts.
+
+2002/12/15     == Re-released 0.8.12 ==
+
+2002/12/15
+  - Postfix snapshot 1.1.12-20021214 has been released. Two minor patch
+    conflicts.
+
+2002/12/06     == Released 0.8.12 ==
+
+2002/12/06
+  - OpenSSL 0.9.6h has been released. Update documentation and filenames
+    to reflect this new release.
+  - Minor bug fix: when calling "sendmail -bs", smtpd is not run with
+    superuser permissions, therefore the loading of the private key fails.
+    STARTTLS is not used anyway, so the key is not needed anyway, but the
+    failure to load creates a misleading warning.
+    Do not initialize TLS engine at all when not started with superuser
+    permissions.
+
+2002/12/03
+  - Postfix snapshot 1.1.12-20021203 has been released. Resolved one patch
+    conflict.
+
+2002/11/01     == Re-released 0.8.11a ==
+
+2002/11/01
+  - Postfix snapshot 1.1.11-20021031 has been released. No patch conflicts.
+
+2002/10/30     == Re-released 0.8.11a ==
+
+2002/10/30
+  - Postfix snapshot 1.1.11-20021029 has been released. No patch conflicts.
+
+2002/09/30      == Re-released 0.8.11a ==
+
+2002/09/30
+  - Postfix snapshot 1.1.11-20020928 has been released. No patch conflices.
+
+2002/09/24
+  - Postfix snapshot 1.1.11-20020923 has been released. Adapt patchkit.
+
+2002/09/19     == Re-released 0.8.11a ==
+
+2002/09/18
+  - Postfix snapshot 1.1.11-20020917 has been released. Adapt patchkit.
+
+2002/08/23     == Re-released 0.8.11a ==
+
+2002/08/23
+  - Postfix snapshot 1.1.11-20020822 has been released. Adapt patchkit.
+
+2002/08/20
+  - Postfix snapshot 1.1.11-20020819 has been released with several
+    enhancements and changes. Adapt patchkit (minor issues).
+
+2002/08/12
+  - OpenSSL has experienced several (security critical) updates.
+
+2002/07/26     == Re-released 0.8.11a ==
+
+2002/07/26
+  - On popular demand, a new diff for the snapshot version of Postfix
+    is created: postfix-1.1.11-20020719.
+
+2002/06/18     == Re-released 0.8.11a ==
+
+2002/06/18
+  - On popular demand, a new diff for the snapshot versions of Postfix
+    is created: postfix-1.1.11-20020613.
+
+2002/06/03     == Released 0.8.11a ==
+
+2002/06/03
+  - When compiling with SSL but without SASL, compilation fails due to
+    the modification of state->sasl_mechanism_list that is not part of the
+    "state" structure when SASL is not compiled in.
+    This bug was introduced in version 0.8.11.
+    Bug reported and patch supplied by Bernd Matthes
+    <bernd.matthes@gemplus.com>.
+
+2002/05/29     == Released 0.8.11 ==
+
+2002/05/29
+  - Postfix 1.1.11 is released.
+
+2002/05/25
+  - Fix processing of options after STARTTLS handshaking: AUTH= was not
+    handled, as the "=" was not recognized as for the extension list for
+    the case without TLS. (The TLS case was a copy of an older version
+    of the code not yet containing the "=" and the change in the main
+    code slipped through without noting the difference, hence the option
+    as not added to the TLS part.
+    Found by "Christoph Vogel" <Christoph.Vogel@Corbach.de>.
+
+2002/05/24
+  - Bug reported by "Christoph Vogel" <Christoph.Vogel@Corbach.de>:
+    Client side AUTH does not work, if STARTTLS is used: if a server
+    announces AUTH and STARTTLS, AUTH is being used if TLS is disabled.
+    Once TLS is enabled, AUTH is still offered by the server, but the
+    client does not use it any longer.
+    Reason: when AUTH is offered, not only the SMTP_REATURE_AUTH flag
+    is set in state->features, but also the available mechanisms are
+    remembered in state->sasl_mechanism_list. As AUTH may be offered
+    twice by some hosts (in the correct "AUTH mech" form and the older
+    and deprecated "AUTH=mech" form), a check against processing the
+    line twice is included in smtp_sasl_helo_auth(). This check now
+    prevented the correct processing in the second evaluation of the
+    ESMTP extensions offered after the STARTTLS activation.
+    Solution: reset state->sasl_mechanism_list before processing the
+    extension list just like state->features.
+
+2002/05/15     == Released 0.8.10 ==
+
+2002/05/15
+  - Postfix 1.1.10 has been released. No changes.
+
+2002/05/14     == Released 0.8.9 ==
+
+2002/05/14
+  - Postfix 1.1.9 has been released. Patchkit requires a small adjustment
+    (supplied by Tuomo Soini <tis@foobar.fi>).
+
+2002/05/10     == Released 0.8.8 ==
+
+2002/05/10
+  - OpenSSL 0.9.6d has been released. Release the unchanged patchkit
+    with a new version number and under a new filename to indicate
+    that it should be built against 0.9.6d (it has the session caching
+    failure of 0.9.6c fixed). Update documentation accordingly.
+
+2002/05/05
+  - Postfix 1.1.8 has been released, the patchkit applies cleanly.
+
+2002/04/03     == Re-released 0.8.7 ==
+
+2002/04/03
+  - Postfix 1.1.7 has been released, the patchkit applies cleanly.
+    Re-released the patchkit.
+
+2002/03/29     == Released 0.8.7 ==
+
+2002/03/29
+  - Postfix/TLS did not honor the per-recipient-switching-off in SMTP
+    client mode via tls_per_site (per-host-switching off was honored).
+    Patch by Will Day <wd@hpgx.net>.
+
+2002/03/27     == Released 0.8.6 ==
+
+2002/03/27
+  - Postfix 1.1.6 has been released. Adapted patchkit to resolve minor
+    patch conflict. (Template provided by Simon Matter
+    <simon.matter@ch.sauter-bc.com>)
+
+2002/03/13     == Released 0.8.5 ==
+
+2002/03/13
+  - Postfix 1.1.5 has been released. The patchkit would apply cleanly, but
+    obviously the "lock_fd" change that applies to dict_dbm.c (Wietse)
+    also has to be applied to dict_sdbm.c. Tuomo Soini <tis@foobar.fi>
+    kindly provided this change.
+
+2002/02/25     == Released 0.8.4 ==
+
+2002/02/25
+  - Postfix 1.1.4 became visible. One patch conflict in a Makefile
+    (Carsten Hoeger <choeger@suse.de>).
+
+2002/02/21
+  - Dates in this CHANGES document were showing 2001 even though 2002 already
+    began :-). Fixed. (Marvin Solomon <solomon@conceptshopping.com>)
+
+2002/02/07
+  - Bug in the documentation (setup.html): the main.cf variables for the
+    SMTP server process have to be named smtpd_* instead of smtp_*.
+    Found by Andreas Piesk <a.piesk@gmx.net>.
+
+2002/02/03     == Released 0.8.3 ==
+
+2002/02/03
+  - Patch from Andreas Piesk <a.piesk@gmx.net>: remove some compiler warnings
+    by using explicit type casts in hexdump print statements.
+  - Re-released otherwise unchanged patchkit against Postfix-1.1.3.
+
+2002/01/30     == Released 0.8.2 ==
+
+2002/01/30
+  - Re-released unchanged patchkit against Postfix-1.1.2.
+
+2002/01/24     == Released 0.8.1 ==
+
+2002/01/24
+  - Postfix-1.1.1 has been released. The patchkit needed some small adjustment.
+  - Both Tuomo Soini <tis@foobar.fi> and Carsten Hoeger <choeger@suse.de>
+    helped out with this small adjustment. As a side effect of Carsten's
+    complete pfixtls.diff, which I compared after applying Tuomo's adjustment,
+    I found that pfixtls.c contained several wrong "'" characters: on the
+    german keyboard there is an accent looking like the apostroph but producing
+    a different binary code. Obviously on Carsten's machine the code was
+    changed which became obvious during the comparison.
+    (Conclusion: I wrote the comments affected on my SuSE-Linux PC at home with
+    german keyboard. In my university-office I do have HP-UX workstations
+    with US keyboards.)
+
+2002/01/22     == Released 0.8.0 ==
+
+2002/01/22
+  - Received a comment from Wietse on the mailing list, that it is better
+    to resolve the "standalone" issue by using the already available
+    SMTPD_STAND_ALONE() macro in smtpd. Undid 0.7.16 change and made
+    new change in smtpd.c.
+  - Updated links in the References section of the documentation.
+
+2002/01/21     == Released 0.7.16 ==
+
+2002/01/21
+  - When calling "sendmail -bs" and STARTTLS is enabled, smtpd tries to
+    read the private key and fails due to insufficient permissions (smtpd
+    is run with the privileges of the user). This case is caught since
+    version 0.6.18 of the Postfix/TLS patchkit: STARTTLS is still being
+    offered but a "465 temporary failure" message is issued. Some mailers
+    (read this: PINE) will then refuse to continue. (And an irritating
+    error message indicating the failure to read the key will be logged.)
+    Experienced by "Lucky Green" <shamrock@cypherpunks.to> .
+  - Solution: Disable STARTTLS when running "sendmail -bs" by adding
+    "-o smtpd_use_tls=no -o smtpd_enforce_tls=no" to smtpd's arguments
+    upon startup. Using STARTTLS does not make sense in simulated
+    SMTP mode.
+
+2002/01/18     == Released 0.7.15 ==
+
+2002/01/18
+  - Postfix 1.1.0 has been released. The patchkit for the former snapshot
+    version applied cleanly and now becomes the patchkit for the stable
+    version.
+
+2002/01/16     == Released 0.7.14a ==
+
+2002/01/16
+  - Snapshot-20020115 is released. Adapted patchkit.
+  - Add Postfix/TLS entries into the new conf/postfix-files
+    (Tuomo Soini <tis@s.foobar.fi>, Carsten Hoeger <choeger@suse.de>).
+
+2002/01/14
+   - OpenSSL: a user reported that session caching stopped working for him
+     with OpenSSL 0.9.6c. I found that this is also true for my own
+     Postfix/TLS installation.
+     Solution: server side session caching is broken in OpenSSL 0.9.6c when
+     using non-blocking semantics (Postfix/TLS is affected as it uses
+     BIO-pairs); sessions are simply not added to the cache. This bug
+     is not security relevant. A fix has been applied to the OpenSSL source
+     tree for the next release.
+
+2002/01/08     == Released 0.7.14 ==
+
+2002/01/07
+  - New snapshots released as release candidates. Adapted the patchkit
+    to snapshot-20020107. Moved our production servers from 20010228-pl08
+    to snapshot-20020107 with the adapted patchkit.
+  - Fix documentation: tlsmgr can be run chrooted since a long time.
+
+2001/12/21
+  - OpenSSL 0.9.6c is released. Postfix/TLS is fully compatible.
+
+2001/12/19     == Released 0.7.13e ==
+
+2001/12/19
+  - Adapted patchkit to snapshot-20011217.
+
+2001/12/12     == Released 0.7.13d ==
+
+2001/12/12
+  - Adapted patchkit to snapshot-20011210. Adaption provided by
+    Tuomo Soini <tis@foobar.fi>.
+
+2001/11/28     == Released 0.7.13c ==
+
+2001/11/28
+  - Adapted patchkit to snapshot-20011127.
+
+2001/11/26     == Released 0.7.13b ==
+
+2001/11/26
+  - Adapted patchkit to snapshot-20011125.
+
+2001/11/22     == Released 0.7.13a ==
+
+2001/11/22
+  - Adapted patchkit to snapshot-20011121.
+
+2001/11/15     == Released 0.7.13 ==
+
+2001/11/15
+  - Adapted patchkit to postfix-20010228-pl08 and snapshot-20011115.
+
+2001/11/06     == Re-released 0.7.12 ==
+
+2001/11/06
+  - Snapshot-20011105 released. No patch conflicts, but in order to have
+    the pfixtls-* filename and home page entry reflect the new version,
+    I'll re-release 0.7.12.
+
+2001/11/05     == Released 0.7.12 ==
+
+2001/11/05
+  - Release of Postfix-20010228-pl06 and snapshot-20011104. The snapshot
+    version had some minor patch conflicts to be resolved.
+
+2001/10/14     == Released 0.7.11 ==
+
+2001/10/14
+  - Bug fix (client mode): when the peername is checked against the CommonName
+    in the certificate, the comparison does not correclty ignore the case
+    (the peername as returned by DNS query or set in the transport map
+    is not transformed to lower case). This bug was introduced in 0.7.5.
+
+2001/10/09     == Released 0.7.10 ==
+
+2001/10/09
+  - Snapshot-20011008 is released. Some minor adaptions are required to
+    sort out patch conflicts.
+
+2001/09/28
+  - Received patch from Uwe Ohse <use@ohse.de>: There is a bug in sdbm's
+    handling of the .dir file, that also applies to Postfix/TLS.
+    The problem only appears for large databases.
+  - The example entries in conf/master.cf for the submission and smtps services
+    use "chroot=y" flags, while the Postfix default is "chroot=n". This could
+    lead to hardly explainable problems when users did not note this fact
+    during setup.
+    Fixed example entries to also use "chroot=n" default.
+
+2001/09/18
+  - Wietse releases Postfix-20010228-pl05. The patch applies cleanly with
+    "patch -p1 ...", so it is not necessary to release a new patchkit.
+
+2001/09/04     == Released 0.7.9 ==
+
+2001/09/04
+  - Due to unititialized variable in smtpd_state.c, AUTH may not be offered
+    without TLS even though smtpd_tls_auth_only was not enabled.
+    (Patch from Nick Simicich <njs@scifi.squawk.com>.)
+
+2001/08/29
+  - In the snapshot-20010808 version of 0.7.9, the "tlsmgr" line in the sample
+    conf/master.cf is missing (reported by Will Day <wd@hpgx.net>). Fixed.
+
+2001/08/27     == Released 0.7.8 ==
+
+2001/08/27
+  - Received bugreport about issuer_CN imprints consisting of long strings
+    of nonsense. This only appeard with certificates issued from a certain
+    CA (RSA Data Security Inc., Secure Server Certification Authority).
+    (Will Day <wd@hpgx.net>)
+  - The problem: the issuer data of this certificate is:
+        Issuer
+          C=US
+          O=RSA Data Security, Inc.
+          OU=Secure Server Certification Authority
+    It does not contain a CN (CommonName) field. OpenSSL's
+    X509_NAME_get_text_by_NID() function does not catch this condition
+    (no error flag set), but it also does not set the name in the memory
+    location specified.
+  - Solution:
+    1. Preset the memory for the string to '\0', so that a string of length
+       0 is obtained on the failure described above.
+    2. When no CN data is available, use the O (Organization) field
+       instead. The data are used for logging only (it is the issuer, not
+       the subject name), so this change does not affect functionality.
+
+2001/08/22     == Released 0.7.7 ==
+
+2001/08/22
+  - Found one more bug: erronously called SSL_get_ex_new_index() instead
+    of SSL_SESSION_get_ex_new_index() (note the _SESSION missing). This
+    could be responsible for the failure at the locations found during
+    debugging. Works fine on HP-UX (did also before), must cross check
+    at home...
+
+2001/08/21
+  - Received report, that smtp (client) fails with signal 11 (platform:
+    linux redhat). Cannot reproduce any problem on HP-UX (did run 1
+    week in production before release). But malloc() and stack strategies
+    are different between platforms.
+  - Can reproduce the failure on my Linux PC at home :-(.
+  - Found one bug in new_session_cb(): on successfull external caching,
+    success is reported by a return value of 1. This however must be another
+    bug, as it has nothing to do with the locations of the failure, when
+    analyzing the core dumps/running under debugger.
+    Still getting SIGSEGV...
+
+2001/08/20     == Released 0.7.6 ==
+
+2001/08/20
+  - Following "popular demand" implemented new feature and configuration option
+    "smtpd_tls_auth_only": Only allow authentication using the AUTH protocol,
+    when the TLS encryption layer is active. Default is "no" in order to
+    keep compatiblity to postfix without TLS patch.
+    This option does not distinguish between different AUTH mechanisms.
+
+2001/08/16     == Released 0.7.5 ==
+
+2001/08/15
+  - The new session cache handling is working now at my site for quite some
+    time.
+  - Client side: modified peername matching code, such that wildcard
+    certificates can be used. Matching is done as in HTTP/TLS: only the
+    leftmost part of the hostname may be replaced by a '*'.
+
+2001/08/09
+  - Further debugged the CRYPTO_set_ex_data() functionality.
+  - Unified "external cache write" and "external cache remove" callbacks
+    for client and server side. The "external cache read" functions are not
+    that easy to combine, as the lookup keys are quite different and do not
+    match the fixed interface to the callback function.
+  - Change shutdown behaviour according to SSL_shutdown(). When SSL_shutdown()
+    returns, the shutdown handshake may not be complete, if we were the first
+    party to send the shutdown alert. We must call SSL_shutdown() again,
+    to wait for the peer's alert.
+
+2001/08/08
+  - Postfix snapshot 20010808 is being released.
+
+2001/08/08
+  - Rewrite server side to remove externally cached sessions via callback.
+  - Rewrite client side to remove externally cached sessions via callback.
+    This turns out to be more difficult as expected, as the client side
+    session cache is sorted by hostnames, but the callbacks are called
+    with the SSL_SESSION objects. The information must be stored into the
+    SSL_SESSION objects by using the CRYPTO_set_ex_data() functionality,
+    the documentation of which, ahem, ...
+  - Reloading sessions stays separate, as the functionality is different.
+
+2001/08/07
+  - Started reworking the session cache code.
+    * On the server side the retrieval from the external cache and the writing
+      to the cache are handled by callback functions. The removal is handled
+      directly.
+    * On the client side, all session cache operations are performed explicitly.
+    * The explicit handling is on the client side is bad, as it requires a
+      quite complicated logic to detect session reuse and the appropriate
+      handling.
+    * The explicit handling of session removal on both sides is bad, as
+      the OpenSSL library will remove sessions (on session failure) according
+      to the TLS specifications automatically, so we want to take advantage
+      of this feature and have the externally cached sessions removed as
+      required via callback.
+  - First step: on the client side, also use the new_session_cb(), so that
+    new sessions are automatically saved to the external cache on creation.
+
+2001/08/01
+  - Postfix-20010228-pl04 is being released.
+
+2001/07/11     == Released 0.7.4 ==
+
+2001/07/10
+  - Postfix snapshot 20010709 was released. Resolved some minor patch
+    conflicts.
+
+2001/07/10
+  - OpenSSL 0.9.6b has been released including a security fix for the
+    libraries internal pseudo random number generator.
+    * Note: to exploit the weakness, an attacker must be able to retrieve
+      single random bytes. As in Postfix/TLS random bytes are only used
+      indirectly during the SSL handshake, an attacker could never access
+      the PRNG in the way required to exploit the weakness.
+    * Postfix/TLS is therefore not vulnerable (as are most (all?) applications
+      utilizing the SSL layer).
+    * The OpenSSL team however recommends to upgrade or install the bugfix
+      included in the announcement in any case.
+    * Details can be found at http://www.openssl.org/
+
+2001/05/31     == Released 0.7.3a ==
+
+2001/05/30
+  - Report from <Andre.Konopka@Presse-Data.de>: TLS logging does not work.
+    Reason: parameters are not evaluated in mail_params.c, as the corresponding
+    lines for other_int_defaults[] were missing from the patch. This
+    only affected the 0.7.3-snapshot version, the version for "stable"
+    is correct.
+    I will release 0.7.3a with this fix only for the snapshot version to keep
+    version numbering consistent with the "stable" version.
+
+2001/05/28     == Released 0.7.3 ==
+
+2001/05/28
+  - Upgraded to snapshot-20010425: resolved some minor patch conflicts.
+    No functional changes.
+
+2001/05/16
+  - Received french documentation (doc_french/) contributed by
+    Etienne Roulland <Etienne.Roulland@univ-poitiers.fr>.
+
+2001/05/03     == Released 0.7.2 ==
+
+2001/05/03
+  - Postfix-Snapshot 20010502 is released. Bernhard Rosenkraenzer
+    <bero@redhat.de> supplies an adapted patch for Postfix/TLS, as the
+    normal patch has several rejections because of code changes;
+    functionality has not changed.
+
+2001/05/01
+  - Patchlevel 02 of Postfix 20010228 is being released. The Postfix/TLS
+    patchkit applies cleanly when using the "-p1" switch to patch.
+
+2001/04/09     == Released 0.7.1 ==
+
+2001/04/06
+  - OpenSSL 0.9.6a is released. It contains several bugfixes and will become
+    the recommended version to be used with Postfix/TLS.
+    I will run some more test and then re-release Postfix/TLS (without
+    additional changes to the source) as 0.7.1 to make people aware of the
+    new versions of Postfix and OpenSSL.
+
+2001/04/05
+  - Hint from Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>:
+    the "Known Bugs" section in doc/test.html actually contains bugs
+    of clients and/or interoperatbility problems. Better name it
+    "Known interoperability problems" and rename the entries
+    "Postfix/TLS server" and "Postfix/TLS client" to improve clarity.
+
+2001/03/29
+  - Patchlevel 01 of Postfix 20010228 is being released. The Postfix/TLS
+    patchkit applies cleanly when using the "-p1" switch to patch.
+    OpenSSL 0.9.6a will be out within the next handful of days, so I will
+    delay the release of a new patchlevel until then.
+
+2001/03/01     == Released 0.7.0 ==
+  - IMPORTANT: If you are upgrading from a much older version, you will find
+    that some configuration options have changed over time (fingerprints are
+    now handled with ':'. check_relay_ccerts is now permit_tls_clientcerts.
+    Session caching has been reworked.)
+    It is recommended to re-read the sample-tls.cf file or the html version
+    in the documentation.
+
+2001/03/01
+  - Wietse has announced the _release_ version (non-beta) or postfix:
+    20010228!
+  - Applied the Patchkit to the _release_ version (not the snapshot version).
+    Resolved one minor patch conflict.
+  - So, it's time to call this Postfix/TLS 0.7.0.
+
+2001/02/26     == Released 0.6.38 ==
+
+2001/02/26
+  - Snapshot-20010225 has been released. Resolved one minor patch conflict.
+
+2001/02/23     == Released 0.6.37 ==
+
+2001/02/23
+  - Snapshot-20010222 has been announced as RELEASE CANDIDAT. Resolved one
+    minor patch conflict.
+  - Removed "check_relay_ccerts" restriction which has been replaced
+    by "permit_tls_clientcerts" in 0.6.24. (Was left in until now for
+    transition.)
+  - Do not try to save session data > 8kB, since this cannot be handled
+    by SDBM. (This is more or less academical, since I have never met a
+    session even half that large.)
+
+2001/02/19     == Released 0.6.36 ==
+
+2001/02/05
+  - Snapshot-20010204 has been released. Resolved one minor patch conflict.
+
+2001/02/03     == Released 0.6.35 ==
+
+2001/02/03
+  - Snapshot-20010202 has been released. Resolved one minor patch conflict.
+
+2001/01/29     == Released 0.6.34 ==
+
+2001/01/29
+  - Snapshot-20010128 has been released. Resolved some minor patch conflicts.
+
+2001/01/11     == Released 0.6.33 ==
+
+2001/01/10
+  - Discussion in Thread "When to get peer certificate?" continues and it
+    comes out, that cross references between datastructures are well maintained
+    inside OpenSSL. A fact not well known due to lack of documentation
+    (seems I am facing some more work on the OpenSSL manpages :-).
+  - Moved around data needed for the certificate verification: a lot of
+    "static" entries globally needed inside pfixtls.c could now be moved
+    into the connection specific TLScontext.
+
+2001/01/07     == Released 0.6.32 ==
+
+2001/01/07
+  - Since now the checks at handshake stage (in pfixtls.c) are more strict,
+    some of the checks in smptd.c and smtp_proto.c could be removed.
+    At a later point I can probably move even more checks into pfixtls.c...
+
+2001/01/05
+  - Had a discussion with Ari Pirinen <aripirin@europe.com> on openssl-users
+    (Thread: When to get peer certificate?) about the earliest possible
+    place to check the CommonName of the peer against the expected name.
+    (This is what smtp does when enforcing the peername of the server it
+    is connecting to.)
+    The final result was, that the check can already been done inside the
+    verifiy_callback() routine even before the handshake is completed.
+    The positive side effect is, that since the session is never completly
+    established, it is also not cached on either client or server.
+  - Since this is a good idea, I have extended the verify_callback in
+    src/global/pfixtls.c to check the CommonName of the peer (if applicable)
+    and have the handshake shut down immediatly on failure. I have also
+    changed the behaviour so that whenever a positive certificate verification
+    is required, the handshake is shut down immediatly.
+    (The versions up to now did delay these checks until the session was
+    established and then shut down the connection. I had established this
+    practice while working on BIO-pairs and running into a bug in
+    OpenSSL 0.9.5 (fixed now) and with the verify depth.)
+
+2000/12/23     == Released 0.6.31 ==
+
+2000/12/23
+  - Bug: When only enabling smtpd_tls_wrappermode and not additionally setting
+    smtpd_use_tls or smtpd_enforce_tls, the TLS engine was not fired up on
+    startup of smtpd
+    Fixed: also start TLS engine when only smtpd_tls_wrappermode is enabled.
+    (Experienced by "Fiamingo, Frank" <FiamingF@strsoh.org>)
+
+2000/12/18     == Released 0.6.30 ==
+
+2000/12/18
+  - New snapshot 20001217 has been released. Due to the change of "timeout"
+    parameters now being its own class and table, the old patchkit does not
+    apply cleanly!
+  - Checked out Postfix/TLS parameters being timeout values and put them into
+    the new style time parameter table. This allows to specify time values
+    like 3600s or 1h. Updated sample configuration to reflect this new style.
+  - "Fiamingo, Frank" <FiamingF@strsoh.org> pointed out to me, that there are
+    three parameters in src/global/mail_params.h (namely DEF_TLS_RAND_EXCH_NAME,
+    DEF_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CA_FILE) that are hardcoded as
+    "/etc/postfix/something".
+    This does not match the usual style of postfix, where no paths are
+    hardcoded this way. I have removed the defaults for CERT_FILE and CA_FILE.
+    The RAND_EXCH is needed for good PRNG seeding on systems without
+    /dev/urandom, I however don't know yet, how to rearrange this requirement.
+    I could use the Postfix internal mechanisms to enforce a parameter, but
+    this would annoy people having compiled in TLS but not activated. 
+
+2000/12/13     == Released 0.6.29 ==
+
+2000/12/13
+  - Snapshot-20001212 has been released.
+  - Undid bugfixes for 20001210 which now are included in the new snapshot.
+
+2000/12/12     == Released 0.6.28 ==
+
+2000/12/12
+  - Added bugfix provided by Wietse on postfix-users@postfix.org for
+    "postconf -m" behaviour.
+
+2000/12/11
+  - New snapshot-20001210 released. Some patch conflicts occur. Additionally
+    * adjusted calls to myflock() to changed interface,
+    * fixed bug in smtpd_sasl_glue(), where a change to the name_mask()
+      call was not applied in the original snapshot.
+
+2000/12/05     == Released 0.6.27 ==
+
+2000/12/04
+  - Print informational message "SSL session removed" only when
+    var_smtp[d]_loglevel >= 2. (Proposed by Craig Sanders <cas@taz.net.au>.)
+  - Extend logging of "setting up TLS connection from/to" and corresponding
+    success/failure messages so that they include the hostname/ip address.
+    This way it is much easier to automatically analyze errors by simply
+    grepping for e.g. "SSL_accept error" and immediately get the peer
+    causing the problem without further logfile processing.
+    (Proposed by Craig Sanders <cas@taz.net.au>.)
+  - When experiencing a TLS failure due to TLS-enforced failure in client mode
+    (no certificate or hostname/certificate mismatch etc), immediately shut
+    down the TLS mode with "failure" indication, so that the SSL session is
+    removed immediately. This way a new session is always enforced in the
+    case the peer has fixed the problem; no need to wait for the timeout.
+
+2000/11/29     == Released 0.6.26 ==
+
+2000/11/29
+  - Found security relevant bug in the OpenSSL library: the verify_result
+    stating whether or not the certificate verification succeeded is not
+    stored in the session data to be cached and reused.
+  - This bug was found during the development of Postfix/TLS around one
+    year ago, the bug in the library was however only fixed for the server
+    side. At that time I also tested the server side behaviour but ommitted
+    to check the client side, too.
+  - Versions before Postfix/TLS 0.4.4 experienced this problem for both
+    server and client side. Before 0.6.0 a workaround was active for both
+    sides, which has been removed at 0.6.0 in the believe that the bug
+    was gone (I only tested the server side, which was fixed).
+  - Fixed that bug in OpenSSL also for the client side (I can do this myelf
+    now that I have been invited to join the OpenSSL developers team :-).
+    The fix is availabe as of today and will be part of the 0.9.7 release
+    of OpenSSL (or 0.9.6a, if this release will be published).
+  - Included a workaround inside Postfix/TLS for OpenSSL library versions
+    before 0.9.6a or 0.9.7, respectively.
+
+********************** Begin Description
+
+  - By not caching the verify_result for the client side, the following
+    behaviour could appear:
+  * The problem can only appear when smtp_tls_session_cache_database
+    is activated.
+  * smtp_use_tls = yes
+   X On the first connection, the certificate fails verification, failure
+     is logged:
+      smtp[*]: Unverified: subject_CN=serv01.aet.tu-cottbus.de, issuer_CN=BTU-CA
+     For any following connections until the session times out (default 1 hour),
+     the peer certificate seems to pass verification:
+      smtp[*]: Verified: subject_CN=serv01.aet.tu-cottbus.de, issuer_CN=BTU-CA
+   X Security Impact:
+     Unverified certificates are logged as if verification had succeeded.
+  * smtp_enforce_tls = yes
+   X After the verification failure, the session is never correctly established
+     and hence not reused.
+   X Security impact:
+     None, as the session is never reused.
+  * smtp_enforce_tls = yes after smtp_tls_enforce_tls = yes for a server.
+   X If the session has been recorded with use_tls and then for this server
+     enforce_tls is set, the wrong verify_result could be used within the
+     session cache timeout (default = 1 hour).
+   X Security impact:
+     If TLS shall be enforced for a recipient, there is a window of approx.
+     one hour from setting the "enforce_tls" switch until a verification
+     failure is noted. For this to happen, a TLS session to that server must
+     have been used with use_tls set and the not-verifiable certificate must
+     have been recorded in that session.
+  - Evaluation:
+    Even though this _is_ a security problem, I consider risk to be *low*,
+    given the conditions under which the problem might occur.
+
+********************** End Description
+
+2000/11/27     == Released 0.6.25 ==
+
+2000/11/26
+  - Added "permit_tls_all_clientcerts" for smtpd_recipient_restrictions.
+    When this option is enabled, any valid client certificate allows relaying.
+    This can be practical, if e.g. a company has a special CA to create
+    these certificates and only this CA is "trusted". It however does not
+    allow finer control, so if e.g. an employee leaves, he could still
+    relay. Postfix/TLS does not (yet) allow CRL (certificate revocation lists).
+    (Added on popular demand.)
+  - Make the client behaviour more configurabe: when enforcing TLS connections,
+    the peer's name is checked against the CommonName in its certificate.
+    New configuration variable "smtp_tls_enforce_peername" (default=yes)
+    can now be used to accept peername!=CommonName. The server's certificate
+    must still pass the verifcation process against a trusted CA!
+    In tls_per_site, the according key is MUST_NOPEERMATCH.
+    (Added on demand.)
+
+2000/11/24
+  - If the server requires a client certificate and no certificate is presented
+    or the certificate fails verification, the connection is shut down but
+    no information is logged.
+    -> add according msg_info() in smtpd/smtpd.c:startls_cmd().
+  - If TLS is not enforced, it does not make sense for a server to require a
+    client certificate. If no STARTTLS is issued, the SMTP would continue
+    anyway, so why shut down when TLS is activated without verifyable client
+    certificate?
+    -> ignore smtpd_tls_req_ccert=yes, if TLS is not enforced and only treat
+       like smtpd_tls_ask_ccert = yes with an according information logged.
+
+2000/11/22     == Released 0.6.24 ==
+
+2000/11/22
+  - Installed on my own servers and changed configuration to use the new
+    "permit_tls_clientcerts" option name. Patchkit will be released after
+    some hours of successfull operation.
+
+2000/11/21
+  - New snapshot-20001121 is being released. The patch applies without any
+    conflict when applied with "patch -p1", so no need to rush out an updated
+    patchkit.
+  - Rename the smtpd_recipient_restrictions option from "check_relay_ccerts"
+    to "permit_tls_clientcerts" to better match the naming scheme.
+    Leave in the old option for now to not break existing configurations.
+    The final incompatible removing is scheduled of release 0.7.0 of the
+    patchkit which will be matching the next "stable" release of postfix.
+  - There is no manual page for tlsmgr.8 (pointed out by Terje Elde
+    <terje@thinksec.com>).
+    Fix the comments at the beginning of tlsmgr.c and create tlsmgr.8.
+  - In the session cache code an additional 20 bytes were allocated when
+    converting SSL_SESSION data to binary using i2d_SSL_SESSION().
+    In adding these 20 bytes to the size listed by i2d_SSL_SESSION() I followed
+    the example in the OpenSSL source (PEM_ASN1_write()). These 20 bytes are
+    only added since when writing the PEM, a 20 byte checksum is added, so
+    we don't need it in our case -> removed.
+    (Researched after Carlos Vicente <cvicente@mat.upc.es> asked what these
+    20 bytes are good for :-)
+
+2000/10/30     == Re-Released 0.6.23 ==
+
+2000/10/30
+  - Postfix snapshot-20001030 with an important bug fix is made available.
+    The patchkit applies without any problem (patch -p1).
+    Hence, I re-release the 0.66.23 release for the new snapshot.
+
+2000/10/30     == Released 0.6.23 ==
+
+2000/10/30
+  - New Postfix snapshot 20001029 available with some important bug fix.
+    Adjusted patchkit (only minor conflicts).
+
+2000/10/27
+  - The CN_sanitize function (src/smtpd/smtpd.c) that shall make sure that
+    no illegal sign is included into the Received: header does not work
+    on systems were "char" is unsigned by default.
+    (Linux on s390, found by Carsten Hoeger <choeger@suse.de>)
+    -> Worked out a more precise (even though not looking elegant) solution
+    that checks out all acceptable characters.
+  - Sent new smptd.c to Carsten Hoeger for testing, will wait with new
+    Postfix/TLS release.
+
+2000/10/06     == Released 0.6.22 ==
+
+2000/10/06
+  - snapshot-20001005 has been released, featuring fast ETRN. Only some minor
+    patch conflicts needed to be resolved.
+
+2000/09/28     == Released 0.6.21 ==
+
+2000/09/28
+  - snapshot-20000924 seems to be somewhat longer lasting. I have been asked
+    for a new Postfix/TLS release against snapshot-20000924, hence I will
+    create one.
+  - Running OpenSSL 0.9.6 for a week now to my full satisfaction. I will bump
+    bump up the Postfix/TLS version counting to include "0.9.6", even though
+    it will still run fine with 0.9.5a.
+
+2000/09/25/
+  - snapshot-20000924 is available; only small adjustments.
+  - Wietse seems to release new snaphots on a daily basis, it doesn't make
+    sense to follow with a new Postfix/TLS release every day.
+
+2000/09/23     == Released 0.6.20 ==
+
+2000/09/23
+  - Recompile OpenSSL-0.9.6-beta3 with the change and reinstall old pfixtls.c:
+    works again. Hence, all versions of Postfix/TLS working against 0.9.5a
+    will also work again 0.9.6-final, which shall be released on 2000/09/24!
+  - Wietse releases snapshot-20000923, patchkit adapted.
+  - Went through the "install.html" document to add a remark about
+    OpenSSL-0.9.6. This document is of historic quality but did not fit
+    actual versions of Postfix/TLS, we are far beyond OpenSSL 0.9.2: Updated.
+
+2000/09/22
+  - Wietse releases snapshot-20000922. The source directory hierarchie has
+    changed, so the patch needs to be adjusted at several places.
+  - Run tests against OpenSSL 0.9.6-beta3: problems occur!
+    * Certificates are no longer verified, since an informationa flag about the
+      CA certificate search process is written into the error storage and
+      thus misinterpreted as verification failure.
+    * Changed Postfix/TLS source to maintain its own error storage based on
+      the verify_callback, send out according warning to Postfix/TLS mailing
+      list.
+    * Unfortunately, this will break all older versions of Postfix/TLS.
+      Sent out analysis to OpenSSL-bugs@openssl.org.
+    * Additional change is made to OpenSSL: the new behaviour is only activated
+      when a special flag is set, so compatibility is restored!
+
+2000/09/21
+  - Wietse releases snapshot-20000921. Some minor patch conflicts resolved.
+
+2000/09/14     == Released 0.6.19 ==
+
+2000/09/14
+  - Received a bug report: Postfix/TLS will accept a mail even though
+    smtpd_req_ccert=yes (require use of client certificate) and no
+    client certificate is presented.
+    Reason: when no client certificate is presented SSL_get_verify_result()
+    will return X509_V_OK, since this is the default value.
+    Solution: only set "peer_verified" internal information, if the
+    verify_result is X509_V_OK _and_ a peer certificate is available.
+    Remark: This default value does not make too much sense. I will file
+    a bug report/patch before the next release of OpenSSL...
+
+2000/09/03     == Released 0.6.18 ==
+
+2000/09/03
+  - When calling "sendmail -bs", smtpd is started without root privileges,
+    hence it cannot open the private key file and the session cache database.
+    Since the database routines do not offer a graceful return (only fatal
+    and abort), this leads to a failure when TLS and session caching is
+    activated.
+    This affects PINE users (noted by Craig Sanders <cas@taz.net.au>).
+    Solution: Try to read the private key first; if that fails, we can
+    gracefully recover and won't touch the session cache database at all.
+  - When STARTTLS is configured for smtpd but does not work (e.g. because of
+    unaccessible keys), smtpd answers with "465 TLS not available due to
+    temporary reasons". After that the connection was closed, this is however
+    not necessary, as the client may decide to continue without TLS activated.
+  - Craig Sanders <cas@taz.net.au> contributes a script to automatically
+    generate the keys and certificates for Postfix/TLS usage. Added
+    "make-postfix-cert.sh" to the contributed/ directory.
+
+2000/09/02     == Released 0.6.17 ==
+
+2000/09/02
+  - Craig Sanders <cas@taz.net.au> reports that he has connection problems
+    with a site; the message in the log is:
+    SSL_connect error 0
+    8847:error:140943F2:SSL routines:SSL3_READ_BYTES:sslv3 alert unexpected message:s3_pkt.c:956:SSL alert number 10:
+    * This is the error caused by the faulty TLS implementation with
+      CommunigatePro. The bug is fixed in later versions of CommunigatePro,
+      The site shall be contacted, they should update.
+  - More important, he reports a segmentation fault immediately after this
+    problem.
+  - Bug: when not using session caching and an error occurs during the TLS
+    handshake, pfixtls_start_clienttls() tried to remove the erronous
+    session from a non-existant session cache.
+    Fix: check the existence of the session cache before trying to access it.
+    Comment: at all other places in the code this condition was already
+             caught.
+  - Remark: actually session caching was configured, but the configuration
+    variable was mistyped because...
+       it was wrong in conf/sample-tls.cf and doc/conf.html.
+    The correct values are "smtp[d]_tls_session_cache_database" instead of
+    "smtp[d]_tls_use_session_cache_database".
+    Unfortunately this is not flagged by Postfix...
+
+2000/08/25     == Released 0.6.16 ==
+
+2000/08/25
+  - Make sure, that the smtp[d] processes will try to access the "daemon"
+    entropy sources, but will only print an info when not available. Using
+    the PRNG-exchange file, they can happily run without.
+  - Moved HAS_SSL checks, such that the package compiles also when configured
+    without -DHAS_SSL.
+
+2000/08/24
+  - Changed the handling of the PRNG-exchange file. Until now it was written
+    by tlsmgr and read by the smtp[d] daemons. This had the disadvantage, that
+    until tlsmgr rewrote new bytes to the file, all starting daemons read the
+    same seed (to which some more bits, but not too much were added).
+  - Now the file is handled in read->stir into pool->write back mode, so that
+    every daemon will add its own entropy bits.
+  - The smtp[d] processes will do so when starting, when opening a TLS
+    connection and when closing.
+  - The tlsmgr will also read back the file and add it to its pool, so that
+    no entropy is lost.
+  - This change significantly increases the "self seeding" capability of
+    the TLS service.
+
+2000/08/09
+  - Cleaned up the new PRNG-seeding.
+  - When tlsmgr looses connection to an EGD-source (because it was restarted),
+    tlsmgr performes an exit(0), so that a newly started tlsmgr can reconnect.
+    [chroot/dropped privileges].
+
+2000/08/04
+  - Introduced new entropy sources for single daemons:
+    * tls_daemon_random_source
+    Using this source (same style as for tlsmgr), each starting daemon can
+    obtain additional entropy (32 bytes by default). The PRNG-exchange file
+    is still read.
+  - I am not sure about the policy for this feature. If such a source is
+    given, should a failure be considered fatal?
+
+2000/07/23
+  - Started reworking the PRNG seeding:
+    * tlsmgr now recognizes tls_random_source as
+      dev:/dev/urandom         /* Direct read from device file */
+      egd:/path/to/socket       /* Connection via EGD-socket */
+      /path/of/plain-file
+    * If a dev: or egd: is given, tlsmgr will connect and keep the connection
+      open, so that it now can run in chroot-mode with dropped privileges.
+  - Since EGD can be drained, but the connection is permanently open, only
+    suck a small number of bytes (default 32) at a time, but do it more
+    often.
+
+2000/08/09     == Released 0.6.15 ==
+
+2000/08/09
+  - Traced through OpenSSL to learn more about the verify_callback-feature.
+    The callback is called several times. When it returns "1", the handshake
+    will continue, when it calls "0", the handshake will immediately fail
+    (and Postfix/TLS will also close the TCP connection).
+  - Following the sample in the OpenSSL-apps, the verification chain depth
+    was the only property triggering this effect, so this stood hidden until
+    now. Obviously, users having longer chains did set the verifcation
+    depth accordingly or they gave up, since this was never reported...
+  - Changed the behaviour of verify_callback() to never return "0", such that
+    we can deal with the verification result later in a more consistent manner.
+    If we only enable and not enforce, we simply want to ignore problems with
+    the certificate.
+  - verify_callback() did not print out all information, since the wrong
+    state variables (pfixtls_*active instead of pfixtls_*engine) were
+    checked. The *active state variables are only set later.
+    As the verify process now became rather narrative, the normal logging
+    is only done in loglevel 2!
+  - Arrrghhh. The conf/sample-tls.cf _and_ the html-docu (which is actually
+    copied from conf/sample-tls.cf) has wrong names for the verification-
+    depth parameters. *_vd instead of *_verifydepth and ccert<->scert.
+    [Wondering, why this never popped up before...]
+  - Changed the default-verifydepth to "5" which should suffice for most
+    cases. Maybe the limit could also be completely removed, but we should
+    at least receive a warning hint when something goes wild.
+    Since OpenSSL>=0.9.5 is required for Postfix/TLS anyway, certificate chain
+    verification can now be used, so the caution applied before is no longer
+    necessary.
+
+2000/08/08
+  - Tracked down the double-free() call in smtp with Efence. SSL_free()
+    does call SSL_SESSION_free() on the negotiated session. Hence, I must
+    not call SSL_SESSION_free() on the session in question, it will be
+    removed anyway.
+  - Also tracked down the certificate chain feature. Reason is the
+    verify_callback() in global/pfixtls.c. It flags a chain depth that
+    is too long as fatal, hence the connection is immediately closed.
+
+2000/08/04
+  - Received information from Alain Thivillon <Alain.Thivillon@hsc.fr>:
+    FreeBSD-CURRENT offers malloc() with additional checks enabled.
+    After successfully delivering, smtp dumps core with free() called
+    twice in TLS mode.
+  - I noted, that there is a communication problem with his site an my new
+    certificate issued by the universities computer center (which has a chain
+    depth of 2). Step back to the old self certificate for the time being.
+
+2000/07/27     == Released 0.6.14 ==
+
+2000/07/27
+  - Introduced new configuration parameter "smtpd_tls_wrappermode" that
+    enables the (deprecated) old style SSL-wrapping around SMTP. It could
+    be run on a different port (once smtps=465) was recommended for this
+    services.
+    This method is used by old versions of Outlook (Express), the Mac versions
+    and even actual versions, when not run on port 25.
+    [Actually it was only a handful of lines, so it doesn't hurt too much,
+    even though it does not follow any RFC.]
+  - I recommend using this option only from master.cf. Example lines added
+    to conf/master.cf and description added to Postfix/TLS-doc/conf.html.
+  - When having SASL enabled and TLS-enforce mode in "smtpd", only offer
+    AUTH, when TLS has been activated. Otherwise the client might simply
+    send the unencrypted credentials before it receives
+      530 Must issue a STARTTLS command first
+    and an eavesdropper already has what he was looking for.
+
+2000/07/19     == Released 0.6.13 ==
+
+2000/07/19
+  - Changed the library-initializaton call to new naming scheme
+    (SSLeay_add_ssl_algorithms() to OpenSSL_add_ssl_algorithms() :-).
+  - Updated documentation to reflect the use of chain certificates with
+    CAfile and smtp[d]_tls_cert_file (see 2000/07/06).
+  - Documentation: the interoperability problem with CommunigatePro has been
+    solved: CommunigatePro violated the TLS-RFC and has been fixed.
+  - Typo: It is "to stir" not "to stirl" :-)
+
+2000/07/06
+  - Received certificate for our site from our computer center. It's a chain
+    certificate. Now load the cert with SSL_CTX_use_certificate_chain_file(),
+    in order to better load the chain CA certificates.
+
+2000/07/04
+  - Reported Wietse about a possible problem in the SASL code, a relay check
+    may also be performed if sasl was not enabled and might lead to unwanted
+    relay.
+    As the fix is in my own codebase, I will leave it Postfix/TLS until a
+    new snapshot (or final release) is available.
+
+2000/06/02     == Released 0.6.12 ==
+
+2000/06/02
+  - Adapted to Snapshot-20000531 (minor patch conflict).
+  - Cleaned up some old header file dependencies in global/pfixtls.c and
+    global/Makefile.in that are no longer needed due to the interface changes
+    (timed_read()/write()) in 0.6.7.
+
+2000/05/29     == Released 0.6.11 ==
+
+2000/05/29
+  - Following Bodo Moeller's analysis, the error is due to a mismatch between
+    the CA certificate accessible in the smtp[d]_tls_CAfile and the one used
+    in the actual certificate (smtp[d]_tls_cert_file).
+    Daniel Miller fixed his setup and the problem is gone.
+  - Introduced a workaround into Postfix/TLS: if the padding error is found,
+    it is removed from the error-queue by Postfix/TLS, in order to protect
+    more sites from experiencing this problem.
+  - Added a warning to conf/sample-tls.cf
+  - Updated to the latest snapshot-20000528.
+
+2000/05/27
+  - After some fiddling around working through the binary certificate data to
+    see where it is modified at 0.6.10, I actually note, that both 0.6.9 and
+    0.6.10 choke on the data. Now going back up through the functions very
+    fast reveals the problem:
+    * The certificate supplied triggers the "RSA-padding" error in any case.
+      Since the certificate authencity is not enforced on OpenSSL-library level
+      but inside postfix later, the error is not enforced.
+      The error messages generated stay however in the error queue.
+      - For blocking sockets, the SSL_accept()/connect() calls return
+       "success", so the error-queue is never checked.
+      - With BIO-pairs, the error queue is checked to find out, whether the
+       function has just to be called again to continue the handshake, so
+       the error messages are found and the connection is shut down due to
+       the error condition.
+  - Submitted bug report to Bodo Moeller. Bug fix is checked into the OpenSSL
+    CVS archive: if the error is ignored during the handshake, clear the
+    error-queue.
+    * The next release of OpenSSL will behave consistently.
+  - This leaves open the question, why the RSA-padding error is issued in the
+    first place. Sent a query to the OpenSSL-* mailing lists.
+
+2000/05/26
+  - A second site experiencing this problem pops up.
+    -> Issued a warning to the postfix_tls mailing list.
+
+2000/05/24
+  - Contacted Damien Miller <djm@mindrot.org>. He did not change his TLS setup
+    in the last time. He is running Postfix/TLS-0.6.6.
+  - Contacted Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>, the author
+    of the BIO-pair part of OpenSSL for some debugging hints. Received several
+    worthful remarks on what to look for.
+  - Checked byte-for-byte the data fed into the OpenSSL-library. It does not
+    differ between 0.6.9 and 0.6.10, so my handling seems to be actually
+    correct.
+
+2000/05/23
+  - A communication error occurs when talking to mail.mindrot.org:
+    SSL_accept error -1
+    10264:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:100:
+    10264:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:396:
+    10264:error:0D079006:asn1 encoding routines:ASN1_verify:bad get asn1 object call:a_verify.c:109:
+  - The error occurs both in client and server mode. 0.6.9 does not show
+    this problem.
+  - Tried to connect with several other sites, all connections are fine,
+    this includes sendmail and qmail peers; hence decided to not recall 0.6.10.
+
+2000/05/23     == Released 0.6.10 ==
+
+2000/05/23
+  - Sent a note to openssl-dev@openssl.org about the behaviour of SSL_free()
+    and BIO_free(), hoping for some clarification whether my way of doing
+    it is the recommended way.
+  - Run the software in production mode on my own servers...
+  - Finished writing the in-source documentation.
+  - Updated sample-tls.cf and sample-smtp[d].cf to reflect the new timeout
+    parameters.
+
+2000/05/21
+  - Removed error messages produced by the now non-blocking behaviour of the
+    TLS layer [apps_ssl_info_callback()].
+
+2000/05/20
+  - Took results home and tried to run it on my Linux-box: SEGV after
+    successfully handling the SMTP session!!
+    * It seems that the SSL_free() and BIO_free() functions interact.
+      SSL_free() releases the underlying BIO and it will bomb out when
+      it is then explicitely BIO_free()'ed again and vice versa.
+    * It did not bomb out on HP-UX, but such things happen. I however want to
+      know, why the example program does not fail...
+    * With respect to the bevaviour as is, SSL_free(TLScontext->con);
+      BIO_free(TLScontext->network_bio) and not touching
+      TLScontext->internal_bio works.
+  - Introduced special timeout values for the TLS negotiation stage, as the
+    timeout values may change with protocol state (suggested by Wietse).
+  - Started writing a full description of the BIO-pair concept and its
+    special treatment into the pfixtls.c sourcecode.
+
+2000/05/19
+  - Systematicly implemented a generalized layer handling:
+    * do_tls_operation() is the generic handler for all SSL_*() input/output
+      functions. It deals with the non-blocking behaviour of this functions,
+      requiring appropriate retrys.
+    * network_biopair_interop() handles the interaction between the socket/fd
+      and the buffering BIO-pair.
+
+2000/05/18
+  - Based on the example in openssl-0.9.5a/ssl/ssltest.c realized the first
+    usage of BIO-pairs. (Can do server handshaking.)
+  - Learned, that the BIO-pair has its own buffering that needs its own
+    flushing. It is not enough to relay on the SSL_ERROR_WANT_READ/WRITE
+    state information.
+
+2000/05/17     == Released 0.6.9 ==
+  - Important: the seperator in the relay-fingerprints is now ':'!!!
+    Don't forget to change your relay_clientcerts databases.
+
+2000/05/16
+  - Changed pfixtls.c to only use the interface described in util/vstream.c
+    for handling the VSTREAM.
+    * Added vstream_context() macro to the VSTREAM-interface.
+  - Introduce TLScontext to identify the connection instead of the file
+    descriptor. Move all static data (SSL structure and information gathered
+    about the connection) into the context.
+    The TLScontext is allocated on TLS-start for a connection and saved with
+    the VSTREAM, so several streams can be used at the same time.
+  - Removed "pfixtls_setfd()" as it is no longer needed.
+  - Changed the relay_clientcerts list from string_list_* to maps_* interface
+    to allow usage of ":" in the list.
+    THIS IS AN INCOMPATIBLE CHANGE!!!!
+  - Updated documentation accordingly.
+
+2000/05/12     == Re-released 0.6.8 ==
+
+2000/05/12
+  - Wietse announces snapshot-20000511 with an important bugfix.
+  - Since upgrading from 20000507 to 20000511 is highly recommended,
+    Postfix/TLS 0.6.8 is re-released for this snapshot (the patch applied
+    cleanly, just the name of the toplevel directory has changed).
+
+2000/05/11     == Released 0.6.8 ==
+
+2000/05/11
+  - Unlike expected I found some time to install the latest cyrus-sasl-1.5.21
+    and test some parts the integration. It does, well, work as advertised
+    (and the advertisement in SASL_README is not too optimistic).
+  - When checking all of the rejected patch-snippets for 0.6.6->0.6.7
+    I missed the parameter "smtpd_enforce_tls" (noted since I wanted to
+    enforce TLS encryption while playing around with plaintext passwords)
+    in the static CONFIG_BOOL_TABLE bool_table[] = {..} in smtpd/smtpd.c
+    -> I will immediately release a corrected version 0.6.8.
+
+2000/05/11     == Released 0.6.7 ==
+
+2000/05/11
+  - The latest sendmail.8.11.0.Beta1 includes STARTTLS support; it is available
+    in source code and also uses OpenSSL.
+
+2000/05/10
+  - After having it running at home (Linux) I also install it at work for
+    the field test.
+  - No time to install the SASL kit, so this part stays untested as of now.
+
+2000/05/09
+  - Downloaded snaphot and apply the patchkit.
+  - Straightened out the rejected parts of the patch.
+  - Due to the new layering with timed_read() and timed_write() functions
+    the integration of the TLS layer needed special adjustment.
+    * When TLS is active, the timed_read() and timed_write() functions are
+      replaced by the corresponding pfixtls_timed_read() and
+      pfixtls_timed_write() functions. When the TLS functionality is stopped,
+      the old functions are restored.
+    * The names of the pfixtls_timed_*() functions are looking into the future,
+      because they are working as before, the timeout functionality is not
+      in, yet.
+
+2000/05/08
+  - Wietse announces snapshot-20000507 with a lot of changes. Especially
+    important: the I/O handling of the smtp-stream has been changed to
+    a more layered technique that allows easier integration of the TLS layer.
+
+2000/04/27     == Released 0.6.6 ==
+
+2000/04/27
+  - Fixed inconsistency between documentation and actual behaviour: peer
+    certificate information was not logged at level 1 (found by
+    Damien Miller <djm@mindrot.org>).
+    * While at it: the logged information did not say whether the certificate
+      data logged passed verification or not: fixed. (The information logged
+      in the Received: header already contained that information.)
+  - Backported dict_dbm.c from snapshot-20000309 with the updated
+    dict_delete() behaviour (key not found is not considered fatal).
+    Maintained dict_sdbm.c accordingly.
+
+2000/04/18     == Released 0.6.5 ==
+  - Important:
+    * New session cache mechanism SDBM. Please adapt your main.cf and delete
+      any old ".db" session cache files manually.
+
+2000/04/18
+  - I am using the SDBM session cache for a week right now and did not have
+    any trouble, so I think its worth pushing it out.
+  - I am not completely happy with the dict_del() behaviour of considering
+    a not-found key fatal. It might happen when the smtp[d] processes would
+    be allowed to delete themselves. They are not as of now, so I accept it
+    for now but will reconsider it.
+  - Updated documentation accordingly.
+
+2000/04/17
+  - Received corrections for the HTML-docs from Ralf Hildebrandt
+    <R.Hildebrandt@tu-bs.de>.
+
+2000/04/11
+  - Transfered SDBM from home (Linux-testbed :-) to work [found and fixed some
+    small items when compiling on HP-UX]. Started running it under
+    "real life" conditions.
+
+2000/04/07
+  - Implemented "SDBM" Simple Database Management routines as also utilized in
+    ModSSL. Of course, it requires reopening of the databases, so the
+    routines are changed, that the _file_descriptors_ are left open, but
+    the _in_memory_ database stuff (especially the cached data) is closed
+    and reopened on access. This is what is really needed. The pagesize
+    is increased from standard DBM compatibility to hold the session
+    information.
+    Additionally, this software is in the public domain, so no additional
+    license problems arise.
+  - The access goes through the dict_* interface, hence the locking is
+    performed by myflock().
+
+2000/04/01     == Released 0.6.4 ==
+
+2000/04/01
+  - Updated to the new patchlevel of Postfix (19991231-pl06), some parts of
+    the patch were rejected due to changes in smtpd.
+  - Changed patch name with respect of today's release of OpenSSL-0.9.5a.
+    The code remained unchanged.
+    
+2000/03/25-31
+  - The cached informations are not deleted by "tlsmgr" even though stored
+    and retrieved by the smtp[d] processess. Strange.
+  - Spend some large amount of time digging through the Berkeley DB
+    documentation and code.
+    * It claims that Berkeley DB is multi-process capable. Caveat: it takes
+      the very complicated "transaction model", that I did not use until now.
+      Hence the session cache does not work as is.
+    * Even with transaction model, Berkeley DB requires re-opening of the
+      databases to get rid of cached information. F*ck.
+  - Finally, I give up on Berkeley DB for session caching. It will never
+    work for us. Even if it would, it requires a large amount of helper files
+    and it seems, that the transaction environment is somewhat fragile when it
+    comes to some problem. I won't rely on it.
+
+2000/03/28     == Released 0.6.3 ==
+
+2000/03/28
+  - As has been pointed out to me, the TLS information in the Received:
+    header is not conform to RFC822.
+  - The TLS protocol and peer CN information is now included in '()', so
+    that it is a comment.
+
+2000/03/21     == Released 0.6.2 ==
+
+2000/03/21
+  - I have been running DB based session caching with the changes for some
+    more time now without problems. Am I really confident? No, not really.
+    I remember the trouble I had with Berkeley DB and sendmail on HP-UX.
+    I don't think I really trust it.
+  - Realized single "smtp_tls_per_site" lookup. I cannot use the more or
+    less comfortable "domain_list" lookups as before, since these do not
+    return the value, just found or not :-(.
+    Hence the lookup is realized with maps and exact lookup. I never tried
+    regexp. But if I understand the docs correctly, it should be possible to
+    use it here to realize wildcard lookups, if it would not have been
+    disabled :-(.
+  - Summary:
+    * Session Cache will be cleaned at "postfix reload" or "postfix start"
+    * New table "smtp_tls_per_site"
+    * Gone: "smtp_tls_[use/enforce]_[recipients/sites]"
+
+
+2000/03/16
+  - Changed pfixtls.c, so that it will only open Session Cache databases,
+    that are already available. tlsmgr is responsible for creation.
+  - Change tlsmgr.c, such that session cache databases will be removed before
+    opening, so that fresh databases are used whenever postfix is restarted.
+    This means, that session information is not kept over a postfix stop/start
+    or reload sequence, but it also means, that issuing a postfix reload will
+    clean the session cache.
+    I don't use simple dict_open with O_TRUNC, because this would not help
+    against database files, that are locked by hanging smtp[d] processes.
+    If you think it will also solve the "hang" problem described for
+    2000/03/15: in a certain sense it can, since tlsmgr will be killed by
+    the watchdog and new, fresh cache files are installed, but that is not
+    more than an ugly hack. It must be solved in a clean manner.
+
+2000/03/15
+  - Experienced some strange problem with Berkeley DB based session cache.
+    The DB routines hang while trying to delete an entry. I did save the
+    corresponding "hash:" file and could reproduce it (and walk through
+    the endless loop with a debugger), but I didn't find the reason why.
+    Since during "db->del" the database is exclusively locked all other
+    processes hang however, so this is really bad!!!!!!!!
+
+2000/03/12     == Released 0.6.1 ==
+
+2000/03/12
+  - Created tls_info_t structure to hold all information about the active
+    TLS connection. Remove all global variables except those for the
+    running client/server engines (those might be replaced with global
+    variables in smtpd/smtp, though).
+  - Added field "dNSName" to the structure (still unused). This will be
+    used with X503v3 extensions.
+  - Cleaned up TODO, since some items are now done...
+
+2000/03/11
+  - Added missing #include <sys/time.h> to tlsmgr.c. (Worked without on HP-UX,
+    showed up on Linux.)
+  - Bug: removal of server side sessions from the cache in case of trouble
+    failed, because uppercase hex was used instead of lowercase for the key.
+    This does not affect removal of expired sessions by tlsmgr.
+  - Stepped up to postfix-19991231-pl05.
+
+2000/03/09     == Released 0.6.0 ==
+  - Important:
+    * This release features an additional daemon, the "tlsmgr", please update
+      your master.cf accordingly.
+    * This release does not use the /var/spool/postfix/TLS* directories
+      anymore. Remove them and re-install the original postfix-script.
+    * Check the new/changed configuration parameters tls_random* and
+      smtp[d]_tls_session_cache*.
+    * This release will only work with OpenSSL >= 0.9.5!!!!!
+
+2000/03/09
+  - Testcompilation of Postfix/TLS without -DSSL and the OpenSSL includes and
+    libraries passed.
+  - Worked through tlsmgr.c to remove unneeded header files.
+  - Wrote documentation for tlsmgr.c.
+  - Updated documentation on top of pfixtls.c.
+  - Put (char *) casts into the myfree() calls, where necessary, to make the
+    HP compiler happy.
+  - Updated html PRNG documentation in Postfix/TLS.
+
+2000/03/08
+  - Finished first version of "tlsmgr". Does run through session cache
+    databases and detects and deletes (*) old sessions.
+  * Had to realize SYNC_UPDATES for the dict_db_delete() function and patch
+    the flag handling within the function. Changes sent to Wietse.
+  - Restored qmgr to its original state.
+  - Extended pfixtls.c to need an additional "needs_095_or_later()" function
+    when compiled with an older version of postfix.
+  - The session cache is now enabled, when a database filename is given.
+    smtp[d]_tls_use_session_cache configuration parameters removed,
+    updated documenation accordingly.
+  - Moved the PRNG handling to tlsmgr, applying the new model. tlsmgr will
+    query external sources at startup and will then feed a PRNG exchange
+    file with random data in intervals of configurable (but random driven)
+    length.
+    If running outside chroot, tlsmgr can query the entropy source (e.g.
+    EGD or /dev/urandom) again and so increase entropy with time. If the
+    entropy sources don't limit access, the tlsmgr can run with "postfix"
+    privileges. Mine does.
+    -> master.cf became a new entry.
+  - tlsmgr is realized as a trigger server and has the "fifo" entry. Actually,
+    it does not take any input. One could utilize it to feed back some entropy
+    from running smtp[d] processes, but I think this would overload the
+    issue.
+  - I will release a 0.6.0 pre-version as is. tlsmgr still lacks the detailed
+    information in the header and the interface description in pfixtls.c
+    probably is also not longer up do date.
+
+2000/03/07
+  - Since defective session data can cause SEGFAULTs, it is now armored
+    by a leading structure that does contain a session cache version and
+    the postfix library version before the timestamp. If a session does
+    not match exactly the version numbers, it is immediately discarded
+    and deleted to avoid harm.
+  - Removed the seperate storage of the peer's certificate verify_result,
+    so starting from this moment, Postfix/TLS will only work safely with
+    OpenSSL >= 0.9.5!!!
+  - Ported server side session cache routines to the client side; works.
+  - Analyzed structure of "qmgr" to understand consequences for the planned
+    "tlsmgr" daemon. Transferred the sceleton.
+  - Received word from sendmail, a (at least preliminary) TLS enabled test
+    address is "bounce@esmtp.org".
+
+2000/03/06
+  - Wietse supplied a change to the dict/dict_db mechanism to allow for
+    synchronous updates.
+    Session cache updates for the server side seem to work now, removal of
+    old sessions (when called from the client) integrated.
+
+2000/03/05
+  - Got the database style session cache to run for the server side (at least
+    partial). The removal of old sessions is not yet realized.
+    [There are several man pages for OpenSSL as of 0.9.5, but the i2d etc
+    interfaces are not belong them, so I had to study the source code instead.]
+  * What is not working by now is the synchronization of the memory database
+    to disk. It only is synchronized automatically upon close. It would be
+    necessary to sync after each update or delete, but this is not implemented
+    in Wietse's dict library. I will post an according proposal.
+
+2000/03/04
+  - Wietse posts a patch to select "EHLO" negotiation even if ESMTP is
+    not recognized from the 220 greeting. Activating this flag will however
+    break compatibility with mailers, that simply close the connection
+    upon EHLO. I don't know how the large the number of these broken mailers
+    is, but activating "smtp_always_send_ehlo" is a tradeoff.
+  - Integrated Wietse's patch into Postfix/TLS.
+
+2000/03/03
+  - Received update from Matti Aarnio (Zmailer) is now for some time able
+    to do server _and_ client side TLS. Updated documenation accordingly.
+    When testing, Postfix client to Zmailer server failed, because
+    Zmailer announces with "ESMTP+IDENT" and Postfix does not recognize
+    the ESMTP token (must be seperate), so only HELO is used and STARTTLS
+    is not offered by the Zmailer server. Informed Matti accordingly,
+    will wait until the problem is resolved before actually publishing
+    the update.
+  - Enhanced the documentation by listing automatic reply services at which
+    interoperability can be tested.
+
+2000/03/02
+  - Went through the Postfix source to check out the database routines.
+    It should be possible to move session caching from directory/file-
+    based to database. Since DBM only allows blocks (key+contents) of
+    1024 bytes and a session is larger, only Berkeley DB can be used.
+    Put some first bits into Postfix/TLS.
+
+2000/02/29     == Released 0.5.5 ==
+
+2000/02/29
+  - OpenSSL 0.9.5 has been released. Since I want to promote 0.9.5, as it
+    contains several bugfixes and enhancements, I release a new version
+    of Postfix/TLS. My personal highlights:
+    * The bug with Win32 Netscape not commencing after certificate storage
+      unlocking should be fixed. (I will leave the not in however, as long
+      as I have not positively checked it myself. Reproducibility...)
+    * The bug, that the certificate verifiation result is not stored in the
+      session cache (discovered for Postfix/TLS 0.4.4) is fixed. I will leave
+      the Postfix/TLS workaround in as long as it will run with older versions
+      of OpenSSL.
+    * The OpenSSL commandline tools like "openssl gendh" now support EGD, so
+      that the examples for generating the DH parameters now will really work
+      with high quality random data :-)
+    * The support of 56bit ciphers has lost its importance since 128bit
+      versions of Netscape etc are now easily available...
+  - This version does not feature source code changes but updated documenation
+    when compared with 0.5.4:
+    * List examples on how to generate good entropy for the PRNG seed in
+      /etc/postfix/random_file.
+  - Update the TODO document with respect to the discussion about session
+    caching and other security items. This document is a very short summary,
+    for the full discussion check the mail archive at
+      http://www.aet.tu-cottbus.de/mailman/listinfo/postfix_tls/
+
+2000/02/26-28
+  - Wietse considers including Postfix/TLS into the main release. A discussion
+    about security relevant features, especially the session cache inside
+    the chroot jail takes place.
+    The discussion will definetely lead to some changes; I have however not
+    decided on the first step, yet :-)
+
+2000/02/21     == RELEASED 0.5.4 ==
+  - Important: Another directoy is created in /var/spool/postfix, so don't
+    forget to install the new versions of conf/postfix-script-*sgid.
+
+2000/02/21
+  - Finished the seed-exchange architecture by saving the random seed at exit
+    of smtp and smtpd.
+  - Wrote documentation for the PRNG handling to the documentation.
+  - Tested on HP-UX (with a current OpenSSL-pre-0.9.5 snapshot and 0.9.4)
+    and on SuSE-Linux (with 0.9.4).
+  * THIS VERSION WILL STILL RUN WITH OPENSSL-0.9.4, but it will also run
+    with OpenSSL-0.9.5. Older versions of Postfix/TLS will not, because the
+    PRNG is not seeded!
+
+2000/02/19
+  - Start to implement my own model of collecting entropy. All smtp and smtpd
+    processes will record some items (mainly the time of actions) to add
+    some entropy into the PRNG. The state is saved and used to re-seed by the
+    smtp and smtpd processes, so that entropy adds up into the pool.
+    The seeding by external file is additionally kept in order to be able
+    to inject additional entropy.
+
+2000/02/18
+  - Included routines to add random seed from a configurable file
+    "rand_file_name". I don't want to retrieve the entropy from a real
+    random system source, because the amount of entropy that can be collected
+    is limited. We might hence stall. Let's think about this problem.
+  - The SSL_CTX_load_verify_locations() has been fixed in the latest
+    OpenSSL snapshot.
+
+2000/02/17
+  - Tracked down the SSL_CTX_load_verify_locations() problem in the OpenSSL
+    library. If more than one CA-certificate is loaded, a bogus return value 0
+    is created, because the count of certs is checked to be "1" instead of
+    allowing ">=1". Reported to openssl-dev.
+
+2000/02/16
+  - Downloaded the latest openssl-SNAPSHOT-20000215 and installed it on
+    my development machine, then recompiled Postfix/TLS and try to run it.
+    * Failure: SSL_CTX_load_verify_locations() fails on reading the CAfile with
+      return value 0, but no actual error is displayed.
+      If the return value is not checked, the CA-certificates work, so that
+      they are loaded and the error indicator seems to be bogus.
+      Reported to openssl-dev mailing list.
+    * Failure: OpenSSL has become picky about correct seeding of the PRNG
+      Pseudo Random Number Generator. Installed some "testseed" that is
+      actually not random, but then Postfix/TLS starts to work again. We
+      will need some good random seed setup, probably reading from either
+      /dev/random (if available) or from EGD.
+      Found out during the experiments, that EGD is not that simple to use
+      as described in some of my Postfix/TLS docs. Must be upgraded.
+      Asked in the openssl-dev mailing list about the recommended amount
+      of random data needed for seeding the PRNG. Ulf Moeller recommends
+      a minimum of 128bit.
+
+2000/02/14     == Released 0.5.3 ==
+
+2000/02/14
+  - OpenSSL 0.9.5 is to be released within the next hours/days. Since I intend
+    to use some of its new features soon, I will re-release 0.5.2 as the last
+    version that will run with 0.9.4 but for the latest postfix patchlevel.
+  - No functional changes.
+  - Updated patch for postfix-19991231-pl04.
+
+2000/01/28     == Released 0.5.2 ==
+
+2000/01/28
+  - Stepped up the next postfix patchlevel postfix-19991231-pl03.
+    No functional changes.
+
+2000/01/03     == Released 0.5.1 ==
+
+2000/01/03
+  - Bug fixed: Don't specify a default value for "smtpd_tls_dcert_file",
+    assuming that typically a DSA certificate is not used.
+    Otherwise smtpd will try to read it on startup and the TLS engine won't
+    start since it is not found.
+    I didn't note this bug before today, because I could not install this
+    release in a larger scale on my own servers due to a network failure
+    of our campus backbone lastring from Dec 31 until today.
+  - Stepped up to the just released postfix-19991231-pl01.
+
+2000/01/01     == Released 0.5.0 ==
+
+2000/01/01
+  - Upgraded to the new postfix release 19991231.
+
+1999/12/30
+  - Enabled support for DSA certificate and key for the server side. One
+    can have both at the same time, the selected cipher decides which one
+    is used. OpenSSL clients (like Postfix/TLS) will prefer the RSA cipher
+    suites, if not especially changed in the cipher selection list.
+    Netscape will only use the RSA cert.
+  - The client side can only have one certificate. There is a way out by using
+    a callback function, that will receive the list of acceptable CAs and
+    then do some clever selection: SSL_CTX_set_client_cert_cb().
+    I will however have to figure out, how it has to be prepared, it seems,
+    that there is no example available.
+  - I have been able to successfully generate a DSA CA and certificates for
+    some Postfix hosts and to do authentication and relaying as expected.
+    So now I have to document how it is done in a practical manner...
+  - Moved up prerelease 0.5.0pre02 to the download site.
+
+1999/12/28
+  - Moved up to SNAPSHOT-19991227.
+  - Don't forget to check the return value when calling
+    SSL_CTX_set_cipherlist().
+  - Add code to load DH-parameters from disk.
+  - Add configuration information for the new functionality: DH paramter
+    support, possibility to influence the cipherlist.
+  - Moved up prerelease 0.5.0pre01 to the download site.
+
+1999/12/25
+  - Found some minutes to relax from the christmas business.
+  - Applied the 0.4.7 patch to SNAPSHOT-19991223 and included the new changes
+    of 1999/12/19.
+    Once the new stable release of postfix is out, this minimum state will be
+    the new Postfix/TLS patch: the new functionality will not influence
+    stability, so it can stay in even if still unfinished.
+
+1999/12/23
+  - Wietse announces SNAPSHOT-19991223: if no severe bugs are found, it will
+    be promoted as next stable release soon. Good to have kept everything
+    from yesterday.
+
+1999/12/22
+  - Got a query from a Postfix/TLS user: the patch does not apply cleanly to
+    SNAPSHOT-19991216 and he somehow messed up to integrate the rejected
+    parts (it later turned out he just forgot on reject).
+    Applied the patch myself and generated a diff, sent it to the user
+    and of course kept a copy for myself, since I will have to apply it
+    myself eventually once the next "stable" release of postfix is out.
+
+1999/12/19
+  - Began modifications for 0.5.x:
+    * Added configuration variables for specifying the cipherlist to be used
+      smtpd_tls_cipherlist and smtp_tls_cipherlist. For the format, there
+      is some (however sparse) documentation in the openssl package.
+    * Call SSL_CTX_set_cipherlist() with these data.
+    * Added default temporary DH parameters to pfixtls.c (only server side is
+      necessary) and configuration variables to specify user generated
+      parameters; they are however not used, yet.
+      The default parameters were generated using the presumably good
+      /dev/random source.
+
+1999/12/13     == Released 0.4.7 ==
+
+1999/12/13
+  - Addendum to the last change: do also remove sessions, that could _not_
+    be reused.
+  - Updated configuration information:
+    * As of OpenSSL 0.9.4, certificate chain verification is not sufficient,
+      since the certificate purpose is not checked, so I recommend to add
+      all intermediate CAs the the list of CAs and stay with a verification
+      depth of 1.
+      Work is in progress for 0.9.5.
+  - Stepped up to the just released new patchlevel postfix-19990906-pl09.
+
+1999/12/10     == Released 0.4.6 ==
+
+1999/12/10
+  - Realized changes implied below: Removed SSL_CTX_add_session() in the
+    client startup; remove session on stop with SSL_SESSION_free().
+  - In the morning there is a mail on the list, that Postfix might be
+    crashed with a single "\" on the "CC:" line. Hence, we should expect
+    a new patchlevel soon. Release the actual change anyway.
+
+1999/12/09
+  - Read in the "openssl-users" mailing list, that SSL_CTX_add_session()
+    is only intended for servers. On the client side, SSL_set_session()
+    is sufficient.
+    Additionally, the session should be explicitely freed, since
+    SSL_set_session() will increment the usage count for the session.
+    Explained by Bodo Moeller.
+
+1999/12/xx
+  - Had a discussion (by email) with Bodo Moeller about DH/DSS. It seems
+    I understand better now (after the discussion) how it works :-).
+    Implementing it should not be too difficult but might take some more
+    hours. Mentally scheduled it for Version "0.5.0" whenever this might
+    be (rough guess: christmas vacation).
+    Decided to hence not discuss this topic in the docs, since it might
+    change in the near future anyway.
+
+1999/11/23
+  - Discussion with rch@writeme.com (Richard) about implementing DH ciphers
+    and DSA keys and certificates on the Postfix/TLS list: It does not work
+    as of now.
+
+1999/11/15     == Released 0.4.5 ==
+
+1999/11/15
+  - Applied patch to postfix-19990906-pl07 without problems. Well, let's
+    release new version of Postfix/TLS, so that we look up to date.
+  - Add the "DO NOT EDIT THIS FILE" to conf/sample-tls.cf.
+
+1999/11/08
+  - Applied patch to the fresh release of postfix-19990906-pl06 without
+    problems. Nothing else, so no new release of Postfix/TLS.
+
+1999/11/07     == Released 0.4.4 ==
+
+1999/11/07
+  - Played around some more with the X509_verify_cert() function: when saving
+    a session, neither the verify_result is saved nor the certificate chain
+    necessary to re-verify. So there were two possibilities left: do a full
+    renegotiation negating the benefit of session caching or
+  - save the verify_result into to the session cache file and set the value
+    when rereading from disk. This way the positive result of session caching
+    is kept.
+  - Make sure, the verify_result value is propagated as pfixtls_peer_verified
+    and used where needed.
+  - After experiencing some failures at TLS connection setup, the SSL_sessions
+    are now freed again when closing. It seems, something is left over in the
+    session structures, even though SSL_clear() is called.
+
+1999/11/06
+  - When not asking for a client certificate, the "Received:" header will show
+    the protocol and cipher, but silently omit the client CN (because they
+    where not supplied). Noted by Craig Sanders <craig@taz.net.au>.
+    The same holds, if a certificate is asked for, but none supplied.
+    Now, in any case an appropriate information is added in the "Received:"
+    header.
+  - Added a hint to remove sessions from the cache during testing, since
+    old information may still be in the cache. Also proposed by Craig
+    Sanders <craig@taz.net.au>.
+  - While at it: client CN and issuer CN are printed, but the verification
+    state is not, so that the trust value of this data is not known.
+    * Added (verify OK/not verified) to the Received: header.
+    * Obtained information using the SSL_get_verify_result(SSL *con) call.
+    * Learned, that the state is not saved in the session information, so
+      that a recalled old session will always return "OK" even if the
+      certificate failed the verification! Call it a bug in OpenSSL.
+      Still investigating on a good way to work around this problem.
+  - Fixed a bug in the syslog entries: The client CN is logged, but the
+    issuer CN is not, because of a missing "%s" in the format string.
+
+1999/11/03     == Released 0.4.3 ==
+
+1999/11/03
+  - Added some hints about security to the html documentation.
+  - Tested the changes made two weeks ago at home in the large university
+    setup. I was to a conference in between and didn't want to release
+    the new version without having done some more tests.
+
+1999/10/17
+  - Added another half a ton of comments (this time for the client side),
+    yielding one ton alltogether...
+
+1999/10/16
+  - Rearranged some of the TLS-engine initialization to improve readability.
+  - Do not "free" the SSL connection, when it is not really necessary. Do only
+    reset information about the TLS connection, when there was one. This is
+    the better way instead of the quick fix applied for 0.4.2.
+  - Added half a ton of comments to the TLS code (server side) to document
+    what is done when and why, since there is no real documentation about
+    the OpenSSL library.
+
+1999/10/11     == Released 0.4.2 ==
+
+1999/10/11
+  - Fixed a severe bug introduced in 0.4.0: smtpd and smtp tried to flush
+    old session from the session cache even when TLS was not enabled. Since
+    no SSL-context was allocated, smtp would segfault on connection close.
+
+1999/10/10     == Released 0.4.1 ==
+
+1999/10/10
+  - Added a long description of the session cache handling to the top of
+    global/pfixtls.c.
+  - There is a race condition when cleaning up the session cache in qmgr, that
+    might lead to lost sessions in client mode. The worst consequence is an
+    additional session negotiation, so we can live with it as of now.
+    Bug described in qmgr/qmgr_tls.c.
+  - Implemented immediate removal of session cache files with expired sessions
+    when these are called. No need to first load and then discard them.
+  - Implemented the requirement from RFC2246 to remove sessions, when
+    connection failures occure (well actually, when TLS layer failures
+    occur, but I cannot seperate this from another) for the server side.
+    the client side is under work.
+
+1999/10/09
+  - Set an absolut maximum length of 32 for the IDs used for session caching.
+    This matches the default in OpenSSL, but I don´t want to see surprises
+    when somebody sometimes will run into a longer session id.
+
+1999/10/05     == Released 0.4.0 ==
+  - The new disk based session cache is a major step, so the minor release
+    number is pushed to 0.4.
+  - By now I think all necessary bells and whistles are in the code. What
+    is left is a big code cleanup and some more testing before calling this
+    patchkit "1.0.0".
+  - Initiated Mailing List at
+       http://www.aet.tu-cottbus.de/mailman/listinfo/postfix_tls
+
+1999/10/05
+  - Some code cleanup.
+  - Added new options to the documentation and the hint to update
+    "postfix-script", because otherwise qmgr might fail!
+
+1999/10/03
+  - Realized disc based session caching also for the Postfix/TLS client.
+    Must go to real world testing now between hosts.
+    And, of course, tune up the documentation, because users will have to
+    install a new postfix-script, too.
+
+1999/10/02
+  - The old sessions must be removed once they have timed out, so a process
+    is needed that will scan through the list of old sessions and remove
+    once they have expired.
+    Lucky me: this is what qmgr usually does with deferred messages, so
+    qmgr is extended only a little bit and will now also clean up the
+    old sessions from the cache directory.
+    And hey: it is good to see how easily this thing can be extended and
+    functions can easily be reused. Postfix is an excellent peace of
+    software engineering and there is no line of C++ or other "object
+    oriented modern junk" in it. It should be recommended as an example
+    to computer sience students.
+
+1999/09/28
+  - I cannot use the mod_ssl way for session caching and I don´t want to
+    spend an extra "gcache" daemon as ApacheSSL does. So I follow Wietse´s
+    idea realized for his mail queues and create hash level based subdirectory
+    structures. The good thing: I can cannibalize the mail_queue code.
+    The bad thing: there is a path length of 100 chars fix coded in Wietse´s
+    routines. It does hold for 32byte session ideas.
+    Status: can save sessions to disk and recall them (server side).
+
+1999/09/26
+  - Created new call backs for external session caching for the server side.
+    In a first step, they can print out the session ids for the newly created
+    session and when recalling a session.
+    As the OpenSSL documentation on this is pretty sparse, Ben Laurie´s
+    ApacheSSL code is very helpful, Ralph Engelschall´s Mod_SSL code for
+    session caching is far more complicated.
+
+1999/09/23     == Released 0.3.10 ==
+
+1999/09/23
+  - Debugging for 0.3.8/0.3.9 would have been so much easier, if the error
+    messages put onto the error message stack from the OpenSSL library would
+    have been printed out. The error was clearly stated from the library, I
+    just didn't print it. Added pfixtls_print_errors() calls where missing
+    after calls to the OpenSSL library.
+    Sometimes I feel so old...
+  - Used opportunity to upgrade to the latest postfix patchlevel 05:
+    postfix-19990906-pl05.
+
+1999/09/19     == Released 0.3.9 ==
+
+1999/09/19
+  - Added a "smtp_no_tls_sites" table to allow people to enable TLS negotiation
+    globally and only omit it on a per site basis.
+
+1999/09/18
+  - Finally found the bug described for 0.3.8: In the server setup, the
+    SSL_CTX_set_session_id_context() call was missing. To find this, I
+    had to trace through the OpenSSL library and when I finally found it
+    in ssl/ssl_sess.c, there was an appropriate comment about this. I however
+    have to find out why I didn´t receive the appropriate error message...
+  - This bug was hidden during the first developing stages, as the shutdown
+    sequence was not working correct, so the session was not cached.
+
+1999/09/17     == Released 0.3.8 ==
+
+1999/09/17
+  - Something is strange with the session caching in smtpd server mode
+    with Netscape 4.61 client. The first connection is fine, the next
+    one hangs after the server fails with errors while reading the
+    SSLv3 client hello C. (Found by Michael Stroeder <x_mst@propack-data.de>)
+    Reproducable with OpenSSL 0.9.3a, 0.9.4 and SNAPSHOT 19990915, so
+    the problem seems to be persistent. I will try to figure out the
+    problem myself before reporting it to the developers. If I don't find
+    it, maybe they do :-)
+    Workaround: the cached session is removed after connection is closed.
+    This will impose some time penalty on the negotiation. As the caching
+    is local in the smtp processes and they time out anyway, the penalty
+    should not be significant.
+    The problem does not occure with Postfix/TLS clients.
+
+1999/09/13     == Released 0.3.7 ==
+
+1999/09/13
+  - Ran tests, seems no further conflicts between Wietse's changes and my
+    extensions.
+
+1999/09/09
+  - Applied the patchkit 0.3.6 to postfix-19990906-pl02 and worked out
+    the rejected part of the patch. From this point of view the patch
+    is included. Now everything has to be retested.
+
+1999/09/09     == Released 0.3.6 ==
+
+1999/09/09
+  - Added a missing Â´#ifdef HAS_SSL #endif´ in smtp_connect.c.
+    Noted by Jeff Johnson <jeff@websitefactory.net>.
+  - HINT:
+    On 1999/09/06 a new "stable" version of postfix was released.
+    Future Postfix/TLS enhancements will be against this new version 19990906.
+
+1999/08/25     == Released 0.3.5 ==
+
+1999/08/25
+  - Added Wietse's patch for postfix-19990601 to prevent crashing smtpd when
+    VRFY is called without setting the sender with "MAIL FROM:" first.
+
+1999/08/13
+  - Small changes to global/pfixtls.[ch]: Since we also support client STARTLS,
+    we check the peers certificate, which may also be a "server" certificate
+    (not just client). Hence I renamed "*ccert*" to "*peer*".
+  - global/pfixtls.c: add some "const" to "char *" for OpenSSL library calls,
+    to make gcc happy.
+  - Extended comments in pfixtls.[ch] to better match Wietse's style.
+
+1999/08/12     == Released 0.3.4 ==
+
+1999/08/12
+  - Enabled workarounds for known bugs in SSL-engines.
+  - Tested with OpenSSL 0.9.4.
+  - Windows95/NT: Problem with Netscape hanging on first connection when
+    the client certificate database has to be unlocked cannot be reproduced
+    anymore.
+    I am happy, but I am also not sure what caused the problem to go away
+    and I cannot figure out the security settings manually from the files...
+
+1999/08/11
+  - Corrected loglevel handling: At some points smtpd_tls_loglevel was used
+    instead of smtp_tls_loglevel (only noted at loglevels >= 2).
+
+1999/08/09     == Released 0.3.3 ==
+
+1999/08/09
+  - Removed SSL_CTX_set_quiet_shutdown() as it does prevent the shutdown
+    from actually being performed. In order to remove the annoying
+    "SSL3 alert write:warning:close notify" it is now explicitly handled
+    in apps_ssl_info_callback().
+    Bug found by Bodo Moeller <bodo@openssl.org>.
+
+1999/08/06     == Released 0.3.2 ==
+
+1999/08/06
+  - Add option "smtp_tls_note_starttls_offer" to collect information about
+    hosts, that offered the STARTTLS feature without using it.
+  - Shut up smtpd. Only print information about relaying based on certs
+    when msg_verbose is true.
+
+1999/07/20
+  - Added missing "const" in pfixtls.h (found by Juergen Scheiderer
+    <jnschei@suse.de>). HP-UX ANSI-C didn't complain.
+
+1999/07/08     == Released 0.3.1 ==
+
+1999/07/08
+  - New config variable "smtpd_tls_received_header". When "true", the protocol
+    and cipher data as well as subject and issuer CN of the client certificate
+    are included into the "Received:" header.
+
+1999/07/07
+  - "starting TLS engine" message will only be printed when loglevel >=2
+    to reduce unnecessary noise in the log files.
+  - Added code to fetch the protocol (e.g. TLSv1) and the cipher used (by name
+    and bits). Information is printed to the logfile.
+
+1999/07/01     == Released 0.3.0 ==
+
+1999/07/01
+  - (Client mode) Bug fix: Don't try to use STARTTLS if it is not offered. The
+    server we are connected to might not understand it and respond with a
+    "500 command not understood", causing the email to bounce back, even
+    when the lack of STARTTLS is just a temporary problem.
+  - Updated documentation for the new per recipient/site TLS decisions.
+
+1999/06/30
+  - Client mode: Added variables and routines to decide "per recipient" or
+    "per host/site" whether to use/enforce TLS or not.
+
+1999/06/18     == Released 0.2.8 ==
+
+1999/06/18
+  - In client mode the "use_tls" and "enforce_tls" internal variables were
+    not initialized correctly, such that the client could try to use the
+    STARTTLS negotiation even if not wanted. This error was introduced
+    in 0.2.7.
+    Noted by "Cerebus" <cerebus@sackheads.org>.
+
+1999/06/08     == Released 0.2.7 ==
+
+1999/06/08
+  - Studied discussions in the IETF-apps-TLS mailing list: MS Exchange
+    seems to offer STARTTLS even if not configured. Added this info to the
+    documentation.
+  - Updated Documentation regarding the changes made.
+
+1999/06/03
+  - The subject-CommonName (CN) of the server certificate is extracted when
+    connecting to a TLS server.
+  - In "smtp_*_tls" mode, this subject-CommonName is matched against the
+    hostname of the server. In "enforce" mode, the connection is droppend
+    when the certified server name and the real hostname differ.
+  - Added missing dependencies in smtp/Makefile.in (missing pfixtls.h since
+    0.2.0).
+
+1999/06/02     == Released 0.2.6 ==
+
+1999/06/02
+  - Adapted patchkit to postfix-19990601.
+
+1999/06/01     == Released 0.2.5 ==
+
+1999/06/01
+  - Updated OpenSSL API to 0.9.3a -> position of include files has changed
+    from <xxx.h> to <openssl/xxx.h>. No functional changes.
+  - pkcs12 utility is now part of OpenSSL -> changed documentation
+    accordingly.
+
+1999/05/20     == Released 0.2.4 ==
+
+1999/05/20
+  - Updated postfix base 19990317 from pl04 to pl05.
+
+1999/05/14     == Released 0.2.3 ==
+
+1999/05/14
+  - Fixed a bug in pfixtls_stop_*(): there was a ";" to much directly
+    after "if (con);". This check is only done as a safety measure:
+    When SSL is not started you should not stop it. This case could however
+    only happen when the code in smtp[d] would be wrong, so it should never
+    be necessary. (Bug found by Uwe Ohse <uwe@ohse.de>)
+
+1999/05/11     == Released 0.2.2 ==
+
+1999/05/11
+  - Matti Aarnio: Reworked pfixtls_dump() to use fewer strcpy and strcat calls.
+  - Added information about Matti Aarnio (author/maintainer of ZMailer)
+    working on RFC2487 for ZMailer.
+
+1999/05/04     == Released 0.2.1 ==
+
+1999/05/04
+  - Stuffed up the documenation to reflect the actual status. No change
+    in functionality.
+
+1999/04/30     == Released 0.2.0 ==
+
+1999/04/30
+  - Adjusted the changes in smtp*.c to Wietse's indentation style.
+  - Sorry, the documentation about the client side has by now to be
+    taken from sample-tls.conf. The documenation has to be rearranged
+    in a larger scale.
+
+1999/04/29
+  - Finished client support for STARTTLS in smtp; some testing done.
+  - Fixed a race condition in smtpd: When in PIPELINE mode, the connection
+    was switched back from SSL to normal mode before the buffers were
+    flashed.
+  - Adjusted the code in pfixtls.[ch] and additions in smtpd*.c to
+    Wietse's indentation style.
+
+1999/04/28
+  - Incorporated skeleton of STARTTLS support into smtp.
+  - Introduced variables to control client STARTTLS to configuration.
+
+1999/04/15     == Released 0.1.5 ==
+
+1999/04/15
+  - Adjusted pfixtls.diff to postfix-19990317-pl04.
+
+1999/04/14
+  - Ported from OpenSSL the BIO_callback functions to dump out the negotiation
+    and transmission for debugging purposes. The functions are triggered
+    by the the new loglevels 3 and 4.
+  - Call SSL_free() to get rid of the SSL connection structure not used
+    anymore.
+
+1999/04/13     == Released 0.1.4 ==
+
+1999/04/13
+  - Based on a hint in the openssl-users list added an SSL_set_accept_state()
+    before the actual SSL_accept(). I don't really understand why, but the
+    documentation of SSL is a bit short anyway.
+
+1999/04/11
+  - Some more comments on certificates in the documentation.
+
+1999/04/10
+  - Moved initialization of the pfixtls_server_engine to the pre_jail_init()
+    section of smtpd, so that it is called with root privileges to read the
+    key and cert information. The secret key of the server can now be protected
+    by "chown root secretkey.pem; chmod 400 secretkey.pem".
+    Additionally, this makes it possible to run smtpd in chroot jail, even
+    though I didn't test that, yet. All information is read at smtpd startup
+    time except the CAcerts in tls_CApath, which are checked at runtime.
+    I have to look into that.
+  - Updated documentation accordingly.
+  - Rewrote the documentation with regard to the certificate setup and
+    explaining the different types of certificates.
+
+1999/04/09
+  - Introduced pfixtls_print_errors() which imitates BIO_print_errors()
+    (the typical way to print error information in OpenSSL) but writes
+    to syslog instead of a file handle.
+    Hence we can get more informative error information.
+
+1999/04/08     == Released 0.1.3 ==
+
+1999/04/08
+  - Stuffed up the documentation by reworking the references.
+  - Added contributed script for automatic addition of fingerprints.
+  - Added ACKNOWLEDGEMENTS file
+
+1999/04/06     == Released 0.1.2 ==
+
+1999/04/06
+  - Portability: removed call of "snprintf()", as it is not available on
+    some (older) UNIX versions (in this case Solaris 2.5).
+  - Removed calls to "select()" when in TLS mode: Even though no new bytes
+    arrive, there might be bytes left in the SSL buffer -> possible hang.
+
+1999/03/30     == Released 0.1.1 ==
+
+1999/03/30
+  - Added disclaimer about export restrictions.
+  - Fixed a bug in util/match_ops.c:
+    When using dictionary lookup the compare was case sensitive by accident.
+    Effect: Fingerprint matching did not work with databases, only for plain
+    file.
+    Bug report submitted to postfix author.
+
+1999/03/29     == Released first version 0.1.0 ==
diff --git a/postfix/src/tls/TLS_TODO b/postfix/src/tls/TLS_TODO
new file mode 100644 (file)
index 0000000..81389c8
--- /dev/null
@@ -0,0 +1,36 @@
+This list does not really follow priority.
+
+* Implement support of CRL checking. OpenSSL 0.9.7 finally supports CRLs,
+  so Postfix/TLS should support loading CRLs.
+
+* Cleanup the "pfixtls" special logging, so that it fits Wietses original
+  "per site" decision to make debugging easier.
+
+* Move TLS based information from separate lines into Postfix's smtpd
+  logging lines to make logfile analysis easier.
+
+* Check the "info_callback" for sensitive use. I already had to remove the
+  "warning alert" issued on normal shutdown. Why is a warning issued for
+  a normal shutdown??
+
+* Allow to specify the protocol used globally: SSLv2, SSLv3, TLSv1.
+
+* Enhance tls_per_site feature, such that not only MAY, MUST, NONE flags
+  are supported. It should also be possible to influence the behaviour:
+  choose the SSLv2/SSLv3/TLSv1 protocols.
+  [A compatible way to upgrad the tls_per_site table would be to add the
+  keywords:
+  MUST,SSLv2
+  MAY,NO_TLSv1
+  ]
+
+* Introduce new tls_per_client table to achieve the same selective behaviour
+  for incoming connections.
+
+* Introduce better support for "opportunistic" encryption: collect information
+  about peers connecting; log warnings when the key changed etc.
+  [I am not sure that I already have the best answers available.]
+
+* Find a way to use the certificates themselves instead of the fingerprints
+  to allow certificate based relaying. The maintenance of the fingerprints
+  is a nightmare.
diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h
new file mode 100644 (file)
index 0000000..a2ce271
--- /dev/null
@@ -0,0 +1,214 @@
+#ifndef _TLS_H_INCLUDED_
+#define _TLS_H_INCLUDED_
+
+/*++
+/* NAME
+/*      tls 3h
+/* SUMMARY
+/*      libtls internal interfaces
+/* SYNOPSIS
+/*      #include <tls.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * OpenSSL library.
+  */
+#include <openssl/lhash.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+#error "need OpenSSL version 0.9.5 or later"
+#endif
+
+ /*
+  * Utility library.
+  */
+#include <vstream.h>
+
+ /*
+  * TLS session context, also used by the VSTREAM call-back routines for SMTP
+  * input/output, and by OpenSSL call-back routines for key verification.
+  * 
+  * XXX Eliminate fixed-length buffers where possible.
+  * 
+  * XXX Eliminate the tls_info structure; it is no longer needed now that the
+  * TLScontext structure is exposed to the caller. If the caller's TLScontext
+  * pointer is null, there is no TLS session. This change (plus other
+  * changes) eliminated global variables that were shared between TLS client
+  * and server code. Multiple clients and/or servers can now co-exist in the
+  * same process.
+  */
+#define CCERT_BUFSIZ   256
+#define HOST_BUFSIZ  255               /* RFC 1035 */
+
+typedef struct {
+    SSL    *con;
+    BIO    *internal_bio;              /* postfix/TLS side of pair */
+    BIO    *network_bio;               /* network side of pair */
+    char    peer_subject[CCERT_BUFSIZ];
+    char    peer_issuer[CCERT_BUFSIZ];
+    char    peer_CN[CCERT_BUFSIZ];
+    char    issuer_CN[CCERT_BUFSIZ];
+    unsigned char md[EVP_MAX_MD_SIZE];
+    char    fingerprint[EVP_MAX_MD_SIZE * 3];
+    char    peername_save[HOST_BUFSIZ + 1];
+    int     enforce_verify_errors;
+    int     enforce_CN;
+    int     hostname_matched;
+    int     log_level;
+} TLScontext_t;
+
+#define TLS_BIO_BUFSIZE        8192
+
+typedef struct {
+    int     peer_verified;
+    int     hostname_matched;
+    char   *peer_subject;
+    char   *peer_issuer;
+    char   *peer_fingerprint;
+    char   *peer_CN;
+    char   *issuer_CN;
+    const char *protocol;
+    const char *cipher_name;
+    int     cipher_usebits;
+    int     cipher_algbits;
+} tls_info_t;
+
+extern const tls_info_t tls_info_zero;
+
+ /*
+  * tls_client.c
+  */
+extern SSL_CTX *tls_client_init(int);
+extern TLScontext_t *tls_client_start(SSL_CTX *, VSTREAM *, int, int,
+                                             const char *, tls_info_t *);
+
+#define tls_client_stop(ctx , stream, timeout, failure, tls_info) \
+       tls_session_stop((ctx), (stream), (timeout), (failure), (tls_info))
+
+ /*
+  * tls_server.c
+  */
+extern SSL_CTX *tls_server_init(int, int);
+extern TLScontext_t *tls_server_start(SSL_CTX *, VSTREAM *, int,
+                                             const char *, const char *,
+                                             tls_info_t *, int);
+
+#define tls_server_stop(ctx , stream, timeout, failure, tls_info) \
+       tls_session_stop((ctx), (stream), (timeout), (failure), (tls_info))
+
+ /*
+  * tls_session.c
+  */
+extern void tls_session_stop(SSL_CTX *, VSTREAM *, int, int, tls_info_t *);
+
+#ifdef TLS_INTERNAL
+
+#include <vstring.h>
+
+extern VSTRING *tls_session_passivate(SSL_SESSION *);
+extern SSL_SESSION *tls_session_activate(char *, int);
+
+ /*
+  * tls_stream.c.
+  */
+extern void tls_stream_start(VSTREAM *, TLScontext_t *);
+extern void tls_stream_stop(VSTREAM *);
+
+ /*
+  * tls_bio_ops.c: a generic multi-personality driver that retries SSL
+  * operations until they are satisfied or until a hard error happens.
+  * Because of its ugly multi-personality user interface we invoke it via
+  * not-so-ugly single-personality wrappers.
+  */
+extern int tls_bio(int, int, TLScontext_t *,
+                          int (*) (SSL *),     /* handshake */
+                          int (*) (SSL *, void *, int),        /* read */
+                          int (*) (SSL *, const void *, int),  /* write */
+                          void *, int);
+
+#define tls_bio_connect(fd, timeout, context) \
+        tls_bio((fd), (timeout), (context), SSL_connect, \
+               NULL, NULL, NULL, 0)
+#define tls_bio_accept(fd, timeout, context) \
+        tls_bio((fd), (timeout), (context), SSL_accept, \
+               NULL, NULL, NULL, 0)
+#define tls_bio_shutdown(fd, timeout, context) \
+       tls_bio((fd), (timeout), (context), SSL_shutdown, \
+               NULL, NULL, NULL, 0)
+#define tls_bio_read(fd, buf, len, timeout, context) \
+       tls_bio((fd), (timeout), (context), NULL, \
+               SSL_read, NULL, (buf), (len))
+#define tls_bio_write(fd, buf, len, timeout, context) \
+       tls_bio((fd), (timeout), (context), NULL, \
+               NULL, SSL_write, (buf), (len))
+
+ /*
+  * tls_dh.c
+  */
+extern void tls_set_dh_1024_from_file(const char *);
+extern void tls_set_dh_512_from_file(const char *);
+extern DH *tls_tmp_dh_cb(SSL *, int, int);
+
+ /*
+  * tls_rsa.c
+  */
+extern RSA *tls_tmp_rsa_cb(SSL *, int, int);
+
+ /*
+  * tls_verify.c
+  */
+extern int tls_verify_certificate_callback(int, X509_STORE_CTX *, int);
+
+#define TLS_VERIFY_DEFAULT     (0)
+#define TLS_VERIFY_PEERNAME    (1<<0)
+
+ /*
+  * tls_certkey.c
+  */
+extern int tls_set_ca_certificate_info(SSL_CTX *, const char *, const char *);
+extern int tls_set_my_certificate_key_info(SSL_CTX *, const char *,
+                                                  const char *,
+                                                  const char *,
+                                                  const char *);
+
+ /*
+  * tls_misc.c
+  */
+extern int TLScontext_index;
+extern int TLSpeername_index;
+
+extern void tls_print_errors(void);
+extern void tls_info_callback(const SSL *, int, int);
+extern long tls_bio_dump_cb(BIO *, int, const char *, int, long, long);
+
+ /*
+  * tls_seed.c
+  */
+extern void tls_int_seed(void);
+extern int tls_ext_seed(int);
+
+ /*
+  * tls_temp.c, code that is going away.
+  */
+#endif                                 /* TLS_INTERNAL */
+
+/* LICENSE
+/* .ad
+/* .fi
+/*      The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*      Wietse Venema
+/*      IBM T.J. Watson Research
+/*      P.O. Box 704
+/*      Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif                                 /* _TLS_H_INCLUDED_ */
diff --git a/postfix/src/tls/tls_bio_ops.c b/postfix/src/tls/tls_bio_ops.c
new file mode 100644 (file)
index 0000000..bc359ba
--- /dev/null
@@ -0,0 +1,336 @@
+/*++
+/* NAME
+/*     tls_bio_ops 3
+/* SUMMARY
+/*     TLS network BIO management
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     int tls_bio_connect(fd, timeout, context)
+/*     int     fd;
+/*     int     timeout;
+/*     TLScontext_t *context;
+/*
+/*     int tls_bio_accept(fd, timeout, context)
+/*     int     fd;
+/*     int     timeout;
+/*     TLScontext_t *context;
+/*
+/*     int tls_bio_shutdown(fd, timeout, context)
+/*     int     fd;
+/*     int     timeout;
+/*     TLScontext_t *context;
+/*
+/*     int tls_bio_read(fd, buf, len, timeout, context)
+/*     int     fd;
+/*     void    *buf;
+/*     int     len;
+/*     int     timeout;
+/*     TLScontext_t *context;
+/*
+/*     int tls_bio_write(fd, buf, len, timeout, context)
+/*     int     fd;
+/*     void    *buf;
+/*     int     len;
+/*     int     timeout;
+/*     TLScontext_t *context;
+/* DESCRIPTION
+/*     This layer synchronizes the TLS network buffers with the network
+/*     while performing TLS handshake or input/output operations.
+/*
+/*     When the TLS layer is active, it converts plain-text
+/*     data from Postfix into encrypted network data and vice versa.
+/*     However, to handle network timeout conditions, Postfix
+/*     needs to maintain control over network input/output. This
+/*     rules out the usual approach of placing the TLS layer
+/*     between the application and the network socket.
+/*
+/*     As shown below, Postfix reads/writes plain-text data from/to
+/*     the TLS layer. The TLS layer informs Postfix when it needs
+/*     to read/write encrypted data from/to the network; Postfix
+/*     then reads/writes encrypted data from/to the TLS layer and
+/*     takes care of the network socket I/O.
+/*
+/*     The TLS layer to network interface is realized with a BIO pair:
+/*
+/*      Postfix             |   TLS layer
+/*                          |
+/*     smtp/smtpd           |
+/*      /\    ||            |
+/*      ||    \/            |
+/*     vstream read/write <===> TLS read/write/etc
+/*                          |     /\    ||
+/*                          |     ||    \/
+/*                          |   BIO pair (internal_bio)
+/*                          |   BIO pair (network_bio)
+/*                          |     /\    ||
+/*                          |     ||    \/
+/*     socket read/write  <===> BIO read/write
+/*      /\    ||            |
+/*      ||    \/            |
+/*      network             |
+/*
+/*     The Postfix VSTREAM read/write operations invoke the SSL
+/*     read/write operations to send and retrieve plain-text data. Inside
+/*     the TLS layer the data are converted to/from TLS protocol.
+/*
+/*     Whenever an SSL operation reports success, or whenever it
+/*     indicates that network input/output needs to happen, Postfix
+/*     uses the BIO read/write routines to synchronize the
+/*     network_bio buffer with the network.  Writing data to the
+/*     network has precedence over reading from the network. This
+/*     is necessary to avoid deadlock.
+/*
+/*     The BIO pair buffer size is set to 8192 bytes. This is much
+/*     larger than the typical Path MTU, and avoids sending tiny TCP
+/*     segments.  It is also larger than the default VSTREAM_BUFSIZE
+/*     (4096, see vstream.h), so that large write operations can
+/*     be handled within one request.  The internal buffer in the
+/*     network/network_bio handling layer is set to the same
+/*     value, since this seems to be reasonable. The code is
+/*     however able to handle arbitrary values smaller or larger
+/*     than the buffer size in the BIO pair.
+/*
+/*     tls_bio_connect() performs the SSL_connect() operation while
+/*     synchronizing the network_bio buffer with the network.
+/*
+/*     tls_bio_accept() performs the SSL_accept() operation while
+/*     synchronizing the network_bio buffer with the network.
+/*
+/*     tls_bio_shutdown() performs the SSL_shutdown() operation while
+/*     synchronizing the network_bio buffer with the network.
+/*
+/*     tls_bio_read() performs the SSL_read() operation while
+/*     synchronizing the network_bio buffer with the network.
+/*
+/*     tls_bio_write() performs the SSL_write() operation while
+/*     synchronizing the network_bio buffer with the network.
+/*
+/*     Arguments:
+/* .IP fd
+/*     Network socket.
+/* .IP buf
+/*     Read/write buffer.
+/* .IP len
+/*     Read/write request size.
+/* .IP timeout
+/*     Read/write timeout.
+/* .IP TLScontext
+/*     TLS session state.
+/* DIAGNOSTICS
+/*     The result value is -1 in case of a network read/write
+/*     error, otherwise it is the result value of the TLS operation.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <msg.h>
+#include <iostuff.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+#define NETLAYER_BUFFERSIZE 8192
+
+/* network_biopair_interop - synchronize network with BIO pair */
+
+static int network_biopair_interop(int fd, int timeout, BIO *network_bio)
+{
+    const char *myname = "network_biopair_interop";
+    int     want_write;
+    int     num_write;
+    int     write_pos;
+    int     from_bio;
+    int     want_read;
+    int     num_read;
+    int     to_bio;
+    char    buffer[NETLAYER_BUFFERSIZE];
+
+    /*
+     * To avoid deadlock, write all pending data to the network before
+     * attempting to read from the network.
+     */
+    while ((want_write = BIO_ctrl_pending(network_bio)) > 0) {
+       if (want_write > sizeof(buffer))
+           want_write = sizeof(buffer);
+       from_bio = BIO_read(network_bio, buffer, want_write);
+
+       /*
+        * Write the complete buffer contents to the network.
+        */
+       for (write_pos = 0; write_pos < from_bio; /* see below */ ) {
+           if (timeout > 0 && write_wait(fd, timeout) < 0)
+               return (-1);
+           num_write = write(fd, buffer + write_pos, from_bio - write_pos);
+           if (num_write <= 0) {
+               if ((num_write < 0) && (timeout > 0) && (errno == EAGAIN)) {
+                   msg_warn("write() returns EAGAIN on a writable file descriptor!");
+                   msg_warn("pausing to avoid going into a tight select/write loop!");
+                   sleep(1);
+               } else {
+                   msg_warn("%s: error writing %d bytes to the network: %m",
+                            myname, from_bio - write_pos);
+                   return (-1);
+               }
+           } else {
+               write_pos += num_write;
+           }
+       }
+    }
+
+    /*
+     * Read data from the network into the BIO pair.
+     */
+    while ((want_read = BIO_ctrl_get_read_request(network_bio)) > 0) {
+       if (want_read > sizeof(buffer))
+           want_read = sizeof(buffer);
+       if (timeout > 0 && read_wait(fd, timeout) < 0)
+           return (-1);
+       num_read = read(fd, buffer, want_read);
+       if (num_read == 0)
+           /* FIX 200412 Cannot return a zero read count. */
+           return (-1);
+       if (num_read < 0) {
+           if ((num_read < 0) && (timeout > 0) && (errno == EAGAIN)) {
+               msg_warn("read() returns EAGAIN on a readable file descriptor!");
+               msg_warn("pausing to avoid going into a tight select/write loop!");
+               sleep(1);
+           } else {
+               msg_warn("%s: error reading %d bytes from the network: %m",
+                        myname, want_read);
+               return (-1);
+           }
+       } else {
+           to_bio = BIO_write(network_bio, buffer, num_read);
+           if (to_bio != num_read)
+               msg_panic("%s: BIO_write error: to_bio != num_read", myname);
+       }
+    }
+    return (0);
+}
+
+/* tls_bio - perform SSL input/output operation with extreme prejudice */
+
+int     tls_bio(int fd, int timeout, TLScontext_t *TLScontext,
+                       int (*hsfunc) (SSL *),
+                       int (*rfunc) (SSL *, void *, int),
+                       int (*wfunc) (SSL *, const void *, int),
+                       void *buf, int num)
+{
+    const char *myname = "tls_bio";
+    int     status;
+    int     err;
+    int     retval = 0;
+    int     biop_retval;
+    int     done;
+
+    /*
+     * If necessary, retry the SSL handshake or read/write operation after
+     * handling any pending network I/O.
+     */
+    for (done = 0; done == 0; /* void */ ) {
+       if (hsfunc)
+           status = hsfunc(TLScontext->con);
+       else if (rfunc)
+           status = rfunc(TLScontext->con, buf, num);
+       else if (wfunc)
+           status = wfunc(TLScontext->con, buf, num);
+       else
+           msg_panic("%s: nothing to do here", myname);
+       err = SSL_get_error(TLScontext->con, status);
+
+#if (OPENSSL_VERSION_NUMBER <= 0x0090581fL)
+
+       /*
+        * There is a bug up to and including OpenSSL-0.9.5a: if an error
+        * occurs while checking the peers certificate due to some
+        * certificate error (e.g. as happend with a RSA-padding error), the
+        * error is put onto the error stack. If verification is not
+        * enforced, this error should be ignored, but the error-queue is not
+        * cleared, so we can find this error here. The bug has been fixed on
+        * May 28, 2000.
+        * 
+        * This bug so far has only manifested as 4800:error:0407006A:rsa
+        * routines:RSA_padding_check_PKCS1_type_1:block type is not
+        * 01:rsa_pk1.c:100: 4800:error:04067072:rsa
+        * routines:RSA_EAY_PUBLIC_DECRYPT:padding check
+        * failed:rsa_eay.c:396: 4800:error:0D079006:asn1 encoding
+        * routines:ASN1_verify:bad get asn1 object call:a_verify.c:109: so
+        * that we specifically test for this error. We print the errors to
+        * the logfile and automatically clear the error queue. Then we retry
+        * to get another error code. We cannot do better, since we can only
+        * retrieve the last entry of the error-queue without actually
+        * cleaning it on the way.
+        * 
+        * This workaround is secure, as verify_result is set to "failed"
+        * anyway.
+        */
+       if (err == SSL_ERROR_SSL) {
+           if (ERR_peek_error() == 0x0407006AL) {
+               pfixtls_print_errors();
+               msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
+               err = SSL_get_error(TLScontext->con, status);
+           }
+       }
+#endif
+
+       /*
+        * Find out if we must retry the operation and/or if there is pending
+        * network I/O.
+        * 
+        * XXX If we're the first to invoke SSL_shutdown(), then the operation
+        * isn't really complete when the call returns. We could hide that
+        * anomaly here and repeat the call.
+        */
+       switch (err) {
+       case SSL_ERROR_NONE:                    /* success */
+           retval = status;
+           done = 1;
+           /* FALLTHROUGH */
+       case SSL_ERROR_WANT_WRITE:              /* flush/update buffers */
+       case SSL_ERROR_WANT_READ:
+           biop_retval =
+               network_biopair_interop(fd, timeout, TLScontext->network_bio);
+           if (biop_retval < 0)
+               return (-1);                    /* network read/write error */
+           break;
+       default:
+           retval = status;
+           done = 1;
+           break;
+       }
+    }
+    return (retval);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_certkey.c b/postfix/src/tls/tls_certkey.c
new file mode 100644 (file)
index 0000000..d97521d
--- /dev/null
@@ -0,0 +1,160 @@
+/*++
+/* NAME
+/*     tls_certkey 3
+/* SUMMARY
+/*     public key certificate and private key loader
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     int     tls_set_ca_certificate_info(ctx, CAfile, CApath)
+/*     SSL_CTX *ctx;
+/*     const char *CAfile;
+/*     const char *CApath;
+/*
+/*     int     tls_set_my_certificate_key_info(ctx, cert_file, key_file,
+/*                                             dcert_file, dkey_file)
+/*     SSL_CTX *ctx;
+/*     const char *cert_file;
+/*     const char *key_file;
+/*     const char *dcert_file;
+/*     const char *dkey_file;
+/* DESCRIPTION
+/*     OpenSSL supports two options to specify CA certificates:
+/*     either one file CAfile that contains all CA certificates,
+/*     or a directory CApath with separate files for each
+/*     individual CA, with symbolic links named after the hash
+/*     values of the certificates. The second option is not
+/*     convenient with a chrooted process.
+/*
+/*     tls_set_ca_certificate_info() loads the CA certificate
+/*     information for the specified TLS server or client context.
+/*     The result is -1 on failure, 0 on success.
+/*
+/*     tls_set_my_certificate_key_info() loads the public key
+/*     certificate and private key for the specified TLS server
+/*      or client context. The key file and certificate file may
+/*     be the same file; the certificate and key must match.
+/*     The result is -1 on failure, 0 on success.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* tls_set_ca_certificate_info - load certificate authority certificates */
+
+int     tls_set_ca_certificate_info(SSL_CTX *ctx, const char *CAfile,
+                                           const char *CApath)
+{
+    if (*CAfile == 0)
+       CAfile = 0;
+    if (*CApath == 0)
+       CApath = 0;
+    if (CAfile || CApath) {
+       if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
+           msg_info("cannot load Certificate Authority data");
+           tls_print_errors();
+           return (-1);
+       }
+       if (!SSL_CTX_set_default_verify_paths(ctx)) {
+           msg_info("cannot set certificate verification paths");
+           tls_print_errors();
+           return (-1);
+       }
+    }
+    return (0);
+}
+
+/* set_cert_stuff - specify certificate and key information */
+
+static int set_cert_stuff(SSL_CTX *ctx, const char *cert_file,
+                                 const char *key_file)
+{
+
+    /*
+     * We need both the private key (in key_file) and the public key
+     * certificate (in cert_file). Both may specify the same file.
+     * 
+     * Code adapted from OpenSSL apps/s_cb.c.
+     */
+    if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
+       msg_warn("cannot get certificate from file %s", cert_file);
+       tls_print_errors();
+       return (0);
+    }
+    if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
+       msg_warn("cannot get private key from file %s", key_file);
+       tls_print_errors();
+       return (0);
+    }
+
+    /*
+     * Sanity check.
+     */
+    if (!SSL_CTX_check_private_key(ctx)) {
+       msg_warn("private key in %s does not match public key certificate in %s",
+                key_file, cert_file);
+       return (0);
+    }
+    return (1);
+}
+
+/* tls_set_my_certificate_key_info - load client or server certificate/key */
+
+int     tls_set_my_certificate_key_info(SSL_CTX *ctx,
+                               const char *cert_file, const char *key_file,
+                             const char *dcert_file, const char *dkey_file)
+{
+    if (*cert_file == 0 && *dcert_file == 0) {
+       msg_warn("need an RSA or DSA certificate/key pair");
+       return (-1);
+    }
+    if (*cert_file) {
+       if (!set_cert_stuff(ctx, cert_file, *key_file ? key_file : cert_file)) {
+           msg_info("cannot load RSA certificate and key data");
+           tls_print_errors();
+           return (-1);
+       }
+    }
+    if (*dcert_file) {
+       if (!set_cert_stuff(ctx, dcert_file, *dkey_file ? dkey_file : dcert_file)) {
+           msg_info("cannot load DSA certificate and key data");
+           tls_print_errors();
+           return (-1);
+       }
+    }
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c
new file mode 100644 (file)
index 0000000..95002bd
--- /dev/null
@@ -0,0 +1,748 @@
+/*++
+/* NAME
+/*     tls
+/* SUMMARY
+/*     client-side TLS engine
+/* SYNOPSIS
+/*     #include <tls.h>
+/*
+/*     SSL_CTX *tls_client_init(verifydepth)
+/*     int     verifydepth; /* unused */
+/*
+/*     TLScontext_t *tls_client_start(client_ctx, stream, timeout, peername,
+/*                                     peeraddr, tls_info)
+/*     SSL_CTX *client_ctx;
+/*     VSTREAM *stream;
+/*     int     timeout;
+/*     const char *peername;
+/*     const char *peeraddr;
+/*     tls_info_t *tls_info;
+/*
+/*     void    tls_client_stop(client_ctx, stream, failure, tls_info)
+/*     SSL_CTX *client_ctx;
+/*     VSTREAM *stream;
+/*     int     failure;
+/*     tls_info_t *tls_info;
+/* DESCRIPTION
+/*      This module is the interface between Postfix TLS clients
+/*     and the OpenSSL library and TLS entropy and cache manager.
+/*
+/*     tls_client_init() is called once when the SMTP client
+/*     initializes.
+/*     Certificate details are also decided during this phase,
+/*     so that peer-specific behavior is not possible.
+/*
+/*     tls_client_start() activates the TLS feature for the VSTREAM
+/*     passed as argument. We expect that network buffers are flushed and the
+/*     TLS handshake can begin immediately. Information about the peer
+/*     is stored into the tls_info structure passed as argument.
+/*
+/*     tls_client_stop() sends the "close notify" alert via
+/*     SSL_shutdown() to the peer and resets all connection specific
+/*     TLS data. As RFC2487 does not specify a separate shutdown, it
+/*     is assumed that the underlying TCP connection is shut down
+/*     immediately afterwards, so we don't care about additional data
+/*     coming through the channel.
+/*     If the failure flag is set, no SSL_shutdown() handshake is performed.
+/*
+/*     Once the TLS connection is initiated, information about the TLS
+/*     state is available via the tls_info structure:
+/* .IP tls_info->protocol
+/*     the protocol name (SSLv2, SSLv3, TLSv1),
+/* .IP tls_info->cipher_name
+/*     the cipher name (e.g. RC4/MD5),
+/* .IP tls_info->cipher_usebits
+/*     the number of bits actually used (e.g. 40),
+/* .IP tls_info->cipher_algbits
+/*     the number of bits the algorithm is based on (e.g. 128).
+/* .PP
+/*     The last two values may differ from each other when export-strength
+/*     encryption is used.
+/*
+/*     The status of the peer certificate verification is available in
+/*     tls_info->peer_verified. It is set to 1 when the certificate could
+/*     be verified.
+/*     If the peer offered a certificate, part of the certificate data are
+/*     available as:
+/* .IP tls_info->peer_subject
+/*     X509v3-oneline with the DN of the peer
+/* .IP tls_info->peer_CN
+/*     extracted CommonName of the peer
+/* .IP tls_info->peer_issuer
+/*     X509v3-oneline with the DN of the issuer
+/* .IP tls_info->issuer_CN
+/*     extracted CommonName of the issuer
+/* .IP tls_info->peer_fingerprint
+/*     fingerprint of the certificate
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+#include <string.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <stringops.h>
+#include <msg.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* TLS library. */
+
+#include <tls_mgr.h>
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+#define STR    vstring_str
+#define LEN    VSTRING_LEN
+
+ /*
+  * To convert binary to fingerprint.
+  */
+static const char hexcodes[] = "0123456789ABCDEF";
+
+ /*
+  * Do or don't we cache client sessions?
+  */
+static int tls_client_cache = 0;
+
+/* client_verify_callback - certificate verification wrapper */
+
+static int client_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+    return (tls_verify_certificate_callback(ok, ctx, TLS_VERIFY_PEERNAME));
+}
+
+/* load_clnt_session - load session from client cache (non-callback) */
+
+static SSL_SESSION *load_clnt_session(const char *hostname,
+                                             int enforce_peername)
+{
+    SSL_SESSION *session = 0;
+    char   *cache_id;
+    VSTRING *cache_id_buffer;
+    VSTRING *session_data = vstring_alloc(2048);
+    int     flags = 0;
+
+#define TLS_FLAG_ENFORCE_PEERNAME      (1<<0)
+
+    /*
+     * Prepare the query.
+     */
+    cache_id = lowercase(mystrdup(hostname));
+    if (var_smtp_tls_loglevel >= 3)
+       msg_info("looking for session %s in client cache", cache_id);
+    if (enforce_peername)
+       flags |= TLS_FLAG_ENFORCE_PEERNAME;
+
+    /*
+     * Look up and activate the SSL_SESSION object. Errors are non-fatal,
+     * since caching is only an optimization.
+     */
+    if (tls_mgr_lookup(tls_client_cache, cache_id, OPENSSL_VERSION_NUMBER,
+                      flags, session_data) == TLS_MGR_STAT_OK) {
+       session = tls_session_activate(STR(session_data), LEN(session_data));
+       if (session) {
+           if (var_smtp_tls_loglevel >= 3)
+               msg_info("reloaded session %s from client cache", cache_id);
+           cache_id_buffer =
+               (VSTRING *) SSL_SESSION_get_ex_data(session, TLSpeername_index);
+           vstring_strcpy(cache_id_buffer, cache_id);
+       }
+    }
+
+    /*
+     * Clean up.
+     */
+    myfree(cache_id);
+    vstring_free(session_data);
+
+    return (session);
+}
+
+ /*
+  * The client session cache is indexed by peer name, not by session id. The
+  * following routines maintain string storage for the peer name in an
+  * SSL_SESSION object. We use VSTRING buffers so that we don't have to worry
+  * about hostname length problems.
+  */
+
+/* new_cache_id_func - create space for peer name in SSL_SESSION object */
+
+static int new_cache_id_func(void *unused_parent, void *unused_ptr,
+                                    CRYPTO_EX_DATA *ad, int idx,
+                                    long unused_argl, void *unused_argp)
+{
+    VSTRING *cache_id_buffer;
+
+    cache_id_buffer = vstring_alloc(32);
+    return (CRYPTO_set_ex_data(ad, idx, (void *) cache_id_buffer));
+}
+
+/* free_cache_id_func - destroy space for peer name in SSL_SESSION object */
+
+static void free_cache_id_func(void *unused_parent, void *unused_ptr,
+                                      CRYPTO_EX_DATA *ad, int idx,
+                                      long unused_argl, void *unused_argp)
+{
+    VSTRING *cache_id_buffer;
+
+    cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(ad, idx);
+    vstring_free(cache_id_buffer);
+}
+
+/* dup_cache_id_func - duplicate peer name when SSL_SESSION is duplicated */
+
+static int dup_cache_id_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
+          void *unused_from_d, int idx, long unused_argl, void *unused_argp)
+{
+    const char *myname = "dup_cache_id_func";
+    VSTRING *old_cache_id_buffer;
+    VSTRING *new_cache_id_buffer;
+
+    old_cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(from, idx);
+    if (old_cache_id_buffer == 0) {
+       msg_warn("%s: cannot get old SSL_SESSION peer name buffer", myname);
+       return (0);
+    }
+    new_cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(to, idx);
+    if (new_cache_id_buffer == 0) {
+       msg_warn("%s: cannot get new SSL_SESSION peer name buffer", myname);
+       return (0);
+    }
+    vstring_strcpy(new_cache_id_buffer, STR(old_cache_id_buffer));
+    return (1);
+}
+
+/* new_client_session_cb - name new session and save it to client cache */
+
+static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
+{
+    TLScontext_t *TLScontext;
+    VSTRING *session_data;
+    VSTRING *cache_id_buffer;
+    int     flags = 0;
+
+    /*
+     * Attach the cache ID string to the session object. Don't worry about
+     * the length; that is the concern of the code that updates the session
+     * cache.
+     */
+    cache_id_buffer =
+       (VSTRING *) SSL_SESSION_get_ex_data(session, TLSpeername_index);
+    TLScontext = SSL_get_ex_data(ssl, TLScontext_index);
+    vstring_strcpy(cache_id_buffer, TLScontext->peername_save);
+    lowercase(STR(cache_id_buffer));           /* just in case */
+
+    if (var_smtp_tls_loglevel >= 3)
+       msg_info("save session %s to client cache", STR(cache_id_buffer));
+
+    /*
+     * Remember whether peername matching was enforced when the session was
+     * created. If later enforce mode is enabled, we do not want to reuse a
+     * session that was not sufficiently checked.
+     */
+    if (TLScontext->enforce_verify_errors && TLScontext->enforce_CN)
+       flags |= TLS_FLAG_ENFORCE_PEERNAME;
+
+#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
+
+    /*
+     * Ugly Hack: OpenSSL before 0.9.6a does not store the verify result in
+     * sessions for the client side. We modify the session directly which is
+     * version specific, but this bug is version specific, too.
+     * 
+     * READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before beta1 have this
+     * bug, it has been fixed during development of 0.9.6a. The development
+     * version of 0.9.7 can have this bug, too. It has been fixed on
+     * 2000/11/29.
+     */
+    session->verify_result = SSL_get_verify_result(TLScontext->con);
+#endif
+
+    /*
+     * Passivate and save the session object. Errors are non-fatal, since
+     * caching is only an optimization.
+     */
+    session_data = tls_session_passivate(session);
+    if (session_data)
+       tls_mgr_update(tls_client_cache, STR(cache_id_buffer),
+                      OPENSSL_VERSION_NUMBER, flags,
+                      STR(session_data), LEN(session_data));
+
+    /*
+     * Clean up.
+     */
+    if (session_data)
+       vstring_free(session_data);
+
+    return (1);
+}
+
+/* tls_client_init - initialize client-side TLS engine */
+
+SSL_CTX *tls_client_init(int unused_verifydepth)
+{
+    int     off = 0;
+    int     verify_flags = SSL_VERIFY_NONE;
+    SSL_CTX *client_ctx;
+    int     cache_types;
+
+    /* See skeleton in OpenSSL apps/s_client.c. */
+
+    if (var_smtp_tls_loglevel >= 2)
+       msg_info("initializing the client-side TLS engine");
+
+    /*
+     * Initialize the OpenSSL library by the book! To start with, we must
+     * initialize the algorithms. We want cleartext error messages instead of
+     * just error codes, so we load the error_strings.
+     */
+    SSL_load_error_strings();
+    OpenSSL_add_ssl_algorithms();
+
+    /*
+     * Initialize the PRNG (Pseudo Random Number Generator) with some seed
+     * from external and internal sources. Don't enable TLS without some real
+     * entropy.
+     */
+    if (tls_ext_seed(var_tls_daemon_rand_bytes) < 0) {
+       msg_warn("no entropy for TLS key generation: disabling TLS support");
+       return (0);
+    }
+    tls_int_seed();
+
+    /*
+     * The SSL/TLS specifications require the client to send a message in the
+     * oldest specification it understands with the highest level it
+     * understands in the message. RFC2487 is only specified for TLSv1, but
+     * we want to be as compatible as possible, so we will start off with a
+     * SSLv2 greeting allowing the best we can offer: TLSv1. We can restrict
+     * this with the options setting later, anyhow.
+     */
+    client_ctx = SSL_CTX_new(SSLv23_client_method());
+    if (client_ctx == NULL) {
+       tls_print_errors();
+       return (0);
+    }
+
+    /*
+     * Here we might set SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1.
+     * Of course, the last one would not make sense, since RFC2487 is only
+     * defined for TLS, but we don't know what is out there. So leave things
+     * completely open, as of today.
+     */
+    off |= SSL_OP_ALL;                         /* Work around all known bugs */
+    SSL_CTX_set_options(client_ctx, off);
+
+    /*
+     * Set the call-back routine for verbose logging.
+     */
+    if (var_smtp_tls_loglevel >= 2)
+       SSL_CTX_set_info_callback(client_ctx, tls_info_callback);
+
+    /*
+     * Override the default cipher list with our own list.
+     */
+    if (*var_smtp_tls_cipherlist != 0)
+       if (SSL_CTX_set_cipher_list(client_ctx, var_smtp_tls_cipherlist) == 0) {
+           tls_print_errors();
+           SSL_CTX_free(client_ctx);           /* 200411 */
+           return (0);
+       }
+
+    /*
+     * Load the CA public key certificates for both the client cert and for
+     * the verification of server certificates. As provided by OpenSSL we
+     * support two types of CA certificate handling: One possibility is to
+     * add all CA certificates to one large CAfile, the other possibility is
+     * a directory pointed to by CApath, containing separate files for each
+     * CA with softlinks named after the hash values of the certificate. The
+     * first alternative has the advantage that the file is opened and read
+     * at startup time, so that you don't have the hassle to maintain another
+     * copy of the CApath directory for chroot-jail.
+     */
+    if (tls_set_ca_certificate_info(client_ctx, var_smtp_tls_CAfile,
+                                   var_smtp_tls_CApath) < 0) {
+       SSL_CTX_free(client_ctx);               /* 200411 */
+       return (0);
+    }
+
+    /*
+     * We do not need a client certificate, so the certificates are only
+     * loaded (and checked) if supplied. A clever client would handle
+     * multiple client certificates and decide based on the list of
+     * acceptable CAs, sent by the server, which certificate to submit.
+     * OpenSSL does however not do this and also has no call-back hooks to
+     * easily implement it.
+     * 
+     * Load the client public key certificate and private key from file and
+     * check whether the cert matches the key. We can use RSA certificates
+     * ("cert") and DSA certificates ("dcert"), both can be made available at
+     * the same time. The CA certificates for both are handled in the same
+     * setup already finished. Which one is used depends on the cipher
+     * negotiated (that is: the first cipher listed by the client which does
+     * match the server). A client with RSA only (e.g. Netscape) will use the
+     * RSA certificate only. A client with openssl-library will use RSA first
+     * if not especially changed in the cipher setup.
+     */
+    if ((*var_smtp_tls_cert_file != 0 || *var_smtp_tls_dcert_file != 0)
+       && tls_set_my_certificate_key_info(client_ctx,
+                                          var_smtp_tls_cert_file,
+                                          var_smtp_tls_key_file,
+                                          var_smtp_tls_dcert_file,
+                                          var_smtp_tls_dkey_file) < 0) {
+       SSL_CTX_free(client_ctx);               /* 200411 */
+       return (0);
+    }
+
+    /*
+     * According to the OpenSSL documentation, temporary RSA key is needed
+     * export ciphers are in use. We have to provide one, so well, we just do
+     * it.
+     */
+    SSL_CTX_set_tmp_rsa_callback(client_ctx, tls_tmp_rsa_cb);
+
+    /*
+     * Finally, the setup for the server certificate checking, done "by the
+     * book".
+     */
+    SSL_CTX_set_verify(client_ctx, verify_flags, client_verify_callback);
+
+    /*
+     * Initialize the session cache. In order to share cached sessions among
+     * multiple SMTP client processes, we use an external cache and set the
+     * internal cache size to a minimum value of 1.
+     */
+    SSL_CTX_sess_set_cache_size(client_ctx, 1);
+    SSL_CTX_set_timeout(client_ctx, var_smtp_tls_scache_timeout);
+
+    /*
+     * The session cache is implemented by the tlsmgr(8) process.
+     */
+    if (tls_mgr_policy(&cache_types) == TLS_MGR_STAT_OK
+       && (tls_client_cache = (cache_types & TLS_MGR_SCACHE_CLIENT)) != 0) {
+
+       /*
+        * OpenSSL does not use callbacks to load sessions from a client
+        * cache, so we must invoke that function directly. Apparently,
+        * OpenSSL does not provide a way to pass session names from here to
+        * call-back routines that do session lookup.
+        * 
+        * OpenSSL can, however, automatically save newly created sessions for
+        * us by callback (we create the session name in the call-back
+        * function).
+        * 
+        * Disable automatic clearing of cache entries, as the client process
+        * has limited lifetime anyway and we can call the cleanup routine
+        * directly.
+        */
+       SSL_CTX_set_session_cache_mode(client_ctx,
+                     SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_AUTO_CLEAR);
+       SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb);
+    }
+
+    /*
+     * Create a global index so that we can attach TLScontext information to
+     * SSL objects; this information is needed inside
+     * tls_verify_certificate_callback().
+     */
+    if (TLScontext_index < 0)
+       TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
+                                               NULL, NULL, NULL);
+
+    /*
+     * Create a global index so that we can attach peer name information to
+     * SSL_SESSION objects; the client session cache manager uses this to
+     * generate cache ID strings.
+     */
+    if (TLSpeername_index < 0)
+       TLSpeername_index = SSL_SESSION_get_ex_new_index(0,
+                                               "TLSpeername ex_data index",
+                                                        new_cache_id_func,
+                                                        dup_cache_id_func,
+                                                        free_cache_id_func);
+
+    return (client_ctx);
+}
+
+ /*
+  * This is the actual startup routine for the connection. We expect that the
+  * buffers are flushed and the "220 Ready to start TLS" was received by us,
+  * so that we can immediately start the TLS handshake process.
+  */
+TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout,
+                                      int enforce_peername,
+                                      const char *peername,
+                                      tls_info_t *tls_info)
+{
+    int     sts;
+    SSL_SESSION *session,
+           *old_session;
+    SSL_CIPHER *cipher;
+    X509   *peer;
+    int     verify_flags;
+    TLScontext_t *TLScontext;
+
+    if (var_smtp_tls_loglevel >= 1)
+       msg_info("setting up TLS connection to %s", peername);
+
+    /*
+     * Allocate a new TLScontext for the new connection and get an SSL
+     * structure. Add the location of TLScontext to the SSL to later retrieve
+     * the information inside the tls_verify_certificate_callback().
+     * 
+     * XXX Need a dedicated procedure for consistent initialization of all the
+     * fields in this structure.
+     */
+#define PEERNAME_SIZE sizeof(TLScontext->peername_save)
+
+    TLScontext = (TLScontext_t *) mymalloc(sizeof(TLScontext_t));
+    memset((char *) TLScontext, 0, sizeof(*TLScontext));
+    TLScontext->log_level = var_smtp_tls_loglevel;
+    strncpy(TLScontext->peername_save, peername, PEERNAME_SIZE - 1);
+    TLScontext->peername_save[PEERNAME_SIZE - 1] = 0;
+    (void) lowercase(TLScontext->peername_save);
+
+    if ((TLScontext->con = (SSL *) SSL_new(client_ctx)) == NULL) {
+       msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
+       tls_print_errors();
+       myfree((char *) TLScontext);
+       return (0);
+    }
+    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
+       msg_info("Could not set application data for 'TLScontext->con'");
+       tls_print_errors();
+       SSL_free(TLScontext->con);
+       myfree((char *) TLScontext);
+       return (0);
+    }
+
+    /*
+     * Set the verification parameters to be checked in
+     * tls_verify_certificate_callback().
+     */
+    if (enforce_peername) {
+       verify_flags = SSL_VERIFY_PEER;
+       TLScontext->enforce_verify_errors = 1;
+       TLScontext->enforce_CN = 1;
+       SSL_set_verify(TLScontext->con, verify_flags, client_verify_callback);
+    } else {
+       TLScontext->enforce_verify_errors = 0;
+       TLScontext->enforce_CN = 0;
+    }
+    TLScontext->hostname_matched = 0;
+
+    /*
+     * The TLS connection is realized by a BIO_pair, so obtain the pair.
+     * 
+     * XXX There is no need to make internal_bio a member of the TLScontext
+     * structure. It will be attached to TLScontext->con, and destroyed along
+     * with it. The network_bio, however, needs to be freed explicitly.
+     */
+    if (!BIO_new_bio_pair(&TLScontext->internal_bio, TLS_BIO_BUFSIZE,
+                         &TLScontext->network_bio, TLS_BIO_BUFSIZE)) {
+       msg_info("Could not obtain BIO_pair");
+       tls_print_errors();
+       SSL_free(TLScontext->con);
+       myfree((char *) TLScontext);
+       return (0);
+    }
+    old_session = NULL;
+
+    /*
+     * Try to load an existing session from the TLS session cache.
+     * 
+     * XXX To avoid memory leaks we must always call SSL_SESSION_free() after
+     * calling SSL_set_session(), regardless of whether or not the session
+     * will be reused.
+     */
+    if (tls_client_cache) {
+       old_session = load_clnt_session(peername, enforce_peername);
+       if (old_session) {
+           SSL_set_session(TLScontext->con, old_session);
+           SSL_SESSION_free(old_session);      /* 200411 */
+#if (OPENSSL_VERSION_NUMBER < 0x00906011L) || (OPENSSL_VERSION_NUMBER == 0x00907000L)
+
+           /*
+            * Ugly Hack: OpenSSL before 0.9.6a does not store the verify
+            * result in sessions for the client side. We modify the session
+            * directly which is version specific, but this bug is version
+            * specific, too.
+            * 
+            * READ: 0-09-06-01-1 = 0-9-6-a-beta1: all versions before beta1
+            * have this bug, it has been fixed during development of 0.9.6a.
+            * The development version of 0.9.7 can have this bug, too. It
+            * has been fixed on 2000/11/29.
+            */
+           SSL_set_verify_result(TLScontext->con, old_session->verify_result);
+#endif
+
+       }
+    }
+
+    /*
+     * Before really starting anything, try to seed the PRNG a little bit
+     * more.
+     */
+    tls_int_seed();
+    (void) tls_ext_seed(var_tls_daemon_rand_bytes);
+
+    /*
+     * Initialize the SSL connection to connect state. This should not be
+     * necessary anymore since 0.9.3, but the call is still in the library
+     * and maintaining compatibility never hurts.
+     */
+    SSL_set_connect_state(TLScontext->con);
+
+    /*
+     * Connect the SSL connection with the Postfix side of the BIO-pair for
+     * reading and writing.
+     */
+    SSL_set_bio(TLScontext->con, TLScontext->internal_bio,
+               TLScontext->internal_bio);
+
+    /*
+     * If the debug level selected is high enough, all of the data is dumped:
+     * 3 will dump the SSL negotiation, 4 will dump everything.
+     * 
+     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
+     * Well there is a BIO below the SSL routines that is automatically
+     * created for us, so we can use it for debugging purposes.
+     */
+    if (var_smtp_tls_loglevel >= 3)
+       BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
+
+    /*
+     * Start TLS negotiations. This process is a black box that invokes our
+     * call-backs for certificate verification.
+     * 
+     * Error handling: If the SSL handhake fails, we print out an error message
+     * and remove all TLS state concerning this session.
+     */
+    sts = tls_bio_connect(vstream_fileno(stream), timeout, TLScontext);
+    if (sts <= 0) {
+       msg_info("SSL_connect error to %s: %d", peername, sts);
+       tls_print_errors();
+       session = SSL_get_session(TLScontext->con);
+       if (session) {
+           SSL_CTX_remove_session(client_ctx, session);
+           if (var_smtp_tls_loglevel >= 2)
+               msg_info("SSL session removed");
+       }
+       SSL_free(TLScontext->con);
+       BIO_free(TLScontext->network_bio);      /* 200411 */
+       myfree((char *) TLScontext);
+       return (0);
+    }
+    if (var_smtp_tls_loglevel >= 3 && SSL_session_reused(TLScontext->con))
+       msg_info("Reusing old session");
+
+    /* Only loglevel==4 dumps everything */
+    if (var_smtp_tls_loglevel < 4)
+       BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
+
+    /*
+     * Let's see whether a peer certificate is available and what is the
+     * actual information. We want to save it for later use.
+     */
+    peer = SSL_get_peer_certificate(TLScontext->con);
+    if (peer != NULL) {
+       if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
+           tls_info->peer_verified = 1;
+
+       tls_info->hostname_matched = TLScontext->hostname_matched;
+
+       TLScontext->peer_CN[0] = '\0';
+       if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
+                                      NID_commonName, TLScontext->peer_CN,
+                                      sizeof(TLScontext->peer_CN))) {
+           msg_info("Could not parse server's subject CN");
+           tls_print_errors();
+       }
+       tls_info->peer_CN = TLScontext->peer_CN;
+
+       TLScontext->issuer_CN[0] = '\0';
+       if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
+                                      NID_commonName, TLScontext->issuer_CN,
+                                      sizeof(TLScontext->issuer_CN))) {
+           msg_info("Could not parse server's issuer CN");
+           tls_print_errors();
+       }
+       if (!TLScontext->issuer_CN[0]) {
+           /* No issuer CN field, use Organization instead */
+           if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
+                               NID_organizationName, TLScontext->issuer_CN,
+                                          sizeof(TLScontext->issuer_CN))) {
+               msg_info("Could not parse server's issuer Organization");
+               tls_print_errors();
+           }
+       }
+       tls_info->issuer_CN = TLScontext->issuer_CN;
+
+       if (var_smtp_tls_loglevel >= 1) {
+           if (tls_info->peer_verified)
+               msg_info("Verified: subject_CN=%s, issuer=%s",
+                        TLScontext->peer_CN, TLScontext->issuer_CN);
+           else
+               msg_info("Unverified: subject_CN=%s, issuer=%s",
+                        TLScontext->peer_CN, TLScontext->issuer_CN);
+       }
+       X509_free(peer);
+    }
+
+    /*
+     * Finally, collect information about protocol and cipher for logging
+     */
+    tls_info->protocol = SSL_get_version(TLScontext->con);
+    cipher = SSL_get_current_cipher(TLScontext->con);
+    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
+    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
+                                              &(tls_info->cipher_algbits));
+
+    /*
+     * The TLS engine is active. Switch to the tls_timed_read/write()
+     * functions and make the TLScontext available to those functions.
+     */
+    tls_stream_start(stream, TLScontext);
+
+    if (var_smtp_tls_loglevel >= 1)
+       msg_info("TLS connection established to %s: %s with cipher %s (%d/%d bits)",
+                peername, tls_info->protocol, tls_info->cipher_name,
+                tls_info->cipher_usebits, tls_info->cipher_algbits);
+
+    tls_int_seed();
+
+    return (TLScontext);
+}
+
+#endif                                 /* USE_TLS */
diff --git a/postfix/src/tls/tls_dh.c b/postfix/src/tls/tls_dh.c
new file mode 100644 (file)
index 0000000..5752333
--- /dev/null
@@ -0,0 +1,233 @@
+/*++
+/* NAME
+/*     tls_dh
+/* SUMMARY
+/*     Diffie-Hellman parameter support
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     void    tls_set_dh_1024_from_file(path)
+/*     const char *path;
+/*
+/*     void    tls_set_dh_512_from_file(path)
+/*     const char *path;
+/*
+/*     DH      *tls_tmp_dh_cb(ssl, export, keylength)
+/*     SSL     *ssl; /* unused */
+/*     int     export;
+/*     int     keylength;
+/* DESCRIPTION
+/*     This module maintains parameters for Diffie-Hellman key generation.
+/*
+/*     tls_tmp_dh_cb() is a call-back routine for the
+/*     SSL_CTX_set_tmp_dh_callback() function.
+/*
+/*     tls_set_dh_1024_from_file() and tls_set_dh_512_from_file()
+/*     override the compiled-in DH parameters with those specified
+/*     in the named files. The file format is as expected by the
+/*     PEM_read_DHparams() routine.
+/* DIAGNOSTICS
+/*      In case of error, tls_set_dh_1024_from_file() and
+/*     tls_set_dh_512_from_file() log a warning and ignore the request.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+#include <stdio.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+ /*
+  * Compiled-in DH parameters. These are used when no parameters are
+  * explicitly loaded from file.
+  * 
+  * XXX What is the origin of these parameters?
+  */
+static unsigned char dh512_p[] = {
+    0x88, 0x3F, 0x00, 0xAF, 0xFC, 0x0C, 0x8A, 0xB8, 0x35, 0xCD, 0xE5, 0xC2,
+    0x0F, 0x55, 0xDF, 0x06, 0x3F, 0x16, 0x07, 0xBF, 0xCE, 0x13, 0x35, 0xE4,
+    0x1C, 0x1E, 0x03, 0xF3, 0xAB, 0x17, 0xF6, 0x63, 0x50, 0x63, 0x67, 0x3E,
+    0x10, 0xD7, 0x3E, 0xB4, 0xEB, 0x46, 0x8C, 0x40, 0x50, 0xE6, 0x91, 0xA5,
+    0x6E, 0x01, 0x45, 0xDE, 0xC9, 0xB1, 0x1F, 0x64, 0x54, 0xFA, 0xD9, 0xAB,
+    0x4F, 0x70, 0xBA, 0x5B,
+};
+static unsigned char dh512_g[] = {
+    0x02,
+};
+
+static unsigned char dh1024_p[] = {
+    0xB0, 0xFE, 0xB4, 0xCF, 0xD4, 0x55, 0x07, 0xE7, 0xCC, 0x88, 0x59, 0x0D,
+    0x17, 0x26, 0xC5, 0x0C, 0xA5, 0x4A, 0x92, 0x23, 0x81, 0x78, 0xDA, 0x88,
+    0xAA, 0x4C, 0x13, 0x06, 0xBF, 0x5D, 0x2F, 0x9E, 0xBC, 0x96, 0xB8, 0x51,
+    0x00, 0x9D, 0x0C, 0x0D, 0x75, 0xAD, 0xFD, 0x3B, 0xB1, 0x7E, 0x71, 0x4F,
+    0x3F, 0x91, 0x54, 0x14, 0x44, 0xB8, 0x30, 0x25, 0x1C, 0xEB, 0xDF, 0x72,
+    0x9C, 0x4C, 0xF1, 0x89, 0x0D, 0x68, 0x3F, 0x94, 0x8E, 0xA4, 0xFB, 0x76,
+    0x89, 0x18, 0xB2, 0x91, 0x16, 0x90, 0x01, 0x99, 0x66, 0x8C, 0x53, 0x81,
+    0x4E, 0x27, 0x3D, 0x99, 0xE7, 0x5A, 0x7A, 0xAF, 0xD5, 0xEC, 0xE2, 0x7E,
+    0xFA, 0xED, 0x01, 0x18, 0xC2, 0x78, 0x25, 0x59, 0x06, 0x5C, 0x39, 0xF6,
+    0xCD, 0x49, 0x54, 0xAF, 0xC1, 0xB1, 0xEA, 0x4A, 0xF9, 0x53, 0xD0, 0xDF,
+    0x6D, 0xAF, 0xD4, 0x93, 0xE7, 0xBA, 0xAE, 0x9B,
+};
+
+static unsigned char dh1024_g[] = {
+    0x02,
+};
+
+ /*
+  * Cached results.
+  */
+static DH *dh_1024 = 0;
+static DH *dh_512 = 0;
+
+/* tls_set_dh_1024_from_file - set Diffie-Hellman parameters from file */
+
+void    tls_set_dh_1024_from_file(const char *path)
+{
+    FILE   *paramfile;
+
+    if ((paramfile = fopen(path, "r")) != 0) {
+       dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
+       if (dh_1024 == 0) {
+           msg_warn("cannot load 1024-bit DH parameters from file %s"
+                    " -- using compiled-in defaults", path);
+           tls_print_errors();
+       }
+       (void) fclose(paramfile);               /* 200411 */
+    } else {
+       msg_warn("cannot load 1024-bit DH parameters from file %s: %m"
+                " -- using compiled-in defaults", path);
+    }
+}
+
+/* tls_set_dh_512_from_file - set Diffie-Hellman parameters from file */
+
+void    tls_set_dh_512_from_file(const char *path)
+{
+    FILE   *paramfile;
+
+    if ((paramfile = fopen(path, "r")) != 0) {
+       dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
+       if (dh_512 == 0) {
+           msg_warn("cannot load 512-bit DH parameters from file %s"
+                    " -- using compiled-in defaults", path);
+           tls_print_errors();
+       }
+       (void) fclose(paramfile);               /* 200411 */
+    } else {
+       msg_warn("cannot load 512-bit DH parameters from file %s: %m"
+                " -- using compiled-in defaults", path);
+    }
+}
+
+/* tls_get_dh_512 - get 512-bit DH parameters, compiled-in or from file */
+
+static DH *tls_get_dh_512(void)
+{
+    DH     *dh;
+
+    if (dh_512 == 0) {
+       /* Use the compiled-in parameters. */
+       if ((dh = DH_new()) == 0) {
+           msg_warn("cannot create DH parameter set: %m");     /* 200411 */
+           return (0);
+       }
+       dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), (BIGNUM *) 0);
+       dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), (BIGNUM *) 0);
+       if ((dh->p == 0) || (dh->g == 0)) {
+           msg_warn("cannot load compiled-in DH parameters");  /* 200411 */
+           DH_free(dh);                        /* 200411 */
+           return (0);
+       } else
+           dh_512 = dh;
+    }
+    return (dh_512);
+}
+
+/* tls_get_dh_1024 - get 1024-bit DH parameters, compiled-in or from file */
+
+static DH *tls_get_dh_1024(void)
+{
+    DH     *dh;
+
+    if (dh_1024 == 0) {
+       /* Use the compiled-in parameters. */
+       if ((dh = DH_new()) == 0) {
+           msg_warn("cannot create DH parameter set: %m");     /* 200411 */
+           return (0);
+       }
+       dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), (BIGNUM *) 0);
+       dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), (BIGNUM *) 0);
+       if ((dh->p == 0) || (dh->g == 0)) {
+           msg_warn("cannot load compiled-in DH parameters");  /* 200411 */
+           DH_free(dh);                        /* 200411 */
+           return (0);
+       } else
+           dh_1024 = dh;
+    }
+    return (dh_1024);
+}
+
+/* tls_tmp_dh_cb - call-back for Diffie-Hellman parameters */
+
+DH     *tls_tmp_dh_cb(SSL *unused_ssl, int export, int keylength)
+{
+    DH     *dh_tmp;
+
+    if (export) {
+       if (keylength == 512)
+           dh_tmp = tls_get_dh_512();          /* export cipher */
+       else if (keylength == 1024)
+           dh_tmp = tls_get_dh_1024();         /* normal */
+       else
+           dh_tmp = tls_get_dh_1024();         /* cheat */
+    } else {
+       dh_tmp = tls_get_dh_1024();             /* sign-only certificate */
+    }
+    return (dh_tmp);
+}
+
+#ifdef TEST
+
+int main(int unused_argc, char **unused_argv)
+{
+    tls_tmp_dh_cb(0, 1, 512);
+    tls_tmp_dh_cb(0, 1, 1024);
+    tls_tmp_dh_cb(0, 1, 2048);
+    tls_tmp_dh_cb(0, 0, 512);
+}
+
+#endif
+
+#endif
diff --git a/postfix/src/tls/tls_mgr.c b/postfix/src/tls/tls_mgr.c
new file mode 100644 (file)
index 0000000..3572b12
--- /dev/null
@@ -0,0 +1,408 @@
+/*++
+/* NAME
+/*     tls_mgr 3
+/* SUMMARY
+/*     tlsmgr client interface
+/* SYNOPSIS
+/*     #include <tls_mgr.h>
+/*
+/*     int     tls_mgr_seed(buf, len)
+/*     VSTRING *buf;
+/*     int     len;
+/*
+/*     int     tls_mgr_policy(cache_types)
+/*     int     *cache_types;
+/*
+/*     int     tls_mgr_update(cache_type, cache_id,
+/*                             openssl_version, flags, buf, len)
+/*     int     cache_type;
+/*     const char *cache_id;
+/*     long    openssl_version;
+/*     int     flags;
+/*     const char *buf;
+/*     int     len;
+/*
+/*     int     tls_mgr_lookup(cache_type, cache_id,
+/*                             openssl_version, flags, buf)
+/*     int     cache_type;
+/*     const char *cache_id;
+/*     long    openssl_version;
+/*     int     flags;
+/*     VSTRING *buf;
+/*
+/*     int     tls_mgr_delete(cache_type, cache_id)
+/*     int     cache_type;
+/*     const char *cache_id;
+/* DESCRIPTION
+/*     These routines communicate with the tlsmgr(8) server for
+/*     entropy and session cache management. Since these are
+/*     non-critical services, requests are allowed to fail without
+/*     disrupting Postfix.
+/*
+/*     tls_mgr_seed() requests entropy from the tlsmgr(8)
+/*     Pseudo Random Number Generator (PRNG) pool.
+/*
+/*     tls_mgr_policy() requests the session caching policy.
+/*
+/*     tls_mgr_lookup() loads the specified session from
+/*     the specified session cache.
+/*
+/*     tls_mgr_update() saves the specified session to
+/*     the specified session cache.
+/*
+/*     tls_mgr_delete() removes specified session from
+/*     the specified session cache.
+/*
+/*     Arguments
+/* .IP cache_types
+/*     The bit-wise OR of zero or more of the following:
+/* .RS
+/* .IP TLS_MGR_SCACHE_CLIENT
+/*     Session caching is enabled for SMTP client sessions.
+/* .IP TLS_MGR_SCACHE_SERVER
+/*     Session caching is enabled for SMTP server sessions.
+/* .RE
+/* .IP cache_type
+/*     One of TLS_MGR_SCACHE_CLIENT or TLS_MGR_SCACHE_SERVER (see above).
+/* .IP cache_id
+/*     The session cache lookup key.
+/* .IP openssl_version
+/*     The OpenSSL version. Sessions saved by the wrong OpenSSL version are
+/*     deleted, to avoid compatibility problems.
+/* .IP flags
+/*     Flags that must be set in the retrieved cache entry; it not,
+/*     the cache entry is deleted.
+/* .IP buf
+/*     The result or input buffer.
+/* .IP len
+/*     The length of the input buffer, or the amount of data requested.
+/* DIAGNOSTICS
+/*     All client functions return one of the following status codes:
+/* .IP TLS_MGR_STAT_OK
+/*      The request completed, and the requested operation was
+/*     successful (for example, the requested session was found,
+/*     or the specified session was saved or removed).
+/* .IP TLS_MGR_STAT_ERR
+/*      The request completed, but the requested operation failed
+/*     (for example, the requested object was not found or the
+/*     specified session was not saved or removed).
+/* .IP TLS_MGR_STAT_FAIL
+/*      The request could not complete (the client could not
+/*     communicate with the tlsmgr(8) server).
+/* SEE ALSO
+/*     tlsmgr(8) TLS session and PRNG management
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <attr.h>
+#include <attr_clnt.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <tls_mgr.h>
+
+/* Application-specific. */
+
+static ATTR_CLNT *tls_mgr;
+
+/* tls_mgr_open - create client handle */
+
+static void tls_mgr_open(void)
+{
+
+    /*
+     * Sanity check.
+     */
+    if (tls_mgr != 0)
+       msg_panic("tls_mgr_open: multiple initialization");
+
+    /*
+     * Use whatever IPC is preferred for internal use: UNIX-domain sockets or
+     * Solaris streams.
+     */
+#ifndef VAR_TLS_MGR_SERVICE
+    tls_mgr = attr_clnt_create("local:" TLS_MGR_CLASS "/" TLS_MGR_SERVICE,
+                              var_ipc_timeout, var_ipc_idle_limit,
+                              var_ipc_ttl_limit);
+#else
+    tls_mgr = attr_clnt_create(var_tlsmgr_service, var_ipc_timeout,
+                              var_ipc_idle_limit, var_ipc_ttl_limit);
+#endif
+    attr_clnt_control(tls_mgr,
+                     ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
+                     ATTR_CLNT_CTL_END);
+}
+
+/* tls_mgr_seed - request PRNG seed */
+
+int     tls_mgr_seed(VSTRING *buf, int len)
+{
+    int     status;
+
+    /*
+     * Create the tlsmgr client handle.
+     */
+    if (tls_mgr == 0)
+       tls_mgr_open();
+
+    /*
+     * Request seed.
+     */
+    if (attr_clnt_request(tls_mgr,
+                         ATTR_FLAG_NONE,       /* Request attributes */
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_SEED,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_SIZE, len,
+                         ATTR_TYPE_END,
+                         ATTR_FLAG_MISSING,    /* Reply attributes */
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status,
+                         ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED, buf,
+                         ATTR_TYPE_END) != 2)
+       status = TLS_MGR_STAT_FAIL;
+    return (status);
+}
+
+/* tls_mgr_policy - request caching policy */
+
+int     tls_mgr_policy(int *policy)
+{
+    int     status;
+
+    /*
+     * Create the tlsmgr client handle.
+     */
+    if (tls_mgr == 0)
+       tls_mgr_open();
+
+    /*
+     * Request policy.
+     */
+    if (attr_clnt_request(tls_mgr,
+                         ATTR_FLAG_NONE,       /* Request attributes */
+                       ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_POLICY,
+                         ATTR_TYPE_END,
+                         ATTR_FLAG_MISSING,    /* Reply attributes */
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_POLICY, policy,
+                         ATTR_TYPE_END) != 2)
+       status = TLS_MGR_STAT_FAIL;
+    return (status);
+}
+
+/* tls_mgr_lookup - request cached session */
+
+int     tls_mgr_lookup(int cache_type, const char *cache_id,
+                              long openssl_vsn, int flags, VSTRING *buf)
+{
+    int     status;
+
+    /*
+     * Create the tlsmgr client handle.
+     */
+    if (tls_mgr == 0)
+       tls_mgr_open();
+
+    /*
+     * Send the request and receive the reply.
+     */
+    if (attr_clnt_request(tls_mgr,
+                         ATTR_FLAG_NONE,       /* Request */
+                       ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_LOOKUP,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_LONG, TLS_MGR_ATTR_VERSION, openssl_vsn,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_FLAGS, flags,
+                         ATTR_TYPE_END,
+                         ATTR_FLAG_MISSING,    /* Reply */
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status,
+                         ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buf,
+                         ATTR_TYPE_END) != 2)
+       status = TLS_MGR_STAT_FAIL;
+    return (status);
+}
+
+/* tls_mgr_update - save session to cache */
+
+int     tls_mgr_update(int cache_type, const char *cache_id,
+                              long openssl_vsn, int flags,
+                              const char *buf, int len)
+{
+    int     status;
+
+    /*
+     * Create the tlsmgr client handle.
+     */
+    if (tls_mgr == 0)
+       tls_mgr_open();
+
+    /*
+     * Send the request and receive the reply.
+     */
+    if (attr_clnt_request(tls_mgr,
+                         ATTR_FLAG_NONE,       /* Request */
+                       ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_UPDATE,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_LONG, TLS_MGR_ATTR_VERSION, openssl_vsn,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_FLAGS, flags,
+                         ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, len, buf,
+                         ATTR_TYPE_END,
+                         ATTR_FLAG_MISSING,    /* Reply */
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status,
+                         ATTR_TYPE_END) != 1)
+       status = TLS_MGR_STAT_FAIL;
+    return (status);
+}
+
+/* tls_mgr_delete - remove cached session */
+
+int     tls_mgr_delete(int cache_type, const char *cache_id)
+{
+    int     status;
+
+    /*
+     * Create the tlsmgr client handle.
+     */
+    if (tls_mgr == 0)
+       tls_mgr_open();
+
+    /*
+     * Send the request and receive the reply.
+     */
+    if (attr_clnt_request(tls_mgr,
+                         ATTR_FLAG_NONE,       /* Request */
+                       ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_DELETE,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_END,
+                         ATTR_FLAG_MISSING,    /* Reply */
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_STATUS, &status,
+                         ATTR_TYPE_END) != 1)
+       status = TLS_MGR_STAT_FAIL;
+    return (status);
+}
+
+#ifdef TEST
+
+/* System library. */
+
+#include <stdlib.h>
+
+/* Utility library. */
+
+#include <argv.h>
+#include <msg_vstream.h>
+#include <vstring_vstream.h>
+#include <hex_code.h>
+
+/* Global library. */
+
+#include <config.h>
+
+/* Application-specific. */
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+int     main(int unused_ac, char **av)
+{
+    VSTRING *inbuf = vstring_alloc(10);
+    int     status;
+    ARGV   *argv = 0;
+
+    msg_vstream_init(av[0], VSTREAM_ERR);
+
+    msg_verbose = 3;
+
+    mail_conf_read();
+    msg_info("using config files in %s", var_config_dir);
+
+    if (chdir(var_queue_dir) < 0)
+       msg_fatal("chdir %s: %m", var_queue_dir);
+
+    while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
+       argv = argv_split(STR(inbuf), " \t\r\n");
+       if (argv->argc == 0)
+           continue;
+
+#define COMMAND(argv, str, len) \
+    (strcasecmp(argv->argv[0], str) == 0 && argv->argc == len)
+
+       if (COMMAND(argv, "policy", 1)) {
+           int     cache_types;
+
+           status = tls_mgr_policy(&cache_types);
+           vstream_printf("status=%d policy=0x%x\n", status, cache_types);
+       } else if (COMMAND(argv, "seed", 2)) {
+           VSTRING *buf = vstring_alloc(10);
+           VSTRING *hex = vstring_alloc(10);
+           int     len = atoi(argv->argv[1]);
+
+           status = tls_mgr_seed(buf, len);
+           hex_encode(hex, STR(buf), LEN(buf));
+           vstream_printf("status=%d seed=%s\n", status, STR(hex));
+           vstring_free(hex);
+           vstring_free(buf);
+       } else if (COMMAND(argv, "lookup", 5)) {
+           VSTRING *buf = vstring_alloc(10);
+           int     cache_type = atoi(argv->argv[1]);
+           long    openssl_vsn = atol(argv->argv[3]);
+           int     flags = atoi(argv->argv[4]);
+
+           status = tls_mgr_lookup(cache_type, argv->argv[2],
+                                   openssl_vsn, flags, buf);
+           vstream_printf("status=%d session=%.*s\n",
+                          status, LEN(buf), STR(buf));
+       } else if (COMMAND(argv, "update", 6)) {
+           int     cache_type = atoi(argv->argv[1]);
+           long    openssl_vsn = atol(argv->argv[3]);
+           int     flags = atoi(argv->argv[4]);
+
+           status = tls_mgr_update(cache_type, argv->argv[2],
+                                   openssl_vsn, flags,
+                                   argv->argv[5], strlen(argv->argv[5]));
+           vstream_printf("status=%d\n", status);
+       } else if (COMMAND(argv, "delete", 3)) {
+           int     cache_type = atoi(argv->argv[1]);
+
+           status = tls_mgr_delete(cache_type, argv->argv[2]);
+           vstream_printf("status=%d\n", status);
+       } else {
+           vstream_printf("usage:\n"
+                          "seed byte_count\n"
+                          "policy\n"
+                       "lookup cache_type cache_id openssl_version flags\n"
+               "update cache_type cache_id openssl_version flags session\n"
+                          "delete cache_type cache_id\n");
+       }
+       vstream_fflush(VSTREAM_OUT);
+    }
+    if (argv)
+       argv_free(argv);
+
+    vstring_free(inbuf);
+}
+
+#endif                                 /* TEST */
+
+#endif                                 /* USE_TLS */
diff --git a/postfix/src/tls/tls_mgr.h b/postfix/src/tls/tls_mgr.h
new file mode 100644 (file)
index 0000000..3b108a4
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _TLS_MGR_CLNT_H_INCLUDED_
+#define _TLS_MGR_CLNT_H_INCLUDED_
+
+/*++
+/* NAME
+/*     tls_mgr 3h
+/* SUMMARY
+/*     tlsmgr client interface
+/* SYNOPSIS
+/*     #include <tls_mgr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * TLS manager protocol.
+  */
+#define TLS_MGR_SERVICE                "tlsmgr"
+#define TLS_MGR_CLASS          "private"
+
+#define TLS_MGR_ATTR_REQ       "request"
+#define TLS_MGR_REQ_SEED       "seed"
+#define TLS_MGR_REQ_POLICY     "policy"
+#define TLS_MGR_REQ_LOOKUP     "lookup"
+#define TLS_MGR_REQ_UPDATE     "update"
+#define TLS_MGR_REQ_DELETE     "delete"
+#define TLS_MGR_ATTR_POLICY    "policy"
+#define TLS_MGR_ATTR_CACHE_TYPE        "cache_type"
+#define TLS_MGR_ATTR_SEED      "seed"
+#define TLS_MGR_ATTR_CACHE_ID  "cache_id"
+#define TLS_MGR_ATTR_VERSION   "version"
+#define TLS_MGR_ATTR_FLAGS     "flags"
+#define TLS_MGR_ATTR_SESSION   "session"
+#define TLS_MGR_ATTR_SIZE      "size"
+#define TLS_MGR_ATTR_STATUS    "status"
+#define TLS_MGR_ATTR_FLAGS     "flags"
+
+ /*
+  * TLS manager request status codes.
+  */
+#define TLS_MGR_STAT_OK                0       /* success */
+#define TLS_MGR_STAT_ERR       (-1)    /* object not found */
+#define TLS_MGR_STAT_FAIL      (-2)    /* protocol error */
+
+ /*
+  * Are we talking about the client or server cache?
+  */
+#define TLS_MGR_SCACHE_CLIENT  (1<<0)
+#define TLS_MGR_SCACHE_SERVER  (1<<1)
+
+ /*
+  * Functional interface.
+  */
+extern int tls_mgr_seed(VSTRING *, int);
+extern int tls_mgr_policy(int *);
+extern int tls_mgr_lookup(int, const char *, long, int, VSTRING *);
+extern int tls_mgr_update(int, const char *, long, int, const char *, int);
+extern int tls_mgr_delete(int, const char *);
+
+#define TLS_MGR_NO_FLAGS       0
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/tls/tls_misc.c b/postfix/src/tls/tls_misc.c
new file mode 100644 (file)
index 0000000..c17c87c
--- /dev/null
@@ -0,0 +1,231 @@
+/*++
+/* NAME
+/*     tls_misc 3
+/* SUMMARY
+/*     miscellaneous TLS support routines
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     void    tls_print_errors()
+/*
+/*     void    tls_info_callback(ssl, where, ret)
+/*     const SSL *ssl; /* unused */
+/*     int     where;
+/*     int     ret;
+/*
+/*     long    tls_bio_dump_cb(bio, cmd, argp, argi, argl, ret)
+/*     BIO     *bio;
+/*     int     cmd;
+/*     const char *argp;
+/*     int     argi;
+/*     long    argl; /* unused */
+/*     long    ret;
+/* DESCRIPTION
+/*     This module implements routines that support the TLS client
+/*     and server internals.
+/*
+/*     tls_print_errors() queries the OpenSSL error stack,
+/*     logs the error messages, and clears the error stack.
+/*
+/*     tls_info_callback() is a call-back routine for the
+/*     SSL_CTX_set_info_callback() routine. It logs SSL events
+/*     to the Postfix logfile.
+/*
+/*     tls_bio_dump_cb() is a call-back routine for the
+/*     BIO_set_callback() routine. It logs SSL content to the
+/*     Postfix logfile.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <ctype.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <vstream.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+ /*
+  * Indices to attach our own information to SSL and to SSL_SESSION objects,
+  * so that it can be accessed by call-back routines.
+  */
+int     TLScontext_index = -1;
+int     TLSpeername_index = -1;
+
+/* tls_print_errors - print and clear the error stack */
+
+void    tls_print_errors(void)
+{
+    unsigned long err;
+    char    buffer[1024];              /* XXX */
+    const char *file;
+    const char *data;
+    int     line;
+    int     flags;
+    unsigned long thread;
+
+    thread = CRYPTO_thread_id();
+    while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
+       ERR_error_string_n(err, buffer, sizeof(buffer));
+       if (flags & ERR_TXT_STRING)
+           msg_warn("TLS library problem: %lu:%s:%s:%d:%s:",
+                    thread, buffer, file, line, data);
+       else
+           msg_warn("TLS library problem: %lu:%s:%s:%d:",
+                    thread, buffer, file, line);
+    }
+}
+
+/* tls_info_callback - callback for logging SSL events via Postfix */
+
+void    tls_info_callback(const SSL *s, int where, int ret)
+{
+    char   *str;
+    int     w;
+
+    /* Adapted from OpenSSL apps/s_cb.c. */
+
+    w = where & ~SSL_ST_MASK;
+
+    if (w & SSL_ST_CONNECT)
+       str = "SSL_connect";
+    else if (w & SSL_ST_ACCEPT)
+       str = "SSL_accept";
+    else
+       str = "unknown";
+
+    if (where & SSL_CB_LOOP) {
+       msg_info("%s:%s", str, SSL_state_string_long(s));
+    } else if (where & SSL_CB_ALERT) {
+       str = (where & SSL_CB_READ) ? "read" : "write";
+       if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
+           msg_info("SSL3 alert %s:%s:%s", str,
+                    SSL_alert_type_string_long(ret),
+                    SSL_alert_desc_string_long(ret));
+    } else if (where & SSL_CB_EXIT) {
+       if (ret == 0)
+           msg_info("%s:failed in %s",
+                    str, SSL_state_string_long(s));
+       else if (ret < 0) {
+           msg_info("%s:error in %s",
+                    str, SSL_state_string_long(s));
+       }
+    }
+}
+
+ /*
+  * taken from OpenSSL crypto/bio/b_dump.c.
+  * 
+  * Modified to save a lot of strcpy and strcat by Matti Aarnio.
+  * 
+  * Rewritten by Wietse to elimate fixed-size stack buffer, array index
+  * multiplication and division, sprintf() and strcpy(), and lots of strlen()
+  * calls. We could make it a little faster by using a fixed-size stack-based
+  * buffer.
+  * 
+  * 200412 - use %lx to print pointers, after casting them to unsigned long.
+  */
+
+#define TRUNCATE_SPACE_NULL
+#define DUMP_WIDTH     16
+#define VERT_SPLIT     7
+
+static void tls_dump_buffer(const unsigned char *start, int len)
+{
+    VSTRING *buf = vstring_alloc(100);
+    const unsigned char *last = start + len - 1;
+    const unsigned char *row;
+    const unsigned char *col;
+    int     ch;
+
+#ifdef TRUNCATE_SPACE_NULL
+    while (last >= start && (*last == ' ' || *last == 0))
+       last--;
+#endif
+
+    for (row = start; row <= last; row += DUMP_WIDTH) {
+       VSTRING_RESET(buf);
+       vstring_sprintf(buf, "%04lx ", (unsigned long) (row - start));
+       for (col = row; col < row + DUMP_WIDTH; col++) {
+           if (col > last) {
+               vstring_strcat(buf, "   ");
+           } else {
+               ch = *col;
+               vstring_sprintf_append(buf, "%02x%c",
+                                  ch, col - row == VERT_SPLIT ? '|' : ' ');
+           }
+       }
+       VSTRING_ADDCH(buf, ' ');
+       for (col = row; col < row + DUMP_WIDTH; col++) {
+           if (col > last)
+               break;
+           ch = *col;
+           if (!ISPRINT(ch))
+               ch = '.';
+           VSTRING_ADDCH(buf, ch);
+           if (col - row == VERT_SPLIT)
+               VSTRING_ADDCH(buf, ' ');
+       }
+       VSTRING_TERMINATE(buf);
+       msg_info("%s", vstring_str(buf));
+    }
+#ifdef TRUNCATE_SPACE_NULL
+    if ((last + 1) - start < len)
+       msg_info("%04lx - <SPACES/NULLS>",
+                (unsigned long) ((last + 1) - start));
+#endif
+    vstring_free(buf);
+}
+
+/* taken from OpenSSL apps/s_cb.c */
+
+long    tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
+                               long unused_argl, long ret)
+{
+    if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
+       msg_info("read from %08lX [%08lX] (%d bytes => %ld (0x%lX))",
+                (unsigned long) bio, (unsigned long) argp, argi,
+                ret, (unsigned long) ret);
+       tls_dump_buffer((unsigned char *) argp, (int) ret);
+    } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
+       msg_info("write to %08lX [%08lX] (%d bytes => %ld (0x%lX))",
+                (unsigned long) bio, (unsigned long) argp, argi,
+                ret, (unsigned long) ret);
+       tls_dump_buffer((unsigned char *) argp, (int) ret);
+    }
+    return (ret);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_prng.h b/postfix/src/tls/tls_prng.h
new file mode 100644 (file)
index 0000000..df7fad9
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _TLS_PRNG_SRC_H_INCLUDED_
+#define _TLS_PRNG_SRC_H_INCLUDED_
+
+/*++
+/* NAME
+/*     tls_prng_src 3h
+/* SUMMARY
+/*     OpenSSL PRNG maintenance routines
+/* SYNOPSIS
+/*     #include <tls_prng_src.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * External interface.
+  */
+typedef struct TLS_PRNG_SRC {
+    int     fd;                                /* file handle */
+    char   *name;                      /* resource name */
+    int     timeout;                   /* time limit of applicable */
+} TLS_PRNG_SRC;
+
+extern TLS_PRNG_SRC *tls_prng_egd_open(const char *, int);
+extern ssize_t tls_prng_egd_read(TLS_PRNG_SRC *, size_t);
+extern int tls_prng_egd_close(TLS_PRNG_SRC *);
+
+extern TLS_PRNG_SRC *tls_prng_dev_open(const char *, int);
+extern ssize_t tls_prng_dev_read(TLS_PRNG_SRC *, size_t);
+extern int tls_prng_dev_close(TLS_PRNG_SRC *);
+
+extern TLS_PRNG_SRC *tls_prng_file_open(const char *, int);
+extern ssize_t tls_prng_file_read(TLS_PRNG_SRC *, size_t);
+extern int tls_prng_file_close(TLS_PRNG_SRC *);
+
+extern TLS_PRNG_SRC *tls_prng_exch_open(const char *);
+extern void tls_prng_exch_update(TLS_PRNG_SRC *);
+extern void tls_prng_exch_close(TLS_PRNG_SRC *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/tls/tls_prng_dev.c b/postfix/src/tls/tls_prng_dev.c
new file mode 100644 (file)
index 0000000..4c532cc
--- /dev/null
@@ -0,0 +1,155 @@
+/*++
+/* NAME
+/*     tls_prng_dev 3
+/* SUMMARY
+/*     seed OpenSSL PRNG from entropy device
+/* SYNOPSIS
+/*     #include <tls_prng_src.h>
+/*
+/*     TLS_PRNG_SRC *tls_prng_dev_open(name, timeout)
+/*     const char *name;
+/*     int     timeout;
+/*
+/*     ssize_t tls_prng_dev_read(dev, length)
+/*     TLS_PRNG_SRC *dev;
+/*     size_t length;
+/*
+/*     int     tls_prng_dev_close(dev)
+/*     TLS_PRNG_SRC *dev;
+/* DESCRIPTION
+/*     tls_prng_dev_open() opens the specified entropy device
+/*     and returns a handle that should be used with all subsequent
+/*     access.
+/*
+/*     tls_prng_dev_read() reads the requested number of bytes from
+/*     the entropy device and updates the OpenSSL PRNG.
+/*
+/*     tls_prng_dev_close() closes the specified entropy device 
+/*     and releases memory that was allocated for the handle.
+/*
+/*     Arguments:
+/* .IP name
+/*     The pathname of the entropy device.
+/* .IP length
+/*     The number of bytes to read from the entropy device.
+/*     Request lengths will be truncated at 255 bytes.
+/* .IP timeout
+/*     Time limit on individual I/O operations.
+/* DIAGNOSTICS
+/*     tls_prng_dev_open() returns a null pointer on error.
+/*
+/*     tls_prng_dev_read() returns -1 on error, the number
+/*     of bytes received on success.
+/*
+/*     tls_prng_dev_close() returns -1 on error, 0 on success.
+/*
+/*     In all cases the errno variable indicates the type of error.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 0xff
+#endif
+
+/* OpenSSL library. */
+
+#ifdef USE_TLS
+#include <openssl/rand.h>              /* For the PRNG */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <connect.h>
+#include <iostuff.h>
+
+/* TLS library. */
+
+#include <tls_prng.h>
+
+/* tls_prng_dev_open - open entropy device */
+
+TLS_PRNG_SRC *tls_prng_dev_open(const char *name, int timeout)
+{
+    const char *myname = "tls_prng_dev_open";
+    TLS_PRNG_SRC *dev;
+    int     fd;
+
+    if ((fd = open(name, O_RDONLY, 0)) < 0) {
+       if (msg_verbose)
+           msg_info("%s: cannot open entropy device %s: %m", myname, name);
+       return (0);
+    } else {
+       dev = (TLS_PRNG_SRC *) mymalloc(sizeof(*dev));
+       dev->fd = fd;
+       dev->name = mystrdup(name);
+       dev->timeout = timeout;
+       if (msg_verbose)
+           msg_info("%s: opened entropy device %s", myname, name);
+       return (dev);
+    }
+}
+
+/* tls_prng_dev_read - update internal PRNG from device */
+
+ssize_t tls_prng_dev_read(TLS_PRNG_SRC *dev, size_t len)
+{
+    const char *myname = "tls_prng_dev_read";
+    unsigned char buffer[UCHAR_MAX];
+    ssize_t count;
+    size_t  rand_bytes;
+
+    if (len <= 0)
+       msg_panic("%s: bad read length: %ld", myname, (long) len);
+
+    if (len > sizeof(buffer))
+       rand_bytes = sizeof(buffer);
+    else
+       rand_bytes = len;
+    errno = 0;
+    count = timed_read(dev->fd, buffer, rand_bytes, dev->timeout, (void *) 0);
+    if (count > 0) {
+       if (msg_verbose)
+           msg_info("%s: read %ld bytes from entropy device %s",
+                    myname, (long) count, dev->name);
+       RAND_seed(buffer, count);
+    } else {
+       if (msg_verbose)
+           msg_info("%s: cannot read %ld bytes from entropy device %s: %m",
+                    myname, (long) rand_bytes, dev->name);
+    }
+    return (count);
+}
+
+/* tls_prng_dev_close - disconnect from EGD server */
+
+int     tls_prng_dev_close(TLS_PRNG_SRC *dev)
+{
+    const char *myname = "tls_prng_dev_close";
+    int     err;
+
+    if (msg_verbose)
+       msg_info("%s: close entropy device %s", myname, dev->name);
+    err = close(dev->fd);
+    myfree(dev->name);
+    myfree((char *) dev);
+    return (err);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_prng_egd.c b/postfix/src/tls/tls_prng_egd.c
new file mode 100644 (file)
index 0000000..3866475
--- /dev/null
@@ -0,0 +1,166 @@
+/*++
+/* NAME
+/*     tls_prng_egd 3
+/* SUMMARY
+/*     seed OpenSSL PRNG from EGD server
+/* SYNOPSIS
+/*     #include <tls_prng_src.h>
+/*
+/*     TLS_PRNG_SRC *tls_prng_egd_open(name, timeout)
+/*     const char *name;
+/*     int     timeout;
+/*
+/*     ssize_t tls_prng_egd_read(egd, length)
+/*     TLS_PRNG_SRC *egd;
+/*     size_t length;
+/*
+/*     int     tls_prng_egd_close(egd)
+/*     TLS_PRNG_SRC *egd;
+/* DESCRIPTION
+/*     tls_prng_egd_open() connect to the specified UNIX-domain service
+/*     and returns a handle that should be used with all subsequent
+/*     access.
+/*
+/*     tls_prng_egd_read() reads the requested number of bytes from
+/*     the EGD server and updates the OpenSSL PRNG.
+/*
+/*     tls_prng_egd_close() disconnects from the specified EGD server
+/*     and releases memory that was allocated for the handle.
+/*
+/*     Arguments:
+/* .IP name
+/*     The UNIX-domain pathname of the EGD service.
+/* .IP length
+/*     The number of bytes to read from the EGD server.
+/*     Request lengths will be truncated at 255 bytes.
+/* .IP timeout
+/*     Time limit on individual I/O operations.
+/* DIAGNOSTICS
+/*     tls_prng_egd_open() returns a null pointer on error.
+/*
+/*     tls_prng_egd_read() returns -1 on error, the number
+/*     of bytes received on success.
+/*
+/*     tls_prng_egd_close() returns -1 on error, 0 on success.
+/*
+/*     In all cases the errno variable indicates the type of error.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 0xff
+#endif
+
+/* OpenSSL library. */
+
+#ifdef USE_TLS
+#include <openssl/rand.h>              /* For the PRNG */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <connect.h>
+#include <iostuff.h>
+
+/* TLS library. */
+
+#include <tls_prng.h>
+
+/* tls_prng_egd_open - connect to EGD server */
+
+TLS_PRNG_SRC *tls_prng_egd_open(const char *name, int timeout)
+{
+    const char *myname = "tls_prng_egd_open";
+    TLS_PRNG_SRC *egd;
+    int     fd;
+
+    if (msg_verbose)
+       msg_info("%s: connect to EGD server %s", myname, name);
+
+    if ((fd = unix_connect(name, BLOCKING, timeout)) < 0) {
+       if (msg_verbose)
+           msg_info("%s: cannot connect to EGD server %s: %m", myname, name);
+       return (0);
+    } else {
+       egd = (TLS_PRNG_SRC *) mymalloc(sizeof(*egd));
+       egd->fd = fd;
+       egd->name = mystrdup(name);
+       egd->timeout = timeout;
+       if (msg_verbose)
+           msg_info("%s: connected to EGD server %s", myname, name);
+       return (egd);
+    }
+}
+
+/* tls_prng_egd_read - update internal PRNG from EGD server */
+
+ssize_t tls_prng_egd_read(TLS_PRNG_SRC *egd, size_t len)
+{
+    const char *myname = "tls_prng_egd_read";
+    unsigned char buffer[UCHAR_MAX];
+    ssize_t count;
+
+    if (len <= 0)
+       msg_panic("%s: bad length %ld", myname, (long) len);
+
+    buffer[0] = 1;
+    buffer[1] = (len > UCHAR_MAX ? UCHAR_MAX : len);
+
+    if (timed_write(egd->fd, buffer, 2, egd->timeout, (void *) 0) != 2) {
+       msg_info("cannot write to EGD server %s: %m", egd->name);
+       return (-1);
+    }
+    if (timed_read(egd->fd, buffer, 1, egd->timeout, (void *) 0) != 1) {
+       msg_info("cannot read from EGD server %s: %m", egd->name);
+       return (-1);
+    }
+    count = buffer[0];
+    if (count > sizeof(buffer))
+       count = sizeof(buffer);
+    if (count == 0) {
+       msg_info("EGD server %s reports zero bytes available", egd->name);
+       return (-1);
+    }
+    if (timed_read(egd->fd, buffer, count, egd->timeout, (void *) 0) != count) {
+       msg_info("cannot read %ld bytes from EGD server %s: %m",
+                (long) count, egd->name);
+       return (-1);
+    }
+    if (msg_verbose)
+       msg_info("%s: got %ld bytes from EGD server %s", myname,
+                (long) count, egd->name);
+    RAND_seed(buffer, count);
+    return (count);
+}
+
+/* tls_prng_egd_close - disconnect from EGD server */
+
+int     tls_prng_egd_close(TLS_PRNG_SRC *egd)
+{
+    const char *myname = "tls_prng_egd_close";
+    int     err;
+
+    if (msg_verbose)
+       msg_info("%s: close EGD server %s", myname, egd->name);
+    err = close(egd->fd);
+    myfree(egd->name);
+    myfree((char *) egd);
+    return (err);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_prng_exch.c b/postfix/src/tls/tls_prng_exch.c
new file mode 100644 (file)
index 0000000..c618171
--- /dev/null
@@ -0,0 +1,142 @@
+/*++
+/* NAME
+/*     tls_prng_exch 3
+/* SUMMARY
+/*     maintain PRNG exchange file
+/* SYNOPSIS
+/*     #include <tls_prng_src.h>
+/*
+/*     TLS_PRNG_SRC *tls_prng_exch_open(name, timeout)
+/*     const char *name;
+/*     int     timeout;
+/*
+/*     void    tls_prng_exch_update(fh, length)
+/*     TLS_PRNG_SRC *fh;
+/*     size_t length;
+/*
+/*     void    tls_prng_exch_close(fh)
+/*     TLS_PRNG_SRC *fh;
+/* DESCRIPTION
+/*     tls_prng_exch_open() opens the specified PRNG exchange file
+/*     and returns a handle that should be used with all subsequent
+/*     access.
+/*
+/*     tls_prng_exch_update() reads the requested number of bytes
+/*     from the PRNG exchange file, updates the OpenSSL PRNG, and
+/*     writes the requested number of bytes to the exchange file.
+/*     The file is locked for exclusive access.
+/*
+/*     tls_prng_exch_close() closes the specified PRNG exchange
+/*     file and releases memory that was allocated for the handle.
+/*
+/*     Arguments:
+/* .IP name
+/*     The name of the PRNG exchange file.
+/* .IP length
+/*     The number of bytes to read from/write to the entropy file.
+/* .IP timeout
+/*     Time limit on individual I/O operations.
+/* DIAGNOSTICS
+/*     All errors are fatal.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+
+/* OpenSSL library. */
+
+#ifdef USE_TLS
+#include <openssl/rand.h>              /* For the PRNG */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <iostuff.h>
+#include <myflock.h>
+
+/* TLS library. */
+
+#include <tls_prng.h>
+
+/* Application specific. */
+
+#define TLS_PRNG_EXCH_SIZE     1024    /* XXX Why not configurable? */
+
+/* tls_prng_exch_open - open PRNG exchange file */
+
+TLS_PRNG_SRC *tls_prng_exch_open(const char *name)
+{
+    const char *myname = "tls_prng_exch_open";
+    TLS_PRNG_SRC *eh;
+    int     fd;
+
+    if ((fd = open(name, O_RDWR | O_CREAT, 0600)) < 0)
+       msg_fatal("%s: cannot open PRNG exchange file %s: %m", myname, name);
+    eh = (TLS_PRNG_SRC *) mymalloc(sizeof(*eh));
+    eh->fd = fd;
+    eh->name = mystrdup(name);
+    eh->timeout = 0;
+    if (msg_verbose)
+       msg_info("%s: opened PRNG exchange file %s", myname, name);
+    return (eh);
+}
+
+/* tls_prng_exch_update - update PRNG exchange file */
+
+void    tls_prng_exch_update(TLS_PRNG_SRC *eh)
+{
+    unsigned char buffer[TLS_PRNG_EXCH_SIZE];
+    ssize_t count;
+
+    /*
+     * Update the PRNG exchange file. Since other processes may have added
+     * entropy, we use a read-stir-write cycle.
+     */
+    if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
+       msg_fatal("cannot lock PRNG exchange file %s: %m", eh->name);
+    if (lseek(eh->fd, 0, SEEK_SET) < 0)
+       msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name);
+    if ((count = read(eh->fd, buffer, sizeof(buffer))) < 0)
+       msg_fatal("cannot read PRNG exchange file %s: %m", eh->name);
+
+    if (count > 0)
+       RAND_seed(buffer, count);
+    RAND_bytes(buffer, sizeof(buffer));
+
+    if (lseek(eh->fd, 0, SEEK_SET) < 0)
+       msg_fatal("cannot seek PRNG exchange file %s: %m", eh->name);
+    if (write(eh->fd, buffer, sizeof(buffer)) != sizeof(buffer))
+       msg_fatal("cannot write PRNG exchange file %s: %m", eh->name);
+    if (myflock(eh->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
+       msg_fatal("cannot unlock PRNG exchange file %s: %m", eh->name);
+}
+
+/* tls_prng_exch_close - close PRNG exchange file */
+
+void    tls_prng_exch_close(TLS_PRNG_SRC *eh)
+{
+    const char *myname = "tls_prng_exch_close";
+
+    if (close(eh->fd) < 0)
+       msg_fatal("close PRNG exchange file %s: %m", eh->name);
+    myfree(eh->name);
+    myfree((char *) eh);
+    if (msg_verbose)
+       msg_info("%s: closed PRNG exchange file %s", myname, eh->name);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_prng_file.c b/postfix/src/tls/tls_prng_file.c
new file mode 100644 (file)
index 0000000..83754e4
--- /dev/null
@@ -0,0 +1,155 @@
+/*++
+/* NAME
+/*     tls_prng_file 3
+/* SUMMARY
+/*     seed OpenSSL PRNG from entropy file
+/* SYNOPSIS
+/*     #include <tls_prng_src.h>
+/*
+/*     TLS_PRNG_SRC *tls_prng_file_open(name, timeout)
+/*     const char *name;
+/*     int     timeout;
+/*
+/*     ssize_t tls_prng_file_read(fh, length)
+/*     TLS_PRNG_SRC *fh;
+/*     size_t length;
+/*
+/*     int     tls_prng_file_close(fh)
+/*     TLS_PRNG_SRC *fh;
+/* DESCRIPTION
+/*     tls_prng_file_open() open the specified file and returns
+/*     a handle that should be used with all subsequent access.
+/*
+/*     tls_prng_file_read() reads the requested number of bytes from
+/*     the entropy file and updates the OpenSSL PRNG. The file is not
+/*     locked for shared or exclusive access.
+/*
+/*     tls_prng_file_close() closes the specified entropy file
+/*     and releases memory that was allocated for the handle.
+/*
+/*     Arguments:
+/* .IP name
+/*     The pathname of the entropy file.
+/* .IP length
+/*     The number of bytes to read from the entropy file.
+/* .IP timeout
+/*     Time limit on individual I/O operations.
+/* DIAGNOSTICS
+/*     tls_prng_file_open() returns a null pointer on error.
+/*
+/*     tls_prng_file_read() returns -1 on error, the number
+/*     of bytes received on success.
+/*
+/*     tls_prng_file_close() returns -1 on error, 0 on success.
+/*
+/*     In all cases the errno variable indicates the type of error.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+/* OpenSSL library. */
+
+#ifdef USE_TLS
+#include <openssl/rand.h>              /* For the PRNG */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <connect.h>
+#include <iostuff.h>
+
+/* TLS library. */
+
+#include <tls_prng.h>
+
+/* tls_prng_file_open - open entropy file */
+
+TLS_PRNG_SRC *tls_prng_file_open(const char *name, int timeout)
+{
+    const char *myname = "tls_prng_file_open";
+    TLS_PRNG_SRC *fh;
+    int     fd;
+
+    if ((fd = open(name, O_RDONLY, 0)) < 0) {
+       if (msg_verbose)
+           msg_info("%s: cannot open entropy file %s: %m", myname, name);
+       return (0);
+    } else {
+       fh = (TLS_PRNG_SRC *) mymalloc(sizeof(*fh));
+       fh->fd = fd;
+       fh->name = mystrdup(name);
+       fh->timeout = timeout;
+       if (msg_verbose)
+           msg_info("%s: opened entropy file %s", myname, name);
+       return (fh);
+    }
+}
+
+/* tls_prng_file_read - update internal PRNG from entropy file */
+
+ssize_t tls_prng_file_read(TLS_PRNG_SRC *fh, size_t len)
+{
+    const char *myname = "tls_prng_file_read";
+    char    buffer[8192];
+    int     to_read;
+    int     count;
+
+    if (msg_verbose)
+       msg_info("%s: seed internal pool from file %s", myname, fh->name);
+
+    if (lseek(fh->fd, 0, SEEK_SET) < 0) {
+       if (msg_verbose)
+           msg_info("cannot seek entropy file %s: %m", fh->name);
+       return (-1);
+    }
+    errno = 0;
+    for (to_read = len; to_read > 0; to_read -= count) {
+       if ((count = timed_read(fh->fd, buffer, to_read > sizeof(buffer) ?
+                               sizeof(buffer) : to_read,
+                               fh->timeout, (void *) 0)) < 0) {
+           if (msg_verbose)
+               msg_info("cannot read entropy file %s: %m", fh->name);
+           return (-1);
+       }
+       if (count == 0)
+           break;
+       RAND_seed(buffer, count);
+    }
+    if (msg_verbose)
+       msg_info("read %ld bytes from entropy file %s: %m",
+                (long) (len - to_read), fh->name);
+    return (len - to_read);
+}
+
+/* tls_prng_file_close - close entropy file */
+
+int     tls_prng_file_close(TLS_PRNG_SRC *fh)
+{
+    const char *myname = "tls_prng_file_close";
+    int     err;
+
+    if (msg_verbose)
+       msg_info("%s: close entropy file %s", myname, fh->name);
+    err = close(fh->fd);
+    myfree(fh->name);
+    myfree((char *) fh);
+    return (err);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_rsa.c b/postfix/src/tls/tls_rsa.c
new file mode 100644 (file)
index 0000000..cb1476b
--- /dev/null
@@ -0,0 +1,76 @@
+/*++
+/* NAME
+/*     tls_rsa
+/* SUMMARY
+/*     RSA support
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     RSA     *tls_tmp_rsa_cb(ssl, export, keylength)
+/*     SSL     *ssl; /* unused */
+/*     int     export;
+/*     int     keylength;
+/* DESCRIPTION
+/*     This module maintains parameters for Diffie-Hellman key generation.
+/*
+/*     tls_tmp_rsa_cb() is a call-back routine for the
+/*     SSL_CTX_set_tmp_rsa_callback() function.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* tls_tmp_rsa_cb - call-back to generate ephemeral RSA key */
+
+RSA *tls_tmp_rsa_cb(SSL *unused_ssl, int unused_export, int keylength)
+{
+    static RSA *rsa_tmp;
+
+    /* Code adapted from OpenSSL apps/s_cb.c */
+
+    if (rsa_tmp == 0)
+       rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
+    return (rsa_tmp);
+}
+
+#ifdef TEST
+
+int main(int unused_argc, char **unused_argv)
+{
+    tls_tmp_rsa_cb(0, 1, 512);
+    tls_tmp_rsa_cb(0, 1, 1024);
+    tls_tmp_rsa_cb(0, 1, 2048);
+    tls_tmp_rsa_cb(0, 0, 512);
+}
+
+#endif
+
+#endif
diff --git a/postfix/src/tls/tls_scache.c b/postfix/src/tls/tls_scache.c
new file mode 100644 (file)
index 0000000..1788cd0
--- /dev/null
@@ -0,0 +1,567 @@
+/*++
+/* NAME
+/*     tls_scache 3
+/* SUMMARY
+/*     TLS session cache manager
+/* SYNOPSIS
+/*     #include <tls_scache.h>
+/*
+/*     TLS_SCACHE *tls_scache_open(dbname, cache_label, log_level, timeout)
+/*     const char *dbname
+/*     const char *cache_label;
+/*     int     log_level;
+/*     int     timeout;
+/*
+/*     void    tls_scache_close(cache)
+/*     TLS_SCACHE *cache;
+/*
+/*     int     tls_scache_lookup(cache, cache_id, openssl_version,
+/*                             flags, out_openssl_version, out_flags,
+/*                             out_session)
+/*     TLS_SCACHE *cache;
+/*     const char *cache_id;
+/*     long    openssl_version;
+/*     int     flags;
+/*     long    *out_openssl_version;
+/*     int     *out_flags;
+/*     VSTRING *out_session;
+/*
+/*     int     tls_scache_update(cache, cache_id, openssl_version,
+/*                             flags, session, session_len)
+/*     TLS_SCACHE *cache;
+/*     const char *cache_id;
+/*     long    openssl_version;
+/*     int     flags;
+/*     const char *session;
+/*     int     session_len;
+/*
+/*     int     tls_scache_sequence(cache, first_next, openssl_version, flags,
+/*                             out_cache_id, out_openssl_version, out_flags,
+/*                             VSTRING *out_session)
+/*     TLS_SCACHE *cache;
+/*     int     first_next;
+/*     long    openssl_version;
+/*     int     flags;
+/*     char    **out_cache_id;
+/*     long    *out_openssl_version;
+/*     int     *out_flags;
+/*     VSTRING *out_session;
+/*
+/*     int     tls_scache_delete(cache, cache_id)
+/*     TLS_SCACHE *cache;
+/*     const char *cache_id;
+/* DESCRIPTION
+/*     This module maintains Postfix TLS session cache files.
+/*     each session is stored under a lookup key (hostname or
+/*     session ID) together with the OpenSSL version that
+/*     created the session and application-specific flags.
+/*     Upon lookup, the OpenSSL version and flags can be
+/*     specified as optional filters. Entries that don't
+/*     satisfy the filter requirements are silently deleted.
+/*
+/*     tls_scache_open() opens the specified TLS session cache
+/*     and returns a handle that must be used for subsequent
+/*     access.
+/*
+/*     tls_scache_close() closes the specified TLS session cache
+/*     and releases memory that was allocated by tls_scache_open().
+/*
+/*     tls_scache_lookup() looks up the specified session in the
+/*     specified cache, and applies the session timeout, openssl
+/*     version and flags restrictions. Entries that don't satisfy
+/*     the requirements are silently deleted.
+/*
+/*     tls_scache_update() updates the specified TLS session cache
+/*     with the specified session information.
+/*
+/*     tls_scache_sequence() iterates over the specified TLS
+/*     session cache and returns the first or next entry that
+/*     matches the session timeout, OpenSSL version and flags
+/*     restrictions.  Entries that don't satisfy the requirements
+/*     are silently deleted.  Specify TLS_SCACHE_SEQUENCE_NOTHING
+/*     as the third and last argument to disable OpenSSL version
+/*     and flags restrictions, and to disable saving of cache
+/*     entry content or cache entry ID information.  This is useful
+/*     when purging expired entries.
+/*
+/*     tls_scache_delete() removes the specified cache entry from
+/*     the specified TLS session cache.
+/*
+/*     Arguments:
+/* .IP dbname
+/*     The base name of the session cache file.
+/* .IP cache_label
+/*     A string that is used in logging and error messages.
+/* .IP log_level
+/*     The logging level for cache operations.
+/* .IP timeout
+/*     The time after wich a session cache entry is considered too old.
+/* .IP first_next
+/*     One of DICT_SEQ_FUN_FIRST (first cache element) or DICT_SEQ_FUN_NEXT
+/*     (next cache element).
+/* .IP cache_id
+/*     Session cache lookup key.
+/* .IP openssl_version
+/*     When storing information, the OpenSSL version that generated a
+/*     session. When retrieving information, delete cache entries that
+/*     don't match the specified OpenSSL version.
+/*
+/*     Specify TLS_SCACHE_ANY_OPENSSL_VSN to match any OpenSSL version.
+/* .IP flags
+/*     When storing information, application flags that specify properties
+/*     of a session. When retrieving information, delete cache entries that
+/*     have the specified flags set.
+/*
+/*     Specify TLS_SCACHE_ANY_FLAGS to match any flags value.
+/* .IP session
+/*     Storage for session information.
+/* .IP session_len
+/*     The size of the session information in bytes.
+/* .IP out_cache_id
+/* .IP out_openssl_version
+/* .IP out_flags
+/* .IP out_session
+/*     Storage for saving the cache_id, openssl_version, flags
+/*     or session information of the current cache entry.
+/*
+/*     Specify TLS_SCACHE_DONT_NEED_CACHE_ID to avoid saving
+/*     the session cache ID of the cache entry.
+/*
+/*     Specify TLS_SCACHE_DONT_NEED_OPENSSL_VSN to avoid
+/*     saving the OpenSSL version in the cache entry.
+/*
+/*     Specify TLS_SCACHE_DONT_NEED_FLAGS to avoid
+/*     saving the flags information in the cache entry.
+/*
+/*     Specify TLS_SCACHE_DONT_NEED_SESSION to avoid
+/*     saving the session information in the cache entry.
+/* DIAGNOSTICS
+/*     These routines terminate with a fatal run-time error
+/*     for unrecoverable database errors. This allows the
+/*     program to restart and reset the database to an
+/*     empty initial state.
+/*
+/*     tls_scache_open() never returns on failure. All other
+/*     functions return non-zero on success, zero when the
+/*     operation could not be completed.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+#include <string.h>
+#include <stddef.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <dict.h>
+#include <stringops.h>
+#include <mymalloc.h>
+#include <hex_code.h>
+#include <myflock.h>
+#include <vstring.h>
+
+/* Global library. */
+
+/* TLS library. */
+
+#include <tls_scache.h>
+
+/* Application-specific. */
+
+ /*
+  * Session cache entry format.
+  * 
+  * XXX The session cache version number is not needed because we truncate the
+  * database when it is opened.
+  */
+typedef struct {
+    long    scache_db_version;         /* obsolete */
+    long    openssl_version;           /* clients may differ... */
+    time_t  timestamp;                 /* time when saved */
+    int     flags;                     /* enforcement etc. */
+    char    session[1];                        /* actually a bunch of bytes */
+} TLS_SCACHE_ENTRY;
+
+#define TLS_SCACHE_DB_VERSION  0x00000003L
+
+ /*
+  * SLMs.
+  */
+#define STR(x)         vstring_str(x)
+#define LEN(x)         VSTRING_LEN(x)
+
+/* tls_scache_encode - encode TLS session cache entry */
+
+static VSTRING *tls_scache_encode(TLS_SCACHE *cp, const char *cache_id,
+                                         long openssl_version, int flags,
+                                         const char *session,
+                                         int session_len)
+{
+    TLS_SCACHE_ENTRY *entry;
+    VSTRING *hex_data;
+    int     binary_data_len;
+
+    /*
+     * Assemble the TLS session cache entry.
+     * 
+     * We could eliminate some copying by using incremental encoding, but
+     * sessions are so small that it really does not matter.
+     */
+    binary_data_len = session_len + offsetof(TLS_SCACHE_ENTRY, session);
+    entry = (TLS_SCACHE_ENTRY *) mymalloc(binary_data_len);
+    entry->scache_db_version = TLS_SCACHE_DB_VERSION;
+    entry->openssl_version = openssl_version;
+    entry->timestamp = time((time_t *) 0);
+    entry->flags = flags;
+    memcpy(entry->session, session, session_len);
+
+    /*
+     * Encode the TLS session cache entry.
+     */
+    hex_data = vstring_alloc(2 * binary_data_len + 1);
+    hex_encode(hex_data, (char *) entry, binary_data_len);
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("write %s TLS cache entry %s: cache_version=%ld"
+              " openssl_version=0x%lx flags=0x%x time=%ld [data %d bytes]",
+                cp->cache_label, cache_id,
+                (long) entry->scache_db_version,
+                (long) entry->openssl_version,
+                entry->flags,
+                (long) entry->timestamp,
+                session_len);
+
+    /*
+     * Clean up.
+     */
+    myfree((char *) entry);
+
+    return (hex_data);
+}
+
+/* tls_scache_decode - decode TLS session cache entry */
+
+static int tls_scache_decode(TLS_SCACHE *cp, const char *cache_id,
+                                    const char *hex_data, int hex_data_len,
+                                    long openssl_version, int flags,
+                                    long *out_openssl_version,
+                                    int *out_flags,
+                                    VSTRING *out_session)
+{
+    TLS_SCACHE_ENTRY *entry;
+    VSTRING *bin_data;
+
+    /*
+     * Sanity check.
+     */
+    if (hex_data_len < 2 * (offsetof(TLS_SCACHE_ENTRY, session))) {
+       msg_warn("%s TLS cache: truncated entry for %s: %.100s",
+                cp->cache_label, cache_id, hex_data);
+       return (0);
+    }
+
+    /*
+     * Disassemble the TLS session cache entry and enforce the restrictions
+     * specified as version numbers or flags.
+     * 
+     * No early returns or we have a memory leak.
+     */
+#define FREE_AND_RETURN(ptr, x) { vstring_free(ptr); return (x); }
+
+    bin_data = vstring_alloc(hex_data_len / 2 + 1);
+    if (hex_decode(bin_data, hex_data, hex_data_len) == 0) {
+       msg_warn("%s TLS cache: malformed entry for %s: %.100s",
+                cp->cache_label, cache_id, hex_data);
+       FREE_AND_RETURN(bin_data, 0);
+    }
+
+    /*
+     * Before doing anything else, verify that the database format version
+     * matches this program.
+     */
+    entry = (TLS_SCACHE_ENTRY *) STR(bin_data);
+    if (entry->scache_db_version != TLS_SCACHE_DB_VERSION) {
+       msg_warn("%s TLS cache: cache version mis-match for %s: 0x%lx != 0x%lx",
+                cp->cache_label, cache_id, entry->scache_db_version,
+                TLS_SCACHE_DB_VERSION);
+       FREE_AND_RETURN(bin_data, 0);
+    }
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("read %s TLS cache entry %s: cache_version=%ld"
+              " openssl_version=0x%lx time=%ld flags=0x%x [data %d bytes]",
+                cp->cache_label, cache_id, (long) entry->scache_db_version,
+                (long) entry->openssl_version, (long) entry->timestamp,
+                entry->flags,
+                LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session));
+
+    /*
+     * Other mandatory restrictions.
+     */
+    if (entry->timestamp + cp->timeout < time((time_t *) 0))
+       FREE_AND_RETURN(bin_data, 0);
+
+    /*
+     * Optional restrictions.
+     */
+    if (openssl_version != 0 && entry->openssl_version != openssl_version) {
+       msg_warn("%s TLS cache: openssl version mis-match for %s: 0x%lx != 0x%lx",
+                cp->cache_label, cache_id, entry->openssl_version,
+                openssl_version);
+       FREE_AND_RETURN(bin_data, 0);
+    }
+    if (flags != 0 && (entry->flags & flags) != flags) {
+       msg_warn("%s TLS cache: flags mis-match for %s: 0x%x is not subset of 0x%x",
+                cp->cache_label, cache_id, entry->flags, flags);
+       FREE_AND_RETURN(bin_data, 0);
+    }
+
+    /*
+     * Optional output.
+     */
+    if (out_openssl_version != 0)
+       *out_openssl_version = entry->openssl_version;
+    if (out_flags != 0)
+       *out_flags = entry->flags;
+    if (out_session != 0)
+       vstring_memcpy(out_session, entry->session,
+                      LEN(bin_data) - offsetof(TLS_SCACHE_ENTRY, session));
+
+    /*
+     * Clean up.
+     */
+    FREE_AND_RETURN(bin_data, 1);
+}
+
+/* tls_scache_lookup - load session from cache */
+
+int     tls_scache_lookup(TLS_SCACHE *cp, const char *cache_id,
+                                 long openssl_version, int flags,
+                                 long *out_openssl_version, int *out_flags,
+                                 VSTRING *session)
+{
+    const char *hex_data;
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("lookup %s session id=%s ssl=0x%lx flags=0x%x",
+                cp->cache_label, cache_id, openssl_version, flags);
+
+    /*
+     * Initialize. Don't leak data.
+     */
+    VSTRING_RESET(session);
+
+    /*
+     * Search the cache database.
+     */
+    if ((hex_data = dict_get(cp->db, cache_id)) == 0)
+       return (0);
+
+    /*
+     * Decode entry and verify version and flags information.
+     * 
+     * XXX We throw away sessions when flags don't match. If we want to allow
+     * for co-existing cache entries with different flags, the flags would
+     * have to be encoded in the cache lookup key.
+     */
+    if (tls_scache_decode(cp, cache_id, hex_data, strlen(hex_data),
+                         openssl_version, flags, out_openssl_version,
+                         out_flags, session) == 0) {
+       tls_scache_delete(cp, cache_id);
+       return (0);
+    } else {
+       return (1);
+    }
+}
+
+/* tls_scache_update - save session to cache */
+
+int     tls_scache_update(TLS_SCACHE *cp, const char *cache_id,
+                                 long openssl_version, int flags,
+                                 const char *buf, int len)
+{
+    VSTRING *hex_data;
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("put %s session id=%s ssl=0x%lx flags=0x%x [data %d bytes]",
+                cp->cache_label, cache_id, openssl_version, flags, len);
+
+    /*
+     * Encode the cache entry.
+     */
+    hex_data =
+       tls_scache_encode(cp, cache_id, openssl_version, flags, buf, len);
+
+    /*
+     * Store the cache entry.
+     * 
+     * XXX Berkeley DB supports huge database keys and values. SDBM seems to
+     * have a finite limit, and DBM simply can't be used at all.
+     */
+    dict_put(cp->db, cache_id, STR(hex_data));
+
+    /*
+     * Clean up.
+     */
+    vstring_free(hex_data);
+
+    return (1);
+}
+
+/* tls_scache_sequence - get first/next TLS session cache entry */
+
+int     tls_scache_sequence(TLS_SCACHE *cp, int first_next,
+                                   long openssl_version,
+                                   int flags,
+                                   char **out_cache_id,
+                                   long *out_openssl_version,
+                                   int *out_flags,
+                                   VSTRING *out_session)
+{
+    const char *member;
+    const char *value;
+    char   *saved_member;
+
+    /*
+     * Find the first or next database entry.
+     */
+    if (dict_seq(cp->db, first_next, &member, &value) != 0)
+       return (0);                             /* End of list reached */
+
+    /*
+     * Activate the passivated cache entry and check the version and time
+     * stamp information.
+     */
+    if (tls_scache_decode(cp, member, value, strlen(value), openssl_version,
+                         flags, out_openssl_version, out_flags,
+                         out_session) == 0) {
+       saved_member = mystrdup(member);
+       tls_scache_delete(cp, saved_member);
+       myfree(saved_member);
+       return (0);
+    } else {
+       if (out_cache_id)
+           *out_cache_id = mystrdup(member);
+       return (1);
+    }
+}
+
+/* tls_scache_delete - delete session from cache */
+
+int     tls_scache_delete(TLS_SCACHE *cp, const char *cache_id)
+{
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("delete %s session id=%s", cp->cache_label, cache_id);
+
+    /*
+     * Do it.
+     */
+    return (dict_del(cp->db, cache_id) == 0);
+}
+
+/* tls_scache_open - open TLS session cache file */
+
+TLS_SCACHE *tls_scache_open(const char *dbname, const char *cache_label,
+                                   int log_level, int timeout)
+{
+    TLS_SCACHE *cp;
+    DICT   *dict;
+
+    /*
+     * Logging.
+     */
+    if (log_level >= 3)
+       msg_info("open %s TLS cache %s", cache_label, dbname);
+
+    /*
+     * Open the dictionary with O_TRUNC, so that we never have to worry about
+     * opening a damaged file after some process terminated abnormally.
+     */
+#ifdef SINGLE_UPDATER
+#define DICT_FLAGS (DICT_FLAG_DUP_REPLACE)
+#else
+#define DICT_FLAGS \
+       (DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE)
+#endif
+
+    dict = dict_open(dbname, O_RDWR | O_CREAT | O_TRUNC, DICT_FLAGS);
+
+    /*
+     * Sanity checks.
+     */
+    if (dict->lock_fd < 0)
+       msg_fatal("dictionary %s is not a regular file", dbname);
+#ifdef SINGLE_UPDATER
+    if (myflock(dict->lock_fd, INTERNAL_LOCK,
+               MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
+       msg_fatal("cannot lock dictionary %s for exclusive use: %m", dbname);
+#endif
+    if (dict->update == 0)
+       msg_fatal("dictionary %s does not support update operations", dbname);
+    if (dict->delete == 0)
+       msg_fatal("dictionary %s does not support delete operations", dbname);
+    if (dict->sequence == 0)
+       msg_fatal("dictionary %s does not support sequence operations", dbname);
+
+    /*
+     * Create the TLS_SCACHE object.
+     */
+    cp = (TLS_SCACHE *) mymalloc(sizeof(*cp));
+    cp->db = dict;
+    cp->cache_label = mystrdup(cache_label);
+    cp->log_level = log_level;
+    cp->timeout = timeout;
+
+    return (cp);
+}
+
+/* tls_scache_close - close TLS session cache file */
+
+void    tls_scache_close(TLS_SCACHE *cp)
+{
+
+    /*
+     * Logging.
+     */
+    if (cp->log_level >= 3)
+       msg_info("close %s TLS cache %s", cp->cache_label, cp->db->name);
+
+    /*
+     * Destroy the TLS_SCACHE object.
+     */
+    dict_close(cp->db);
+    myfree(cp->cache_label);
+    myfree((char *) cp);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_scache.h b/postfix/src/tls/tls_scache.h
new file mode 100644 (file)
index 0000000..66025c2
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _TLS_SCACHE_H_INCLUDED_
+#define _TLS_SCACHE_H_INCLUDED_
+
+/*++
+/* NAME
+/*     tls_scache 3h
+/* SUMMARY
+/*     TLS session cache manager
+/* SYNOPSIS
+/*     #include <tls_scache.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+#include <vstring.h>
+
+ /*
+  * External interface.
+  */
+typedef struct {
+    DICT   *db;                                /* database handle */
+    char   *cache_label;               /* "client" or "server" */
+    int     log_level;                 /* smtp(d)_tls_log_level */
+    int     timeout;                   /* smtp(d)_tls_session_cache_timeout */
+} TLS_SCACHE;
+
+extern TLS_SCACHE *tls_scache_open(const char *, const char *, int, int);
+extern void tls_scache_close(TLS_SCACHE *);
+extern int tls_scache_lookup(TLS_SCACHE *, const char *, long, int, long *, int *, VSTRING *);
+extern int tls_scache_update(TLS_SCACHE *, const char *, long, int, const char *, int);
+extern int tls_scache_delete(TLS_SCACHE *, const char *);
+extern int tls_scache_sequence(TLS_SCACHE *, int, long, int, char **, long *, int *, VSTRING *);
+
+#define TLS_SCACHE_ANY_OPENSSL_VSN             ((long) 0)
+#define TLS_SCACHE_ANY_FLAGS                   (0)
+
+#define TLS_SCACHE_DONT_NEED_CACHE_ID          ((char **) 0)
+#define TLS_SCACHE_DONT_NEED_OPENSSL_VSN       ((long *) 0)
+#define TLS_SCACHE_DONT_NEED_FLAGS             ((int *) 0)
+#define TLS_SCACHE_DONT_NEED_SESSION           ((VSTRING *) 0)
+
+#define TLS_SCACHE_SEQUENCE_NOTHING \
+       TLS_SCACHE_ANY_FLAGS, TLS_SCACHE_ANY_OPENSSL_VSN, \
+       TLS_SCACHE_DONT_NEED_CACHE_ID, TLS_SCACHE_DONT_NEED_OPENSSL_VSN, \
+       TLS_SCACHE_DONT_NEED_FLAGS, TLS_SCACHE_DONT_NEED_SESSION
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/tls/tls_seed.c b/postfix/src/tls/tls_seed.c
new file mode 100644 (file)
index 0000000..edb7cd9
--- /dev/null
@@ -0,0 +1,88 @@
+/*++
+/* NAME
+/*     tls_seed 3
+/* SUMMARY
+/*     TLS PRNG seeding routines
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     int     tls_ext_seed(nbytes)
+/*     int     nbytes;
+/*
+/*     void    tls_int_seed()
+/* DESCRIPTION
+/*     tls_ext_seed() requests the specified number of bytes
+/*     from the tlsmgr(8) PRNG pool and updates the local PRNG.
+/*     The result is zero in case of success, -1 otherwise.
+/*
+/*     tls_int_seed() mixes the process ID and time of day into
+/*     the PRNG pool. This adds a few bits of entropy with each
+/*     call, provided that the calls aren't made frequently.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this
+/*     software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/time.h>                  /* gettimeofday() */
+#include <unistd.h>                    /* getpid() */
+
+#ifdef USE_TLS
+
+/* OpenSSL library. */
+
+#include <openssl/rand.h>              /* RAND_seed() */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+
+/* TLS library. */
+
+#include <tls_mgr.h>
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+/* tls_int_seed - add entropy to the pool by adding the time and PID */
+
+void    tls_int_seed(void)
+{
+    static struct {
+       pid_t   pid;
+       struct timeval tv;
+    }       randseed;
+
+    if (randseed.pid == 0)
+       randseed.pid = getpid();
+    GETTIMEOFDAY(&randseed.tv);
+    RAND_seed(&randseed, sizeof(randseed));
+}
+
+/* tls_ext_seed - request entropy from tlsmgr(8) server */
+
+int     tls_ext_seed(int nbytes)
+{
+    VSTRING *buf;
+    int     status;
+
+    buf = vstring_alloc(nbytes);
+    status = tls_mgr_seed(buf, nbytes);
+    RAND_seed(vstring_str(buf), VSTRING_LEN(buf));
+    vstring_free(buf);
+    return (status == TLS_MGR_STAT_OK ? 0 : -1);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c
new file mode 100644 (file)
index 0000000..fc7ec92
--- /dev/null
@@ -0,0 +1,705 @@
+/*++
+/* NAME
+/*     tls_server 3
+/* SUMMARY
+/*     server-side TLS engine
+/* SYNOPSIS
+/*     #include <tls.h>
+/*
+/*     SSL_CTX *tls_server_init(verifydepth, askcert)
+/*     int     verifydepth;
+/*     int     askcert;
+/*
+/*     TLScontext_t *tls_server_start(server_ctx, stream, timeout,
+/*                                     peername, peeraddr,
+/*                                     tls_info, requirecert)
+/*     SSL_CTX *server_ctx;
+/*     VSTREAM *stream;
+/*     int     timeout;
+/*     const char *peername;
+/*     const char *peeraddr;
+/*     tls_info_t *tls_info;
+/*     int     requirecert;
+/*
+/*     void    tls_server_stop(server_ctx, stream, failure, tls_info)
+/*     SSL_CTX *server_ctx;
+/*     VSTREAM *stream;
+/*     int     failure;
+/*     tls_info_t *tls_info;
+/* DESCRIPTION
+/*     This module is the interface between Postfix TLS servers
+/*     and the OpenSSL library and TLS entropy and cache manager.
+/*
+/*     tls_server_init() is called once when the SMTP server
+/*     initializes.
+/*     Certificate details are also decided during this phase,
+/*     so that peer-specific behavior is not possible.
+/*
+/*     tls_server_start() activates the TLS feature for the VSTREAM
+/*     passed as argument. We assume that network buffers are flushed and the
+/*     TLS handshake can begin immediately. Information about the peer
+/*     is stored into the tls_info structure passed as argument.
+/*
+/*     tls_server_stop() sends the "close notify" alert via
+/*     SSL_shutdown() to the peer and resets all connection specific
+/*     TLS data. As RFC2487 does not specify a separate shutdown, it
+/*     is assumed that the underlying TCP connection is shut down
+/*     immediately afterwards, so we don't care about additional data
+/*     coming through the channel.
+/*     If the failure flag is set, no SSL_shutdown() handshake is performed.
+/*
+/*     Once the TLS connection is initiated, information about the TLS
+/*     state is available via the tls_info structure:
+/* .IP tls_info->protocol
+/*     the protocol name (SSLv2, SSLv3, TLSv1),
+/* .IP tls_info->cipher_name
+/*     the cipher name (e.g. RC4/MD5),
+/* .IP tls_info->cipher_usebits
+/*     the number of bits actually used (e.g. 40),
+/* .IP tls_info->cipher_algbits
+/*     the number of bits the algorithm is based on (e.g. 128).
+/* .PP
+/*     The last two values may differ from each other when export-strength
+/*     encryption is used.
+/*
+/*     The status of the peer certificate verification is available in
+/*     tls_info->peer_verified. It is set to 1 when the certificate could
+/*     be verified.
+/*     If the peer offered a certificate, part of the certificate data are
+/*     available as:
+/* .IP tls_info->peer_subject
+/*     X509v3-oneline with the DN of the peer
+/* .IP tls_info->peer_CN
+/*     extracted CommonName of the peer
+/* .IP tls_info->peer_issuer
+/*     X509v3-oneline with the DN of the issuer
+/* .IP tls_info->issuer_CN
+/*     extracted CommonName of the issuer
+/* .IP tls_info->peer_fingerprint
+/*     fingerprint of the certificate
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+#include <unistd.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <dict.h>
+#include <stringops.h>
+#include <msg.h>
+#include <hex_code.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* TLS library. */
+
+#include <tls_mgr.h>
+#define TLS_INTERNAL
+#include <tls.h>
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+/* Application-specific. */
+
+/* We must keep some of the info available */
+static const char hexcodes[] = "0123456789ABCDEF";
+
+ /*
+  * The session_id_context indentifies the service that created a session.
+  * This information is used to distinguish between multiple TLS-based
+  * servers running on the same server. We use the name of the mail system.
+  */
+static char server_session_id_context[] = "Postfix/TLS";
+
+static int tls_server_cache = 0;
+
+/* server_verify_callback - server verification wrapper */
+
+static int server_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+    return (tls_verify_certificate_callback(ok, ctx, TLS_VERIFY_DEFAULT));
+}
+
+/* get_server_session_cb - callback to retrieve session from server cache */
+
+static SSL_SESSION *get_server_session_cb(SSL *unused_ssl,
+                                                 unsigned char *session_id,
+                                                 int session_id_length,
+                                                 int *unused_copy)
+{
+    VSTRING *cache_id;
+    VSTRING *session_data = vstring_alloc(2048);
+    SSL_SESSION *session = 0;
+
+#define MAKE_SERVER_CACHE_ID(id, len) \
+    hex_encode(vstring_alloc(2 * (len) + 1), (char *) (id), (len))
+
+    /*
+     * Encode the session ID.
+     */
+    cache_id = MAKE_SERVER_CACHE_ID(session_id, session_id_length);
+    if (var_smtpd_tls_loglevel >= 3)
+       msg_info("looking up session %s in server cache", STR(cache_id));
+
+    /*
+     * Load the session from cache and decode it.
+     */
+    if (tls_mgr_lookup(tls_server_cache, STR(cache_id),
+                      OPENSSL_VERSION_NUMBER, TLS_MGR_NO_FLAGS,
+                      session_data) == TLS_MGR_STAT_OK) {
+       session = tls_session_activate(STR(session_data), LEN(session_data));
+       if (session && (var_smtpd_tls_loglevel >= 3))
+           msg_info("reloaded session %s from server cache", STR(cache_id));
+    }
+
+    /*
+     * Clean up.
+     */
+    vstring_free(cache_id);
+    vstring_free(session_data);
+
+    return (session);
+}
+
+/* remove_server_session_cb - callback to remove session from server cache */
+
+static void remove_server_session_cb(SSL_CTX *unused_ctx, SSL_SESSION *session)
+{
+    VSTRING *cache_id;
+
+    /*
+     * Encode the session ID.
+     */
+    cache_id =
+       MAKE_SERVER_CACHE_ID(session->session_id, session->session_id_length);
+    if (var_smtpd_tls_loglevel >= 3)
+       msg_info("remove session %s from server cache", STR(cache_id));
+
+    /*
+     * Delete the session from cache.
+     */
+    tls_mgr_delete(tls_server_cache, STR(cache_id));
+
+    vstring_free(cache_id);
+}
+
+/* new_server_session_cb - callback to save session to server cache */
+
+static int new_server_session_cb(SSL *unused_ssl, SSL_SESSION *session)
+{
+    VSTRING *cache_id;
+    VSTRING *session_data;
+
+    /*
+     * Encode the session ID.
+     */
+    cache_id =
+       MAKE_SERVER_CACHE_ID(session->session_id, session->session_id_length);
+    if (var_smtpd_tls_loglevel >= 3)
+       msg_info("save session %s to server cache", STR(cache_id));
+
+    /*
+     * Passivate and save the session state.
+     */
+    session_data = tls_session_passivate(session);
+    if (session_data)
+       tls_mgr_update(tls_server_cache, STR(cache_id),
+                      OPENSSL_VERSION_NUMBER, TLS_MGR_NO_FLAGS,
+                      STR(session_data), LEN(session_data));
+
+    /*
+     * Clean up.
+     */
+    if (session_data)
+       vstring_free(session_data);
+    vstring_free(cache_id);
+
+    return (1);
+}
+
+/* tls_server_init - initialize the server-side TLS engine */
+
+SSL_CTX *tls_server_init(int unused_verifydepth, int askcert)
+{
+    int     off = 0;
+    int     verify_flags = SSL_VERIFY_NONE;
+    SSL_CTX *server_ctx;
+    int     cache_types;
+
+    /* See skeleton at OpenSSL apps/s_server.c. */
+
+    if (var_smtpd_tls_loglevel >= 2)
+       msg_info("initializing the server-side TLS engine");
+
+    /*
+     * Initialize the OpenSSL library by the book! To start with, we must
+     * initialize the algorithms. We want cleartext error messages instead of
+     * just error codes, so we load the error_strings.
+     */
+    SSL_load_error_strings();
+    OpenSSL_add_ssl_algorithms();
+
+    /*
+     * Initialize the PRNG (Pseudo Random Number Generator) with some seed
+     * from external and internal sources. Don't enable TLS without some real
+     * entropy.
+     */
+    if (tls_ext_seed(var_tls_daemon_rand_bytes) < 0) {
+       msg_warn("no entropy for TLS key generation: disabling TLS support");
+       return (0);
+    }
+    tls_int_seed();
+
+    /*
+     * The SSL/TLS specifications require the client to send a message in the
+     * oldest specification it understands with the highest level it
+     * understands in the message. Netscape communicator can still
+     * communicate with SSLv2 servers, so it sends out a SSLv2 client hello.
+     * To deal with it, our server must be SSLv2 aware (even if we don't like
+     * SSLv2), so we need to have the SSLv23 server here. If we want to limit
+     * the protocol level, we can add an option to not use SSLv2/v3/TLSv1
+     * later.
+     */
+    server_ctx = SSL_CTX_new(SSLv23_server_method());
+    if (server_ctx == NULL) {
+       tls_print_errors();
+       return (0);
+    }
+
+    /*
+     * Here we might set SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1.
+     * Of course, the last one would not make sense, since RFC2487 is only
+     * defined for TLS, but we also want to accept Netscape communicator
+     * requests, and it only supports SSLv3.
+     */
+    off |= SSL_OP_ALL;                         /* Work around all known bugs */
+    SSL_CTX_set_options(server_ctx, off);
+
+    /*
+     * Set the call-back routine for verbose logging.
+     */
+    if (var_smtpd_tls_loglevel >= 2)
+       SSL_CTX_set_info_callback(server_ctx, tls_info_callback);
+
+    /*
+     * Override the default cipher list with our own list.
+     */
+    if (*var_smtpd_tls_cipherlist != 0)
+       if (SSL_CTX_set_cipher_list(server_ctx, var_smtpd_tls_cipherlist) == 0) {
+           tls_print_errors();
+           SSL_CTX_free(server_ctx);           /* 200411 */
+           return (0);
+       }
+
+    /*
+     * Load the CA public key certificates for both the server cert and for
+     * the verification of client certificates. As provided by OpenSSL we
+     * support two types of CA certificate handling: One possibility is to
+     * add all CA certificates to one large CAfile, the other possibility is
+     * a directory pointed to by CApath, containing separate files for each
+     * CA with softlinks named after the hash values of the certificate. The
+     * first alternative has the advantage that the file is opened and read
+     * at startup time, so that you don't have the hassle to maintain another
+     * copy of the CApath directory for chroot-jail.
+     */
+    if (tls_set_ca_certificate_info(server_ctx, var_smtpd_tls_CAfile,
+                                   var_smtpd_tls_CAfile) < 0) {
+       SSL_CTX_free(server_ctx);               /* 200411 */
+       return (0);
+    }
+
+    /*
+     * Load the server public key certificate and private key from file and
+     * check whether the cert matches the key. We cannot run without (we do
+     * not support ADH anonymous Diffie-Hellman ciphers as of now). We can
+     * use RSA certificates ("cert") and DSA certificates ("dcert"), both can
+     * be made available at the same time. The CA certificates for both are
+     * handled in the same setup already finished. Which one is used depends
+     * on the cipher negotiated (that is: the first cipher listed by the
+     * client which does match the server). A client with RSA only (e.g.
+     * Netscape) will use the RSA certificate only. A client with
+     * openssl-library will use RSA first if not especially changed in the
+     * cipher setup.
+     */
+    if (tls_set_my_certificate_key_info(server_ctx, var_smtpd_tls_cert_file,
+                                       var_smtpd_tls_key_file,
+                                       var_smtpd_tls_dcert_file,
+                                       var_smtpd_tls_dkey_file) < 0) {
+       SSL_CTX_free(server_ctx);               /* 200411 */
+       return (0);
+    }
+
+    /*
+     * According to the OpenSSL documentation, temporary RSA key is needed
+     * export ciphers are in use. We have to provide one, so well, we just do
+     * it.
+     */
+    SSL_CTX_set_tmp_rsa_callback(server_ctx, tls_tmp_rsa_cb);
+
+    /*
+     * Diffie-Hellman key generation parameters can either be loaded from
+     * files (preferred) or taken from compiled in values. First, set the
+     * callback that will select the values when requested, then load the
+     * (possibly) available DH parameters from files. We are generous with
+     * the error handling, since we do have default values compiled in, so we
+     * will not abort but just log the error message.
+     */
+    SSL_CTX_set_tmp_dh_callback(server_ctx, tls_tmp_dh_cb);
+    if (*var_smtpd_tls_dh1024_param_file != 0)
+       tls_set_dh_1024_from_file(var_smtpd_tls_dh1024_param_file);
+    if (*var_smtpd_tls_dh512_param_file != 0)
+       tls_set_dh_512_from_file(var_smtpd_tls_dh512_param_file);
+
+    /*
+     * If we want to check client certificates, we have to indicate it in
+     * advance. By now we only allow to decide on a global basis. If we want
+     * to allow certificate based relaying, we must ask the client to provide
+     * one with SSL_VERIFY_PEER. The client now can decide, whether it
+     * provides one or not. We can enforce a failure of the negotiation with
+     * SSL_VERIFY_FAIL_IF_NO_PEER_CERT, if we do not allow a connection
+     * without one. In the "server hello" following the initialization by the
+     * "client hello" the server must provide a list of CAs it is willing to
+     * accept. Some clever clients will then select one from the list of
+     * available certificates matching these CAs. Netscape Communicator will
+     * present the list of certificates for selecting the one to be sent, or
+     * it will issue a warning, if there is no certificate matching the
+     * available CAs.
+     * 
+     * With regard to the purpose of the certificate for relaying, we might like
+     * a later negotiation, maybe relaying would already be allowed for other
+     * reasons, but this would involve severe changes in the internal postfix
+     * logic, so we have to live with it the way it is.
+     */
+    if (askcert)
+       verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+    SSL_CTX_set_verify(server_ctx, verify_flags, server_verify_callback);
+    if (*var_smtpd_tls_CAfile)
+       SSL_CTX_set_client_CA_list(server_ctx,
+                            SSL_load_client_CA_file(var_smtpd_tls_CAfile));
+
+    /*
+     * Initialize the session cache. In order to share cached sessions among
+     * multiple SMTP server processes, we use an external cache and set the
+     * internal cache size to a minimum value of 1. Access to the external
+     * cache is handled by the appropriate callback functions.
+     * 
+     * Set a session id context to identify to what type of server process
+     * created a session. In our case, the context is simply the name of the
+     * mail system: "Postfix/TLS".
+     */
+    SSL_CTX_sess_set_cache_size(server_ctx, 1);
+    SSL_CTX_set_timeout(server_ctx, var_smtpd_tls_scache_timeout);
+    SSL_CTX_set_session_id_context(server_ctx,
+                                  (void *) &server_session_id_context,
+                                  sizeof(server_session_id_context));
+
+    /*
+     * The session cache is implemented by the tlsmgr(8) server.
+     */
+    if (tls_mgr_policy(&cache_types) == TLS_MGR_STAT_OK
+       && (tls_server_cache = (cache_types & TLS_MGR_SCACHE_SERVER)) != 0) {
+       SSL_CTX_set_session_cache_mode(server_ctx,
+                     SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
+       SSL_CTX_sess_set_get_cb(server_ctx, get_server_session_cb);
+       SSL_CTX_sess_set_new_cb(server_ctx, new_server_session_cb);
+       SSL_CTX_sess_set_remove_cb(server_ctx, remove_server_session_cb);
+    }
+
+    /*
+     * Create a global index so that we can attach TLScontext information to
+     * SSL objects; this information is needed inside
+     * tls_verify_certificate_callback().
+     */
+    if (TLScontext_index < 0)
+       TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
+                                               NULL, NULL, NULL);
+
+    return (server_ctx);
+}
+
+ /*
+  * This is the actual startup routine for a new connection. We expect that
+  * the SMTP buffers are flushed and the "220 Ready to start TLS" was sent to
+  * the client, so that we can immediately start the TLS handshake process.
+  */
+TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
+                                      int timeout, const char *peername,
+                                      const char *peeraddr,
+                                      tls_info_t *tls_info,
+                                      int requirecert)
+{
+    int     sts;
+    int     j;
+    int     verify_flags;
+    unsigned int n;
+    TLScontext_t *TLScontext;
+    SSL_SESSION *session;
+    SSL_CIPHER *cipher;
+    X509   *peer;
+
+    if (var_smtpd_tls_loglevel >= 1)
+       msg_info("setting up TLS connection from %s[%s]", peername, peeraddr);
+
+    /*
+     * Allocate a new TLScontext for the new connection and get an SSL
+     * structure. Add the location of TLScontext to the SSL to later retrieve
+     * the information inside the tls_verify_certificate_callback().
+     *
+     * XXX Need a dedicated procedure for consistent initialization of all the
+     * fields in this structure.
+     */
+#define PEERNAME_SIZE sizeof(TLScontext->peername_save)
+
+    TLScontext = (TLScontext_t *) mymalloc(sizeof(TLScontext_t));
+    memset((char *) TLScontext, 0, sizeof(*TLScontext));
+    TLScontext->log_level = var_smtpd_tls_loglevel;
+    strncpy(TLScontext->peername_save, peername, PEERNAME_SIZE - 1);
+    TLScontext->peername_save[PEERNAME_SIZE - 1] = 0;
+    (void) lowercase(TLScontext->peername_save);
+
+    if ((TLScontext->con = (SSL *) SSL_new(server_ctx)) == NULL) {
+       msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
+       tls_print_errors();
+       myfree((char *) TLScontext);
+       return (0);
+    }
+    if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
+       msg_info("Could not set application data for 'TLScontext->con'");
+       tls_print_errors();
+       SSL_free(TLScontext->con);
+       myfree((char *) TLScontext);
+       return (0);
+    }
+
+    /*
+     * Set the verification parameters to be checked in
+     * tls_verify_certificate_callback().
+     */
+    if (requirecert) {
+       verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+       verify_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+       TLScontext->enforce_verify_errors = 1;
+       SSL_set_verify(TLScontext->con, verify_flags, server_verify_callback);
+    } else {
+       TLScontext->enforce_verify_errors = 0;
+    }
+    TLScontext->enforce_CN = 0;
+
+    /*
+     * The TLS connection is realized by a BIO_pair, so obtain the pair.
+     * 
+     * XXX There is no need to store the internal_bio handle in the TLScontext
+     * structure. It will be attached to and destroyed with TLScontext->con.
+     * The network_bio, however, needs to be freed explicitly, so we need to
+     * store its handle in TLScontext.
+     */
+    if (!BIO_new_bio_pair(&TLScontext->internal_bio, TLS_BIO_BUFSIZE,
+                         &TLScontext->network_bio, TLS_BIO_BUFSIZE)) {
+       msg_info("Could not obtain BIO_pair");
+       tls_print_errors();
+       SSL_free(TLScontext->con);
+       myfree((char *) TLScontext);
+       return (0);
+    }
+
+    /*
+     * Before really starting anything, try to seed the PRNG a little bit
+     * more.
+     */
+    tls_int_seed();
+    (void) tls_ext_seed(var_tls_daemon_rand_bytes);
+
+    /*
+     * Initialize the SSL connection to accept state. This should not be
+     * necessary anymore since 0.9.3, but the call is still in the library
+     * and maintaining compatibility never hurts.
+     */
+    SSL_set_accept_state(TLScontext->con);
+
+    /*
+     * Connect the SSL connection with the Postfix side of the BIO-pair for
+     * reading and writing.
+     */
+    SSL_set_bio(TLScontext->con, TLScontext->internal_bio,
+               TLScontext->internal_bio);
+
+    /*
+     * If the debug level selected is high enough, all of the data is dumped:
+     * 3 will dump the SSL negotiation, 4 will dump everything.
+     * 
+     * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
+     * Well there is a BIO below the SSL routines that is automatically
+     * created for us, so we can use it for debugging purposes.
+     */
+    if (var_smtpd_tls_loglevel >= 3)
+       BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
+
+    /*
+     * Start TLS negotiations. This process is a black box that invokes our
+     * call-backs for session caching and certificate verification.
+     * 
+     * Error handling: If the SSL handhake fails, we print out an error message
+     * and remove all TLS state concerning this session.
+     */
+    sts = tls_bio_accept(vstream_fileno(stream), timeout, TLScontext);
+    if (sts <= 0) {
+       msg_info("SSL_accept error from %s[%s]: %d", peername, peeraddr, sts);
+       tls_print_errors();
+       SSL_free(TLScontext->con);
+       BIO_free(TLScontext->network_bio);      /* 200411 */
+       myfree((char *) TLScontext);
+       return (0);
+    }
+    /* Only loglevel==4 dumps everything */
+    if (var_smtpd_tls_loglevel < 4)
+       BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
+
+    /*
+     * Let's see whether a peer certificate is available and what is the
+     * actual information. We want to save it for later use.
+     */
+    peer = SSL_get_peer_certificate(TLScontext->con);
+    if (peer != NULL) {
+       if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
+           tls_info->peer_verified = 1;
+
+       X509_NAME_oneline(X509_get_subject_name(peer),
+                         TLScontext->peer_subject,
+                         sizeof(TLScontext->peer_subject));
+       if (var_smtpd_tls_loglevel >= 2)
+           msg_info("subject=%s", TLScontext->peer_subject);
+       tls_info->peer_subject = TLScontext->peer_subject;
+
+       X509_NAME_oneline(X509_get_issuer_name(peer),
+                         TLScontext->peer_issuer,
+                         sizeof(TLScontext->peer_issuer));
+       if (var_smtpd_tls_loglevel >= 2)
+           msg_info("issuer=%s", TLScontext->peer_issuer);
+       tls_info->peer_issuer = TLScontext->peer_issuer;
+
+       if (X509_digest(peer, EVP_md5(), TLScontext->md, &n)) {
+           for (j = 0; j < (int) n; j++) {
+               TLScontext->fingerprint[j * 3] =
+                   hexcodes[(TLScontext->md[j] & 0xf0) >> 4];
+               TLScontext->fingerprint[(j * 3) + 1] =
+                   hexcodes[(TLScontext->md[j] & 0x0f)];
+               if (j + 1 != (int) n)
+                   TLScontext->fingerprint[(j * 3) + 2] = ':';
+               else
+                   TLScontext->fingerprint[(j * 3) + 2] = '\0';
+           }
+           if (var_smtpd_tls_loglevel >= 1)
+               msg_info("fingerprint=%s", TLScontext->fingerprint);
+           tls_info->peer_fingerprint = TLScontext->fingerprint;
+       }
+
+       TLScontext->peer_CN[0] = '\0';
+       if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
+                                      NID_commonName, TLScontext->peer_CN,
+                                      sizeof(TLScontext->peer_CN))) {
+           msg_info("Could not parse client's subject CN");
+           tls_print_errors();
+       }
+       tls_info->peer_CN = TLScontext->peer_CN;
+
+       TLScontext->issuer_CN[0] = '\0';
+       if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
+                                      NID_commonName, TLScontext->issuer_CN,
+                                      sizeof(TLScontext->issuer_CN))) {
+           msg_info("Could not parse client's issuer CN");
+           tls_print_errors();
+       }
+       if (!TLScontext->issuer_CN[0]) {
+           /* No issuer CN field, use Organization instead */
+           if (!X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
+                               NID_organizationName, TLScontext->issuer_CN,
+                                          sizeof(TLScontext->issuer_CN))) {
+               msg_info("Could not parse client's issuer Organization");
+               tls_print_errors();
+           }
+       }
+       tls_info->issuer_CN = TLScontext->issuer_CN;
+
+       if (var_smtpd_tls_loglevel >= 1) {
+           if (tls_info->peer_verified)
+               msg_info("Verified: subject_CN=%s, issuer=%s",
+                        TLScontext->peer_CN, TLScontext->issuer_CN);
+           else
+               msg_info("Unverified: subject_CN=%s, issuer=%s",
+                        TLScontext->peer_CN, TLScontext->issuer_CN);
+       }
+       X509_free(peer);
+    }
+
+    /*
+     * If this is a cached session, we have to check by hand if the cached
+     * session peer was verified.
+     */
+    if (requirecert) {
+       if (!tls_info->peer_verified || !tls_info->peer_CN) {
+           msg_info("Re-used session without peer certificate removed");
+           session = SSL_get_session(TLScontext->con);
+           SSL_CTX_remove_session(server_ctx, session);
+           SSL_free(TLScontext->con);
+           BIO_free(TLScontext->network_bio);  /* 200411 */
+           myfree((char *) TLScontext);
+           return (0);
+       }
+    }
+
+    /*
+     * Finally, collect information about protocol and cipher for logging
+     */
+    tls_info->protocol = SSL_get_version(TLScontext->con);
+    cipher = SSL_get_current_cipher(TLScontext->con);
+    tls_info->cipher_name = SSL_CIPHER_get_name(cipher);
+    tls_info->cipher_usebits = SSL_CIPHER_get_bits(cipher,
+                                              &(tls_info->cipher_algbits));
+
+    /*
+     * The TLS engine is active. Switch to the tls_timed_read/write()
+     * functions and make the TLScontext available to those functions.
+     */
+    tls_stream_start(stream, TLScontext);
+
+    if (var_smtpd_tls_loglevel >= 1)
+       msg_info("TLS connection established from %s[%s]: %s with cipher %s (%d/%d bits)",
+                peername, peeraddr,
+                tls_info->protocol, tls_info->cipher_name,
+                tls_info->cipher_usebits, tls_info->cipher_algbits);
+    tls_int_seed();
+
+    return (TLScontext);
+}
+
+#endif                                 /* USE_TLS */
diff --git a/postfix/src/tls/tls_session.c b/postfix/src/tls/tls_session.c
new file mode 100644 (file)
index 0000000..1c319dd
--- /dev/null
@@ -0,0 +1,178 @@
+/*++
+/* NAME
+/*     tls_session
+/* SUMMARY
+/*     TLS client and server session routines
+/* SYNOPSIS
+/*     #include <tls.h>
+/*
+/*     int     tls_session_stop(ctx, stream, timeout, failure, tls_info)
+/*     SSL_CTX *ctx;
+/*     VSTREAM *stream;
+/*     int     timeout;
+/*     int     failure;
+/*     tls_info_t *tls_info;
+/*
+/*     VSTRING *tls_session_passivate(session)
+/*     SSL_SESSION *session;
+/*
+/*     SSL_SESSION *tls_session_activate(session_data, session_data_len)
+/*     char    *session_data;
+/*     int     session_data_len;
+/* DESCRIPTION
+/*     tls_session_stop() implements the tls_server_shutdown()
+/*     and the tls_client_shutdown() routines.
+/*
+/*     tls_session_passivate() converts an SSL_SESSION object to
+/*     VSTRING. The result is a null pointer in case of problems,
+/*     otherwise it should be disposed of with vstring_free().
+/*
+/*     tls_session_activate() reanimates a passivated SSL_SESSION object.
+/*     The result is a null pointer in case of problems,
+/*     otherwise it should be disposed of with SSL_SESSION_free().
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <vstream.h>
+#include <msg.h>
+#include <mymalloc.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+#define STR    vstring_str
+
+/* tls_session_stop - shut down the TLS connection and reset state */
+
+void    tls_session_stop(SSL_CTX *ctx, VSTREAM *stream, int timeout,
+                                int failure, tls_info_t *tls_info)
+{
+    const char *myname = "tls_session_stop";
+    TLScontext_t *TLScontext;
+    int     retval;
+
+    /*
+     * Sanity check.
+     */
+    TLScontext = (TLScontext_t *) vstream_context(stream);
+    if (TLScontext == 0)
+       msg_panic("%s: stream has no active TLS context", myname);
+
+    /*
+     * Perform SSL_shutdown() twice, as the first attempt will send out the
+     * shutdown alert but it will not wait for the peer's shutdown alert.
+     * Therefore, when we are the first party to send the alert, we must call
+     * SSL_shutdown() again. On failure we don't want to resume the session,
+     * so we will not perform SSL_shutdown() and the session will be removed
+     * as being bad.
+     */
+    if (!failure) {
+       retval = tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
+       if (retval == 0)
+           tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
+    }
+
+    /*
+     * Free the SSL structure and the BIOs. Warning: the internal_bio is
+     * connected to the SSL structure and is automatically freed with it. Do
+     * not free it again (core dump)!! Only free the network_bio.
+     * 
+     * XXX SSL_CTX_flush_sessions() searches memory for expired sessions and
+     * removes them from memory and external cache.
+     */
+    SSL_free(TLScontext->con);
+
+    BIO_free(TLScontext->network_bio);
+    myfree((char *) TLScontext);
+    tls_stream_stop(stream);
+    SSL_CTX_flush_sessions(ctx, time(NULL));
+
+    *tls_info = tls_info_zero;
+}
+
+/* tls_session_passivate - passivate SSL_SESSION object */
+
+VSTRING *tls_session_passivate(SSL_SESSION *session)
+{
+    const char *myname = "tls_session_passivate";
+    int     estimate;
+    int     actual_size;
+    VSTRING *session_data;
+    unsigned char *ptr;
+
+    /*
+     * First, find out how much memory is needed for the passivated
+     * SSL_SESSION object.
+     */
+    estimate = i2d_SSL_SESSION(session, (unsigned char **) 0);
+    if (estimate <= 0) {
+       msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname);
+       return (0);
+    }
+
+    /*
+     * Passivate the SSL_SESSION object. The use of a VSTRING is slightly
+     * wasteful but is convenient to combine data and length.
+     */
+    session_data = vstring_alloc(estimate);
+    ptr = (unsigned char *) STR(session_data);
+    actual_size = i2d_SSL_SESSION(session, &ptr);
+    if (actual_size != estimate) {
+       msg_warn("%s: i2d_SSL_SESSION failed: unable to cache session", myname);
+       vstring_free(session_data);
+       return (0);
+    }
+    VSTRING_AT_OFFSET(session_data, actual_size);      /* XXX not public */
+
+    return (session_data);
+}
+
+/* tls_session_activate - activate passivated session */
+
+SSL_SESSION *tls_session_activate(char *session_data, int session_data_len)
+{
+    SSL_SESSION *session;
+    unsigned char *ptr;
+
+    /*
+     * Activate the SSL_SESSION object.
+     */
+    ptr = (unsigned char *) session_data;
+    session = d2i_SSL_SESSION((SSL_SESSION **) 0, &ptr, session_data_len);
+    if (!session)
+       tls_print_errors();
+
+    return (session);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_stream.c b/postfix/src/tls/tls_stream.c
new file mode 100644 (file)
index 0000000..5a013f3
--- /dev/null
@@ -0,0 +1,134 @@
+/*++
+/* NAME
+/*     tls_stream
+/* SUMMARY
+/*     VSTREAM over TLS
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     void    tls_stream_start(stream, context)
+/*     VSTREAM *stream;
+/*     TLScontext_t *context;
+/*
+/*     void    tls_stream_stop(stream)
+/*     VSTREAM *stream;
+/* DESCRIPTION
+/*     This module implements the VSTREAM over TLS support user interface.
+/*     The hard work is done elsewhere.
+/*
+/*     tls_stream_start() enables TLS on the named stream. All read
+/*     and write operations are directed through the TLS library,
+/*     using the state information specified with the context argument.
+/*
+/*     tls_stream_stop() replaces the VSTREAM read/write routines
+/*     by dummies that have no side effects, and deletes the
+/*     VSTREAM's reference to the TLS context.
+/* SEE ALSO
+/*     dummy_read(3), placebo read routine
+/*     dummy_write(3), placebo write routine
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Based on code that was originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* Utility library. */
+
+#include <iostuff.h>
+#include <vstream.h>
+#include <msg.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* tls_timed_read - read content from stream, then TLS decapsulate */
+
+static int tls_timed_read(int fd, void *buf, unsigned len, int timeout,
+                                 void *context)
+{
+    char   *myname = "tls_timed_read";
+    int     ret;
+    TLScontext_t *TLScontext;
+
+    TLScontext = (TLScontext_t *) context;
+    if (!TLScontext)
+       msg_panic("%s: no context", myname);
+
+    ret = tls_bio_read(fd, buf, len, timeout, TLScontext);
+    if (ret > 0 && TLScontext->log_level >= 4)
+       msg_info("Read %d chars: %.*s",
+                ret, ret > 40 ? 40 : ret, (char *) buf);
+    return (ret);
+}
+
+/* tls_timed_write - TLS encapsulate content, then write to stream */
+
+static int tls_timed_write(int fd, void *buf, unsigned len, int timeout,
+                                  void *context)
+{
+    const char *myname = "tls_timed_write";
+    TLScontext_t *TLScontext;
+
+    TLScontext = (TLScontext_t *) context;
+    if (!TLScontext)
+       msg_panic("%s: no context", myname);
+
+    if (TLScontext->log_level >= 4)
+       msg_info("Write %d chars: %.*s",
+                len, (int) (len > 40 ? 40 : len), (char *) buf);
+    return (tls_bio_write(fd, buf, len, timeout, TLScontext));
+}
+
+/* tls_stream_start - start VSTREAM over TLS */
+
+void    tls_stream_start(VSTREAM *stream, TLScontext_t * context)
+{
+    vstream_control(stream,
+                   VSTREAM_CTL_READ_FN, tls_timed_read,
+                   VSTREAM_CTL_WRITE_FN, tls_timed_write,
+                   VSTREAM_CTL_CONTEXT, (void *) context,
+                   VSTREAM_CTL_END);
+}
+
+/* tls_stream_stop - stop VSTREAM over TLS */
+
+void    tls_stream_stop(VSTREAM *stream)
+{
+
+    /*
+     * Prevent data leakage after TLS is turned off. The Postfix/TLS patch
+     * provided null function pointers; we use dummy routines that make less
+     * noise when used.
+     */
+    vstream_control(stream,
+                   VSTREAM_CTL_READ_FN, dummy_read,
+                   VSTREAM_CTL_WRITE_FN, dummy_write,
+                   VSTREAM_CTL_CONTEXT, (void *) 0,
+                   VSTREAM_CTL_END);
+}
+
+#endif
diff --git a/postfix/src/tls/tls_temp.c b/postfix/src/tls/tls_temp.c
new file mode 100644 (file)
index 0000000..a75d8ef
--- /dev/null
@@ -0,0 +1,49 @@
+/*++
+/* NAME
+/*     tls_temp 3
+/* SUMMARY
+/*     code that is to be replaced
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/* DESCRIPTION
+/*     As the summary says.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+const tls_info_t tls_info_zero = {
+    0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
+};
+
+#endif
diff --git a/postfix/src/tls/tls_verify.c b/postfix/src/tls/tls_verify.c
new file mode 100644 (file)
index 0000000..2d4fb09
--- /dev/null
@@ -0,0 +1,282 @@
+/*++
+/* NAME
+/*     tls_verify 3
+/* SUMMARY
+/*     peer name and peer certificate verification
+/* SYNOPSIS
+/*     #define TLS_INTERNAL
+/*     #include <tls.h>
+/*
+/*     int     tls_verify_certificate_callback(ok, ctx, int flags)
+/*     int     ok;
+/*     X509_STORE_CTX *ctx;
+/*     int     flags;
+/* DESCRIPTION
+/*     tls_verify_callback() is called several times (directly or
+/*     indirectly) from crypto/x509/x509_vfy.c. It is called as
+/*     a final check, and if it returns "0", the handshake is
+/*     immediately shut down and the connection fails.
+/*
+/*     Postfix/TLS has two modes, the "opportunistic" mode and
+/*     the "enforce" mode:
+/*
+/*     In the "opportunistic" mode we never want the connection
+/*     to fail just because there is something wrong with the
+/*     peer's certificate. After all, we would have sent or received
+/*     the mail even if TLS weren't available.  Therefore the
+/*     return value is always "1".
+/*
+/*     The SMTP client or server may require TLS (e.g. to protect
+/*     passwords), while peer certificates are optional.  In this
+/*     case we must return "1" even when we are unhappy with the
+/*     peer certificate.  Only when peer certificates are required,
+/*      certificate verification failure will result in immediate
+/*     termination (return 0).
+/*
+/*     The SMTP client will attempt to verify the server hostname
+/*     against the names listed in the server certificate. When
+/*     a hostname match is required, the verification fails
+/*     on certificate verification or hostname mis-match errors.
+/*     When no hostname match is required, hostname verification
+/*     failures are logged but they do not affect the TLS handshake
+/*     or the SMTP session.
+/*
+/*     The rules for peer name wild-card matching differ between
+/*     RFC 2818 (HTTP over TLS) and RFC 2830 (LDAP over TLS), while
+/*     RFC RFC3207 (SMTP over TLS) does not specify a rule at all.
+/*     Postfix uses a restrictive match algorithm. One asterisk
+/*     ('*') is allowed as the left-most component of a wild-card
+/*     certificate name; it matches the left-most component of
+/*     the peer hostname.
+/*
+/*     Another area where RFCs aren't always explicit is the
+/*     handling of dNSNames in peer certificates. RFC 3207 (SMTP
+/*     over TLS) does not mention dNSNames. Postfix follows the
+/*     strict rules in RFC 2818 (HTTP over TLS), section 3.1: The
+/*     Subject Alternative Name/dNSName has precedence over
+/*     CommonName.  If at least one dNSName is provided, Postfix
+/*     verifies those against the peer hostname and ignores the
+/*     CommonName, otherwise Postfix verifies the CommonName
+/*     against the peer hostname.
+/*
+/*     The only error condition not handled inside the OpenSSL
+/*     library is the case of a too-long certificate chain. We
+/*     test for this condition only if "ok = 1", that is, if
+/*     verification didn't fail because of some earlier problem.
+/*
+/*     Arguments:
+/* .IP ok
+/*     Result of prior verification: non-zero means success.  In
+/*     order to reduce the noise level, some tests or error reports
+/*     are disabled when verification failed because of some
+/*     earlier problem.
+/* .IP ctx
+/*     TLS client or server context. This also specifies the
+/*     TLScontext with enforcement options.
+/* .IP flags
+/* .RS
+/* .IP TLS_VERIFY_PEERNAME
+/*     Verify the peer hostname against the names listed
+/*     in the peer certificate. The peer hostname is specified
+/*     via the ctx argument.
+/* .RE
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Originally written by:
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Updated by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+#ifdef USE_TLS
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* match_hostname -  match hostname against pattern */
+
+static int match_hostname(const char *pattern, const char *hostname)
+{
+    char   *peername_left;
+
+    return (strcasecmp(hostname, pattern) == 0
+           || (pattern[0] == '*' && pattern[1] == '.' && pattern[2] != 0
+               && (peername_left = strchr(hostname, '.')) != 0
+               && strcasecmp(peername_left + 1, pattern + 2) == 0));
+}
+
+/* tls_verify_certificate_callback - verify peer certificate info */
+
+int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx, int flags)
+{
+    char    buf[1024];
+    X509   *err_cert;
+    int     err;
+    int     depth;
+    int     verify_depth;
+    SSL    *con;
+    TLScontext_t *TLScontext;
+
+    /* Adapted from OpenSSL apps/s_cb.c */
+
+    err_cert = X509_STORE_CTX_get_current_cert(ctx);
+    err = X509_STORE_CTX_get_error(ctx);
+    depth = X509_STORE_CTX_get_error_depth(ctx);
+
+    con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+    TLScontext = SSL_get_ex_data(con, TLScontext_index);
+
+    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+    if (TLScontext->log_level >= 2)
+       msg_info("certificate verification depth=%d subject=%s", depth, buf);
+
+    /*
+     * Test for a too long certificate chain, because that error condition is
+     * not handled by the OpenSSL library.
+     */
+    verify_depth = SSL_get_verify_depth(con);
+    if (ok && (verify_depth >= 0) && (depth > verify_depth)) {
+       ok = 0;
+       err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+       X509_STORE_CTX_set_error(ctx, err);
+    }
+    if (!ok) {
+       msg_info("certificate verification failed for %s: num=%d:%s",
+                TLScontext->peername_save, err,
+                X509_verify_cert_error_string(err));
+    }
+
+    /*
+     * Match the peer hostname against the names listed in the peer
+     * certificate.
+     */
+    if (ok && (depth == 0) && (flags & TLS_VERIFY_PEERNAME)) {
+       int     i,
+               r;
+       int     hostname_matched;
+       int     dNSName_found;
+
+       STACK_OF(GENERAL_NAME) * gens;
+
+       /*
+        * Verify the name(s) in the peer certificate against the peer
+        * hostname. Log peer hostname/certificate mis-matches. If a match is
+        * required but fails, bail out with a verification error.
+        */
+       hostname_matched = dNSName_found = 0;
+
+       gens = X509_get_ext_d2i(err_cert, NID_subject_alt_name, 0, 0);
+       if (gens) {
+           for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) {
+               const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+
+               if (gn->type == GEN_DNS) {
+                   dNSName_found++;
+                   if ((hostname_matched =
+                        match_hostname((char *) gn->d.ia5->data,
+                                       TLScontext->peername_save)))
+                       break;
+               }
+           }
+           sk_GENERAL_NAME_free(gens);
+       }
+       if (dNSName_found) {
+           if (!hostname_matched)
+               msg_info("certificate peer name verification failed for %s: "
+                      "%d dNSNames in certificate found, but none matches",
+                        TLScontext->peername_save, dNSName_found);
+       } else {
+           buf[0] = '\0';
+           if (!X509_NAME_get_text_by_NID(X509_get_subject_name(err_cert),
+                                       NID_commonName, buf, sizeof(buf))) {
+               msg_info("certificate peer name verification failed for %s:"
+                        "cannot parse subject CommonName",
+                        TLScontext->peername_save);
+               tls_print_errors();
+           } else {
+               hostname_matched = match_hostname(buf,
+                                                 TLScontext->peername_save);
+               if (!hostname_matched)
+                   msg_info("certificate peer name verification failed for %s:"
+                            " CommonName mis-match: %s",
+                            TLScontext->peername_save, buf);
+           }
+       }
+
+       if (!hostname_matched) {
+           if (TLScontext->enforce_verify_errors && TLScontext->enforce_CN) {
+               err = X509_V_ERR_CERT_REJECTED;
+               X509_STORE_CTX_set_error(ctx, err);
+               msg_info("certificate peer name verification failed for %s:"
+                        " hostname mismatch", TLScontext->peername_save);
+               ok = 0;
+           }
+       } else
+           TLScontext->hostname_matched = 1;
+    }
+
+    /*
+     * Other causes for verification failure.
+     */
+    switch (ctx->error) {
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+       X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
+                         buf, sizeof(buf));
+       msg_info("certificate verification failed for %s:"
+                "issuer %s certificate unavailable",
+                TLScontext->peername_save, buf);
+       break;
+    case X509_V_ERR_CERT_NOT_YET_VALID:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+       msg_info("certificate verification failed for %s:"
+                "certificate not yet valid",
+                TLScontext->peername_save);
+       break;
+    case X509_V_ERR_CERT_HAS_EXPIRED:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+       msg_info("certificate verification failed for %s:"
+                "certificate has expired",
+                TLScontext->peername_save);
+       break;
+    }
+    if (TLScontext->log_level >= 2)
+       msg_info("verify return: %d", ok);
+
+    /*
+     * Never fail in case of opportunistic mode.
+     */
+    if (TLScontext->enforce_verify_errors)
+       return (ok);
+    else
+       return (1);
+}
+
+#endif
diff --git a/postfix/src/tlsmgr/.indent.pro b/postfix/src/tlsmgr/.indent.pro
new file mode 120000 (symlink)
index 0000000..5c837ec
--- /dev/null
@@ -0,0 +1 @@
+../../.indent.pro
\ No newline at end of file
diff --git a/postfix/src/tlsmgr/Makefile.in b/postfix/src/tlsmgr/Makefile.in
new file mode 100644 (file)
index 0000000..ddfd530
--- /dev/null
@@ -0,0 +1,78 @@
+SHELL  = /bin/sh
+SRCS   = tlsmgr.c
+OBJS   = tlsmgr.o
+HDRS   = 
+TESTSRC        = smtpd_token_test.c
+DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG= 
+PROG   = tlsmgr
+INC_DIR        = ../../include
+LIBS   = ../../lib/libmaster.a ../../lib/libtls.a ../../lib/libglobal.a \
+       ../../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+       $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+Makefile: Makefile.in
+       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+
+test:  $(TESTPROG)
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+       cp $(PROG) ../../libexec
+
+printfck: $(OBJS) $(PROG)
+       rm -rf printfck
+       mkdir printfck
+       cp *.h printfck
+       sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+       set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+       cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+       lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+       rm -f *.o *core $(PROG) $(TESTPROG) junk *.db *.out *.tmp
+       rm -rf printfck
+
+tidy:  clean
+
+depend: $(MAKES)
+       (sed '1,/^# do not edit/!d' Makefile.in; \
+       set -e; for i in [a-z][a-z0-9]*.c; do \
+           $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+           -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
+       done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+tests:
+
+# do not edit below this line - it is generated by 'make depend'
+tlsmgr.o: tlsmgr.c
+tlsmgr.o: ../../include/sys_defs.h
+tlsmgr.o: ../../include/msg.h
+tlsmgr.o: ../../include/events.h
+tlsmgr.o: ../../include/stringops.h
+tlsmgr.o: ../../include/vstring.h
+tlsmgr.o: ../../include/vbuf.h
+tlsmgr.o: ../../include/mymalloc.h
+tlsmgr.o: ../../include/iostuff.h
+tlsmgr.o: ../../include/vstream.h
+tlsmgr.o: ../../include/vstring_vstream.h
+tlsmgr.o: ../../include/attr.h
+tlsmgr.o: ../../include/mail_conf.h
+tlsmgr.o: ../../include/mail_params.h
+tlsmgr.o: ../../include/tls_mgr.h
+tlsmgr.o: ../../include/mail_proto.h
+tlsmgr.o: ../../include/master_proto.h
+tlsmgr.o: ../../include/mail_server.h
+tlsmgr.o: ../../include/tls_prng.h
+tlsmgr.o: ../../include/tls_scache.h
+tlsmgr.o: ../../include/dict.h
+tlsmgr.o: ../../include/argv.h
diff --git a/postfix/src/tlsmgr/tlsmgr.c b/postfix/src/tlsmgr/tlsmgr.c
new file mode 100644 (file)
index 0000000..8afb684
--- /dev/null
@@ -0,0 +1,918 @@
+/*++
+/* NAME
+/*     tlsmgr 8
+/* SUMMARY
+/*     Postfix TLS session cache and PRNG manager
+/* SYNOPSIS
+/*     \fBtlsmgr\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/*     The tlsmgr(8) maintains the TLS session caches for Postfix
+/*     SMTP client and server processes.  It periodically removes
+/*     entries that have expired, and entries that are no longer
+/*     compatible with the currently running Postfix version.
+/*
+/*     The tlsmgr(8) also maintains the PRNG (pseudo random number
+/*     generator) pool. This is queried by the smtpd(8) and smtp(8)
+/*     processes to seed their internal PRNG pools.
+/*
+/*     The tlsmgr(8)'s internal PRNG pool is initially seeded from
+/*     an external source (EGD, /dev/urandom, or regular file).
+/*     It is updated at configurable pseudo-random intervals with
+/*     data from the external source. It is updated periodically
+/*     with data from TLS session cache entries and with the time
+/*     of day, and is updated with the time of day whenever a
+/*     process requests tlsmgr(8) service.
+/*
+/*     The tlsmgr(8) saves the PRNG state to an exchange file
+/*     periodically and when the process terminates, and reads
+/*     the exchange file when initializing its PRNG.
+/* SECURITY
+/* .ad
+/* .fi
+/*     tlsmgr(8) is not security-sensitive. The code that maintains
+/*     the external and internal PRNG pools does not "trust" the
+/*     data that it manipulates, and the code that maintains the
+/*     TLS session cache does not touch the contents of the cached
+/*     entries, except for seeding its internal PRNG pool.
+/*
+/*     The tlsmgr(8) can be run chrooted and with reduced privileges.
+/*     At process startup it connects to the entropy source and
+/*     exchange file, and creates or truncates the optional TLS
+/*     session cache files.
+/* DIAGNOSTICS
+/*     Problems and transactions are logged to the syslog daemon.
+/* BUGS
+/*     There is no automatic means to limit the number of entries in the
+/*     TLS session caches and/or the size of the TLS cache files.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/*     Changes to \fBmain.cf\fR are not picked up automatically,
+/*     because tlsmgr(8) is a persistent processes.  Use the
+/*     command "\fBpostfix reload\fR" after a configuration change.
+/*
+/*     The text below provides only a parameter summary. See
+/*     postconf(5) for more details including examples.
+/* TLS SESSION CACHE
+/* .ad
+/* .fi
+/* .IP "\fBsmtpd_tls_session_cache_database (empty)\fR"
+/*     Name of the file containing the optional Postfix SMTP server
+/*     TLS session cache.
+/* .IP "\fBsmtpd_tls_session_cache_timeout (3600s)\fR"
+/*     The expiration time of Postfix SMTP server TLS session cache
+/*     information.
+/* .IP "\fBsmtp_tls_session_cache_database (empty)\fR"
+/*     Name of the file containing the optional Postfix SMTP client
+/*     TLS session cache.
+/* .IP "\fBsmtp_tls_session_cache_timeout (3600s)\fR"
+/*     The expiration time of Postfix SMTP client TLS session cache
+/*     information.
+/* PSEUDO RANDOM NUMBER GENERATOR
+/* .ad
+/* .fi
+/* .IP "\fBtls_random_source (see 'postconf -d' output)\fR"
+/*     The external entropy source for the in-memory tlsmgr(8) pseudo
+/*     random number generator (PRNG) pool.
+/* .IP "\fBtls_random_bytes (32)\fR"
+/*     The number of bytes that tlsmgr(8) reads from $tls_random_source
+/*     when (re)seeding the in-memory pseudo random number generator (PRNG)
+/*     pool.
+/* .IP "\fBtls_random_exchange_name (${config_directory}/prng_exch)\fR"
+/*     Name of the pseudo random number generator (PRNG) state file
+/*     that is maintained by tlsmgr(8).
+/* .IP "\fBtls_random_prng_update_period (3600s)\fR"
+/*     The time between attempts by tlsmgr(8) to save the state of
+/*     the pseudo random number generator (PRNG) to the file specified
+/*     with $tls_random_exchange_name.
+/* .IP "\fBtls_random_reseed_period (3600s)\fR"
+/*     The maximal time between attempts by tlsmgr(8) to re-seed the
+/*     in-memory pseudo random number generator (PRNG) pool from external
+/*     sources.
+/* MISCELLANEOUS CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+/*     The default location of the Postfix main.cf and master.cf
+/*     configuration files.
+/* .IP "\fBdaemon_timeout (18000s)\fR"
+/*     How much time a Postfix daemon process may take to handle a
+/*     request before it is terminated by a built-in watchdog timer.
+/* .IP "\fBprocess_id (read-only)\fR"
+/*     The process ID of a Postfix command or daemon process.
+/* .IP "\fBprocess_name (read-only)\fR"
+/*     The process name of a Postfix command or daemon process.
+/* .IP "\fBsyslog_facility (mail)\fR"
+/*     The syslog facility of Postfix logging.
+/* .IP "\fBsyslog_name (postfix)\fR"
+/*     The mail system name that is prepended to the process name in syslog
+/*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/* SEE ALSO
+/*     smtp(8) Postfix SMTP client
+/*     smtpd(8) Postfix SMTP server
+/*     postconf(5), configuration parameters
+/*     master(5), generic daemon options
+/*     master(8), process manager
+/*     syslogd(8), system logging
+/* README FILES
+/* .ad
+/* .fi
+/*     Use "\fBpostconf readme_directory\fR" or
+/*     "\fBpostconf html_directory\fR" to locate this information.
+/* .na
+/* .nf
+/*     TLS_README, Postfix TLS configuration and operation
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Lutz Jaenicke
+/*     BTU Cottbus
+/*     Allgemeine Elektrotechnik
+/*     Universitaetsplatz 3-4
+/*     D-03044 Cottbus, Germany
+/*
+/*     Adapted by:
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>                  /* gettimeofday, not POSIX */
+#include <limits.h>
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 0xff
+#endif
+
+/* OpenSSL library. */
+
+#ifdef USE_TLS
+#include <openssl/rand.h>              /* For the PRNG */
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <events.h>
+#include <stringops.h>
+#include <mymalloc.h>
+#include <iostuff.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <vstring_vstream.h>
+#include <attr.h>
+
+/* Global library. */
+
+#include <mail_conf.h>
+#include <mail_params.h>
+#include <tls_mgr.h>
+#include <mail_proto.h>
+
+/* Master process interface. */
+
+#include <master_proto.h>
+#include <mail_server.h>
+
+/* TLS library. */
+
+#ifdef USE_TLS
+#include <tls_prng.h>
+#include <tls_scache.h>
+
+/* Application-specific. */
+
+ /*
+  * Tunables.
+  */
+char   *var_tls_rand_source;
+int     var_tls_rand_bytes;
+int     var_tls_reseed_period;
+int     var_tls_prng_exch_period;
+
+ /*
+  * Bound the time that we are willing to wait for an I/O operation. This
+  * produces better error messages than waiting until the watchdog timer
+  * kills the process.
+  */
+#define TLS_MGR_TIMEOUT        10
+
+ /*
+  * State for updating the PRNG exchange file.
+  */
+static TLS_PRNG_SRC *rand_exch;
+
+ /*
+  * State for seeding the internal PRNG from external source.
+  */
+static TLS_PRNG_SRC *rand_source_dev;
+static TLS_PRNG_SRC *rand_source_egd;
+static TLS_PRNG_SRC *rand_source_file;
+
+ /*
+  * The external entropy source type is encoded in the source name. The
+  * obvious alternative is to have separate configuration parameters per
+  * source type, so that one process can query multiple external sources.
+  */
+#define DEV_PREF "dev:"
+#define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
+#define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
+
+#define EGD_PREF "egd:"
+#define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
+#define EGD_PATH(egd) ((egd) + EGD_PREF_LEN)
+
+ /*
+  * State for TLS client and server session caches.
+  */
+static TLS_SCACHE *clnt_scache_info;   /* cache handle */
+static int clnt_scache_active;         /* scan in progress */
+
+static TLS_SCACHE *srvr_scache_info;   /* cache handle */
+static int srvr_scache_active;         /* scan in progress */
+
+#define WHICH_CACHE_INFO(type) \
+    (type == TLS_MGR_SCACHE_CLIENT ? clnt_scache_info : \
+       type == TLS_MGR_SCACHE_SERVER ? srvr_scache_info : 0)
+
+ /*
+  * SLMs.
+  */
+#define STR(x)         vstring_str(x)
+#define LEN(x)         VSTRING_LEN(x)
+#define STREQ(x, y)    (strcmp((x), (y)) == 0)
+
+/* tlsmgr_prng_exch_event - update PRNG exchange file */
+
+static void tlsmgr_prng_exch_event(int unused_event, char *dummy)
+{
+    const char *myname = "tlsmgr_prng_exch_event";
+    unsigned char randbyte;
+    int     next_period;
+    struct stat st;
+
+    if (msg_verbose)
+       msg_info("%s: update PRNG exchange file", myname);
+
+    /*
+     * Sanity check. If the PRNG exchange file was removed, there is no point
+     * updating it further. Restart the process and update the new file.
+     */
+    if (fstat(rand_exch->fd, &st) < 0)
+       msg_fatal("cannot fstat() the PRNG exchange file: %m");
+    if (st.st_nlink == 0) {
+       msg_warn("PRNG exchange file was removed -- exiting to reopen");
+       sleep(1);
+       exit(0);
+    }
+    tls_prng_exch_update(rand_exch);
+
+    /*
+     * Make prediction difficult for outsiders and calculate the time for the
+     * next execution randomly.
+     */
+    RAND_bytes(&randbyte, 1);
+    next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
+    event_request_timer(tlsmgr_prng_exch_event, dummy, next_period);
+}
+
+/* tlsmgr_reseed_event - re-seed the internal PRNG pool */
+
+static void tlsmgr_reseed_event(int unused_event, char *dummy)
+{
+    int     next_period;
+    unsigned char randbyte;
+    int     must_exit = 0;
+
+    /*
+     * Reseed the internal PRNG from external source. Errors are recoverable.
+     * We simply restart and reconnect without making a fuss. This is OK
+     * because we do require that exchange file updates succeed. The exchange
+     * file is the only entropy source that really matters in the long term.
+     * 
+     * If the administrator specifies an external randomness source that we
+     * could not open upon start-up, restart to see if we can open it now
+     * (and log a nagging warning if we can't).
+     */
+    if (*var_tls_rand_source) {
+
+       /*
+        * Source is a random device.
+        */
+       if (rand_source_dev) {
+           if (tls_prng_dev_read(rand_source_dev, var_tls_rand_bytes) <= 0) {
+               msg_info("cannot read from entropy device %s: %m -- "
+                        "exiting to reopen", DEV_PATH(var_tls_rand_source));
+               must_exit = 1;
+           }
+       }
+
+       /*
+        * Source is an EGD compatible socket.
+        */
+       else if (rand_source_egd) {
+           if (tls_prng_egd_read(rand_source_egd, var_tls_rand_bytes) <= 0) {
+               msg_info("lost connection to EGD server %s -- "
+                    "exiting to reconnect", EGD_PATH(var_tls_rand_source));
+               must_exit = 1;
+           }
+       }
+
+       /*
+        * Source is a regular file. Read the content once and close the
+        * file.
+        */
+       else if (rand_source_file) {
+           if (tls_prng_file_read(rand_source_file, var_tls_rand_bytes) <= 0)
+               msg_warn("cannot read from entropy file %s: %m",
+                        var_tls_rand_source);
+           tls_prng_file_close(rand_source_file);
+           rand_source_file = 0;
+           var_tls_rand_source[0] = 0;
+       }
+
+       /*
+        * Could not open the external source upon start-up. See if we can
+        * open it this time. Save PRNG state before we exit.
+        */
+       else {
+           msg_info("exiting to reopen external entropy source %s",
+                    var_tls_rand_source);
+           must_exit = 1;
+       }
+    }
+
+    /*
+     * Save PRNG state in case we must exit.
+     */
+    if (must_exit) {
+       if (rand_exch)
+           tls_prng_exch_update(rand_exch);
+       sleep(1);
+       exit(0);
+    }
+
+    /*
+     * Make prediction difficult for outsiders and calculate the time for the
+     * next execution randomly.
+     */
+    RAND_bytes(&randbyte, 1);
+    next_period = (var_tls_reseed_period * randbyte) / UCHAR_MAX;
+    event_request_timer(tlsmgr_reseed_event, dummy, next_period);
+}
+
+/* tlsmgr_clnt_cache_run_event - start SMTP client TLS session cache scan */
+
+static void tlsmgr_clnt_cache_run_event(int unused_event, char *dummy)
+{
+    const char *myname = "tlsmgr_clnt_cache_run_event";
+
+    /*
+     * This routine runs when it is time for another TLS session cache scan.
+     * Make sure this routine gets called again in the future.
+     * 
+     * Don't start a new scan when the timer goes off while cache cleanup is
+     * still in progress.
+     */
+    if (var_smtp_tls_loglevel >= 3)
+       msg_info("%s: start TLS client session cache cleanup", myname);
+
+    if (clnt_scache_active == 0)
+       clnt_scache_active =
+           tls_scache_sequence(clnt_scache_info, DICT_SEQ_FUN_FIRST,
+                               TLS_SCACHE_SEQUENCE_NOTHING);
+
+    event_request_timer(tlsmgr_clnt_cache_run_event, dummy,
+                       var_smtp_tls_scache_timeout);
+}
+
+/* tlsmgr_srvr_cache_run_event - start SMTP server TLS session cache scan */
+
+static void tlsmgr_srvr_cache_run_event(int unused_event, char *dummy)
+{
+    const char *myname = "tlsmgr_srvr_cache_run_event";
+
+    /*
+     * This routine runs when it is time for another TLS session cache scan.
+     * Make sure this routine gets called again in the future.
+     * 
+     * Don't start a new scan when the timer goes off while cache cleanup is
+     * still in progress.
+     */
+    if (var_smtpd_tls_loglevel >= 3)
+       msg_info("%s: start TLS server session cache cleanup", myname);
+
+    if (srvr_scache_active == 0)
+       srvr_scache_active =
+           tls_scache_sequence(srvr_scache_info, DICT_SEQ_FUN_FIRST,
+                               TLS_SCACHE_SEQUENCE_NOTHING);
+
+    event_request_timer(tlsmgr_srvr_cache_run_event, dummy,
+                       var_smtpd_tls_scache_timeout);
+}
+
+/* tlsmgr_loop - TLS manager main loop */
+
+static int tlsmgr_loop(char *unused_name, char **unused_argv)
+{
+    struct timeval tv;
+
+    /*
+     * Update the PRNG pool with the time of day. We do it here after every
+     * event (including internal timer events and external client request
+     * events), instead of doing it in individual event call-back routines.
+     */
+    GETTIMEOFDAY(&tv);
+    RAND_seed(&tv, sizeof(struct timeval));
+
+    /*
+     * This routine runs as part of the event handling loop, after the event
+     * manager has delivered a timer or I/O event, or after it has waited for
+     * a specified amount of time. The result value of tlsmgr_loop()
+     * specifies how long the event manager should wait for the next event.
+     * 
+     * We use this loop to interleave TLS session cache cleanup with other
+     * activity. Interleaved processing is needed when we use a client-server
+     * protocol for entropy and session state exchange with smtp(8) and
+     * smtpd(8) processes.
+     */
+#define DONT_WAIT      0
+#define WAIT_FOR_EVENT (-1)
+
+    if (clnt_scache_active)
+       clnt_scache_active =
+           tls_scache_sequence(clnt_scache_info, DICT_SEQ_FUN_NEXT,
+                               TLS_SCACHE_SEQUENCE_NOTHING);
+    if (srvr_scache_active)
+       srvr_scache_active =
+           tls_scache_sequence(srvr_scache_info, DICT_SEQ_FUN_NEXT,
+                               TLS_SCACHE_SEQUENCE_NOTHING);
+
+    if (clnt_scache_active || srvr_scache_active)
+       return (DONT_WAIT);
+    return (WAIT_FOR_EVENT);
+}
+
+/* tlsmgr_request_receive - receive request */
+
+static int tlsmgr_request_receive(VSTREAM *client_stream, VSTRING *request)
+{
+    int     count;
+
+    /*
+     * Kluge: choose the protocol depending on the request size.
+     */
+    if (read_wait(vstream_fileno(client_stream), var_ipc_timeout) < 0) {
+       msg_warn("timeout while waiting for data from %s",
+                VSTREAM_PATH(client_stream));
+       return (-1);
+    }
+    if ((count = peekfd(vstream_fileno(client_stream))) < 0) {
+       msg_warn("cannot examine read buffer of %s: %m",
+                VSTREAM_PATH(client_stream));
+       return (-1);
+    }
+
+    /*
+     * Short request: master trigger. Use the string+null protocol.
+     */
+    if (count <= 2) {
+       if (vstring_get_null(request, client_stream) == VSTREAM_EOF) {
+           msg_warn("end-of-input while reading request from %s: %m",
+                    VSTREAM_PATH(client_stream));
+           return (-1);
+       }
+    }
+
+    /*
+     * Long request: real tlsmgr client. Use the attribute list protocol.
+     */
+    else {
+       if (attr_scan(client_stream,
+                     ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
+                     ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, request,
+                     ATTR_TYPE_END) != 1) {
+           return (-1);
+       }
+    }
+    return (0);
+}
+
+/* tlsmgr_service - respond to external request */
+
+static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
+                                  char **argv)
+{
+    static VSTRING *request = 0;
+    static VSTRING *cache_id = 0;
+    static VSTRING *buffer = 0;
+    int     cache_type;
+    int     len;
+    long    openssl_vsn;
+    int     flags;
+    static char wakeup[] = {           /* master wakeup request */
+       TRIGGER_REQ_WAKEUP,
+       0,
+    };
+    TLS_SCACHE *cache;
+    int     status = TLS_MGR_STAT_FAIL;
+
+    /*
+     * Sanity check. This service takes no command-line arguments.
+     */
+    if (argv[0])
+       msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+    /*
+     * Initialize. We're select threaded, so we can use static buffers.
+     */
+    if (request == 0) {
+       request = vstring_alloc(10);
+       cache_id = vstring_alloc(10);
+       buffer = vstring_alloc(10);
+    }
+
+    /*
+     * This routine runs whenever a client connects to the socket dedicated
+     * to the tlsmgr service (including wake up events sent by the master).
+     * All connection-management stuff is handled by the common code in
+     * multi_server.c.
+     */
+    if (tlsmgr_request_receive(client_stream, request) == 0) {
+
+       /*
+        * Load session from cache.
+        */
+       if (STREQ(STR(request), TLS_MGR_REQ_LOOKUP)) {
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                       ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_LONG, TLS_MGR_ATTR_VERSION, &openssl_vsn,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_FLAGS, &flags,
+                         ATTR_TYPE_END) == 4) {
+               if ((cache = WHICH_CACHE_INFO(cache_type)) == 0) {
+                   msg_warn("bogus cache type \"%d\" in \"%s\" request",
+                            cache_type, TLS_MGR_REQ_LOOKUP);
+                   VSTRING_RESET(buffer);
+               } else {
+                   status =
+                       tls_scache_lookup(cache, STR(cache_id), openssl_vsn,
+                                         flags,
+                                         TLS_SCACHE_DONT_NEED_OPENSSL_VSN,
+                                         TLS_SCACHE_DONT_NEED_FLAGS,
+                                         buffer) ?
+                       TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
+               }
+           }
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION,
+                      LEN(buffer), STR(buffer),
+                      ATTR_TYPE_END);
+       }
+
+       /*
+        * Save session to cache.
+        */
+       else if (STREQ(STR(request), TLS_MGR_REQ_UPDATE)) {
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                       ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_LONG, TLS_MGR_ATTR_VERSION, &openssl_vsn,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_FLAGS, &flags,
+                         ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buffer,
+                         ATTR_TYPE_END) == 5) {
+               if ((cache = WHICH_CACHE_INFO(cache_type)) == 0) {
+                   msg_warn("bogus cache type \"%d\" in \"%s\" request",
+                            cache_type, TLS_MGR_REQ_UPDATE);
+               } else {
+                   status =
+                       tls_scache_update(cache, STR(cache_id), openssl_vsn,
+                                         flags, STR(buffer), LEN(buffer)) ?
+                       TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
+               }
+           }
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_END);
+       }
+
+       /*
+        * Delete session from cache.
+        */
+       else if (STREQ(STR(request), TLS_MGR_REQ_DELETE)) {
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                       ATTR_TYPE_NUM, TLS_MGR_ATTR_CACHE_TYPE, &cache_type,
+                         ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
+                         ATTR_TYPE_END) == 2) {
+               if ((cache = WHICH_CACHE_INFO(cache_type)) == 0) {
+                   msg_warn("bogus cache type \"%d\" in \"%s\" request",
+                            cache_type, TLS_MGR_REQ_DELETE);
+               } else {
+                   status = tls_scache_delete(cache, STR(cache_id)) ?
+                       TLS_MGR_STAT_OK : TLS_MGR_STAT_ERR;
+               }
+           }
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_END);
+       }
+
+       /*
+        * Entropy request.
+        */
+       else if (STREQ(STR(request), TLS_MGR_REQ_SEED)) {
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                         ATTR_TYPE_NUM, TLS_MGR_ATTR_SIZE, &len,
+                         ATTR_TYPE_END) == 1) {
+               VSTRING_RESET(buffer);
+               if (len <= 0 || len > 255) {
+                   msg_warn("bogus seed length \"%d\" in \"%s\" request",
+                            len, TLS_MGR_REQ_SEED);
+               } else {
+                   VSTRING_SPACE(buffer, len);
+                   RAND_bytes((unsigned char *) STR(buffer), len);
+                   VSTRING_AT_OFFSET(buffer, len);     /* XXX not part of the
+                                                        * official interface */
+                   status = TLS_MGR_STAT_OK;
+               }
+           }
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED,
+                      LEN(buffer), STR(buffer),
+                      ATTR_TYPE_END);
+       }
+
+       /*
+        * Caching policy request.
+        */
+       else if (STREQ(STR(request), TLS_MGR_REQ_POLICY)) {
+           int     cache_types = 0;
+
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                         ATTR_TYPE_END) == 0) {
+               if (clnt_scache_info)
+                   cache_types |= TLS_MGR_SCACHE_CLIENT;
+               if (srvr_scache_info)
+                   cache_types |= TLS_MGR_SCACHE_SERVER;
+               status = TLS_MGR_STAT_OK;
+           }
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_NUM, TLS_MGR_ATTR_POLICY, cache_types,
+                      ATTR_TYPE_END);
+       }
+
+       /*
+        * Master trigger. Normally, these triggers arrive only after some
+        * other process requested the tlsmgr's service. The purpose is to
+        * restart the tlsmgr after it aborted due to a fatal run-time error,
+        * so that it can continue its housekeeping even while nothing is
+        * using TLS.
+        * 
+        * XXX Which begs the question, if TLS isn't used often, do we need a
+        * tlsmgr background process? It could terminate when the session
+        * caches are empty.
+        */
+       else if (STREQ(STR(request), wakeup)) {
+           if (msg_verbose)
+               msg_info("received master trigger");
+           multi_server_disconnect(client_stream);
+           return;                             /* NOT: vstream_fflush */
+       }
+    }
+
+    /*
+     * Protocol error.
+     */
+    else {
+       attr_print(client_stream, ATTR_FLAG_NONE,
+                  ATTR_TYPE_NUM, MAIL_ATTR_STATUS, TLS_MGR_STAT_FAIL,
+                  ATTR_TYPE_END);
+    }
+    vstream_fflush(client_stream);
+}
+
+/* tlsmgr_pre_init - pre-jail initialization */
+
+static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
+{
+    char   *path;
+    struct timeval tv;
+
+    /*
+     * If nothing else works then at least this will get us a few bits of
+     * entropy.
+     */
+    GETTIMEOFDAY(&tv);
+    tv.tv_sec ^= getpid();
+    RAND_seed(&tv, sizeof(struct timeval));
+
+
+    /*
+     * Open the external entropy source. We will not be able to open it again
+     * after we are sent to chroot jail, so we keep it open. Errors are not
+     * fatal. The exchange file (see below) is the only entropy source that
+     * really matters in the long run.
+     * 
+     * Security note: we open the entropy source while privileged, but we don't
+     * access the source until after we release privileges. This way, none of
+     * the OpenSSL code gets to execute while we are privileged.
+     */
+    if (*var_tls_rand_source) {
+
+       /*
+        * Source is a random device.
+        */
+       if (!strncmp(var_tls_rand_source, DEV_PREF, DEV_PREF_LEN)) {
+           path = DEV_PATH(var_tls_rand_source);
+           rand_source_dev = tls_prng_dev_open(path, TLS_MGR_TIMEOUT);
+           if (rand_source_dev == 0)
+               msg_warn("cannot open entropy device %s: %m", path);
+       }
+
+       /*
+        * Source is an EGD compatible socket.
+        */
+       else if (!strncmp(var_tls_rand_source, EGD_PREF, EGD_PREF_LEN)) {
+           path = EGD_PATH(var_tls_rand_source);
+           rand_source_egd = tls_prng_egd_open(path, TLS_MGR_TIMEOUT);
+           if (rand_source_egd == 0)
+               msg_warn("cannot connect to EGD server %s: %m", path);
+       }
+
+       /*
+        * Source is regular file. We read this only once.
+        */
+       else {
+           rand_source_file =
+               tls_prng_file_open(var_tls_rand_source, TLS_MGR_TIMEOUT);
+       }
+    } else {
+       msg_warn("no entropy source specified with parameter %s",
+                VAR_TLS_RAND_SOURCE);
+       msg_warn("encryption keys etc. may be predictable");
+    }
+
+    /*
+     * Open the PRNG exchange file while privileged. Start the exchange file
+     * read/update pseudo thread after dropping privileges.
+     */
+    if (*var_tls_rand_exch_name) {
+       rand_exch = tls_prng_exch_open(var_tls_rand_exch_name);
+       if (rand_exch == 0)
+           msg_fatal("cannot open PRNG exchange file %s: %m",
+                     var_tls_rand_exch_name);
+    }
+
+    /*
+     * Open the session cache files and discard old information while
+     * privileged. Start the cache maintenance pseudo threads after dropping
+     * privileges.
+     */
+    if (*var_smtp_tls_scache_db)
+       clnt_scache_info =
+           tls_scache_open(var_smtp_tls_scache_db, "client",
+                           var_smtp_tls_loglevel,
+                           var_smtp_tls_scache_timeout);
+    if (*var_smtpd_tls_scache_db)
+       srvr_scache_info =
+           tls_scache_open(var_smtpd_tls_scache_db, "server",
+                           var_smtpd_tls_loglevel,
+                           var_smtpd_tls_scache_timeout);
+}
+
+/* tlsmgr_post_init - post-jail initialization */
+
+static void tlsmgr_post_init(char *unused_name, char **unused_argv)
+{
+#define NULL_EVENT     (0)
+#define NULL_CONTEXT   ((char *) 0)
+
+    /*
+     * This routine runs after the skeleton code has entered the chroot jail,
+     * but before any client requests are serviced. Prevent automatic process
+     * suicide after a limited number of client requests or after a limited
+     * amount of idle time.
+     */
+    var_use_limit = 0;
+    var_idle_limit = 0;
+
+    /*
+     * Start the internal PRNG re-seeding pseudo thread first.
+     */
+    if (*var_tls_rand_source) {
+       if (var_tls_reseed_period > INT_MAX / UCHAR_MAX)
+           var_tls_reseed_period = INT_MAX / UCHAR_MAX;
+       tlsmgr_reseed_event(NULL_EVENT, NULL_CONTEXT);
+    }
+
+    /*
+     * Start the exchange file read/update pseudo thread.
+     */
+    if (*var_tls_rand_exch_name) {
+       if (var_tls_prng_exch_period > INT_MAX / UCHAR_MAX)
+           var_tls_prng_exch_period = INT_MAX / UCHAR_MAX;
+       tlsmgr_prng_exch_event(NULL_EVENT, NULL_CONTEXT);
+    }
+
+    /*
+     * Start the cache maintenance pseudo threads last. Strictly speaking
+     * there is nothing to clean up after we truncate the database to zero
+     * length, but early cleanup makes verbose logging more informative (we
+     * get positive confirmation that the cleanup threads are running).
+     */
+    if (*var_smtp_tls_scache_db)
+       tlsmgr_clnt_cache_run_event(NULL_EVENT, NULL_CONTEXT);
+    if (*var_smtpd_tls_scache_db)
+       tlsmgr_srvr_cache_run_event(NULL_EVENT, NULL_CONTEXT);
+}
+
+/* tlsmgr_before_exit - save PRNG state before exit */
+
+static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
+{
+
+    /*
+     * Save state before we exit after "postfix reload".
+     */
+    if (rand_exch)
+       tls_prng_exch_update(rand_exch);
+}
+
+/* main - the main program */
+
+int     main(int argc, char **argv)
+{
+    static CONFIG_STR_TABLE str_table[] = {
+       VAR_TLS_RAND_SOURCE, DEF_TLS_RAND_SOURCE, &var_tls_rand_source, 0, 0,
+       0,
+    };
+    static CONFIG_TIME_TABLE time_table[] = {
+       VAR_TLS_RESEED_PERIOD, DEF_TLS_RESEED_PERIOD, &var_tls_reseed_period, 1, 0,
+       VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_exch_period, 1, 0,
+       0,
+    };
+    static CONFIG_INT_TABLE int_table[] = {
+       VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 1, 0,
+       0,
+    };
+
+    /*
+     * Use the multi service skeleton, and require that no-one else is
+     * monitoring our service port while this process runs.
+     */
+    multi_server_main(argc, argv, tlsmgr_service,
+                     MAIL_SERVER_TIME_TABLE, time_table,
+                     MAIL_SERVER_INT_TABLE, int_table,
+                     MAIL_SERVER_STR_TABLE, str_table,
+                     MAIL_SERVER_PRE_INIT, tlsmgr_pre_init,
+                     MAIL_SERVER_POST_INIT, tlsmgr_post_init,
+                     MAIL_SERVER_EXIT, tlsmgr_before_exit,
+                     MAIL_SERVER_LOOP, tlsmgr_loop,
+                     MAIL_SERVER_SOLITARY,
+                     0);
+}
+
+#else
+
+/* tlsmgr_service - respond to external trigger(s), non-TLS version */
+
+static void tlsmgr_service(VSTREAM *unused_stream, char *unused_service,
+                                  char **unused_argv)
+{
+    msg_info("TLS support is not compiled in -- exiting");
+}
+
+/* main - the main program, non-TLS version */
+
+int     main(int argc, char **argv)
+{
+
+    /*
+     * 200411 We can't simply use msg_fatal() here, because the logging
+     * hasn't been initialized. The text would disappear because stderr is
+     * redirected to /dev/null.
+     * 
+     * We invoke multi_server_main() to complete program initialization
+     * (including logging) and then invoke the tlsmgr_service() routine to
+     * log the message that says why this program will not run.
+     */
+    multi_server_main(argc, argv, tlsmgr_service,
+                     0);
+}
+
+#endif
index 76d90d61e6f9c6fd56c5b2db6ef95a7214108112..19984f90e1d66157822ae59fb5275e89cb477335 100644 (file)
@@ -353,6 +353,9 @@ extern int opterr;
 #ifndef NO_CLOSEFROM
 # define HAS_CLOSEFROM
 #endif
+#ifndef NO_DEV_URANDOM
+# define HAS_DEV_URANDOM
+#endif
 
 /*
  * Allow build environment to override paths.
index 25f65f721c05fd9ed636afc36237640117fe1bb7..32a8771cd03468601a70eafd6fdfa36f1454ee19 100644 (file)
@@ -42,6 +42,9 @@
 /*     These routines operate silently unless the gripe parameter
 /*     specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
 /*     provide suitable constants.
+/* BUGS
+/*     valid_hostmumble() does not guarantee that string lengths
+/*     fit the buffer sizes defined in myaddrinfo(3h).
 /* DIAGNOSTICS
 /*     All functions return zero if they disagree with the input.
 /* SEE ALSO
index 53d86a81c235745a4b5d80c8dbfa140a793f21b5..25e8859ab1525f190470318c1d09ba5ed48c34ad 100644 (file)
@@ -63,6 +63,8 @@ verify.o: ../../include/vstream.h
 verify.o: ../../include/vbuf.h
 verify.o: ../../include/argv.h
 verify.o: ../../include/split_at.h
+verify.o: ../../include/stringops.h
+verify.o: ../../include/vstring.h
 verify.o: ../../include/mail_conf.h
 verify.o: ../../include/mail_params.h
 verify.o: ../../include/mail_proto.h
@@ -72,6 +74,5 @@ verify.o: ../../include/post_mail.h
 verify.o: ../../include/cleanup_user.h
 verify.o: ../../include/verify_clnt.h
 verify.o: ../../include/deliver_request.h
-verify.o: ../../include/vstring.h
 verify.o: ../../include/recipient_list.h
 verify.o: ../../include/mail_server.h