summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net-mail/postfix/ChangeLog13
-rw-r--r--net-mail/postfix/files/digest-postfix-1.1.11-r42
-rw-r--r--net-mail/postfix/files/digest-postfix-1.1.11.200208222
-rw-r--r--net-mail/postfix/files/digest-postfix-1.1.11.200209172
-rw-r--r--net-mail/postfix/files/digest-postfix-1.1.8-r12
-rw-r--r--net-mail/postfix/files/saslv2.diff42
-rw-r--r--net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2bin72042 -> 0 bytes
-rw-r--r--net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2bin0 -> 72150 bytes
-rw-r--r--net-mail/postfix/files/tls+ipv6.diff10732
-rw-r--r--net-mail/postfix/postfix-1.1.11-r4.ebuild185
-rw-r--r--net-mail/postfix/postfix-1.1.11.20020917.ebuild (renamed from net-mail/postfix/postfix-1.1.11.20020822.ebuild)4
-rw-r--r--net-mail/postfix/postfix-1.1.8-r1.ebuild136
12 files changed, 16 insertions, 11104 deletions
diff --git a/net-mail/postfix/ChangeLog b/net-mail/postfix/ChangeLog
index fdb1bc383cee..f790f914da7d 100644
--- a/net-mail/postfix/ChangeLog
+++ b/net-mail/postfix/ChangeLog
@@ -1,6 +1,17 @@
# ChangeLog for net-mail/postfix
# Copyright 2002 Gentoo Technologies, Inc.; Distributed under the GPL
-# $Header: /var/cvsroot/gentoo-x86/net-mail/postfix/ChangeLog,v 1.35 2002/09/17 21:28:32 raker Exp $
+# $Header: /var/cvsroot/gentoo-x86/net-mail/postfix/ChangeLog,v 1.36 2002/09/19 19:09:22 raker Exp $
+
+*postfix-1.1.11.20020917 (19 Sep 2002)
+
+ 19 Sep 2002; Nick Hadaway <raker@gentoo.org>
+ postfix-1.1.11.20020917.ebuild, files/digest-postfix-1.1.11.20020917,
+ files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2 :
+ Version bump. Lots of bug fixes(+features) from the 20020822
+ version. Important fixes include ldap and berkdb related fixes.
+ See...
+ http://archive.progeny.com/postfix/experimental/postfix-1.1.11-20020918.HISTORY
+ for the changelog.
*postfix-1.1.11.20020822 (11 Sep 2002)
diff --git a/net-mail/postfix/files/digest-postfix-1.1.11-r4 b/net-mail/postfix/files/digest-postfix-1.1.11-r4
deleted file mode 100644
index 6ad541484afc..000000000000
--- a/net-mail/postfix/files/digest-postfix-1.1.11-r4
+++ /dev/null
@@ -1,2 +0,0 @@
-MD5 b34bb2b5018327c19456a77814141208 postfix-1.1.11.tar.gz 1190741
-MD5 82fc61f233f5edcece3baa749e53677d pfixtls-0.8.11a-1.1.11-0.9.6d.tar.gz 196051
diff --git a/net-mail/postfix/files/digest-postfix-1.1.11.20020822 b/net-mail/postfix/files/digest-postfix-1.1.11.20020822
deleted file mode 100644
index f44c216bf0b7..000000000000
--- a/net-mail/postfix/files/digest-postfix-1.1.11.20020822
+++ /dev/null
@@ -1,2 +0,0 @@
-MD5 1a82f18a9ce23dc7c6d29d7023281067 postfix-1.1.11-20020822.tar.gz 1275033
-MD5 45661443f25719094ebb537d4865c07e pfixtls-0.8.11a-1.1.11-20020822-0.9.6g.tar.gz 196144
diff --git a/net-mail/postfix/files/digest-postfix-1.1.11.20020917 b/net-mail/postfix/files/digest-postfix-1.1.11.20020917
new file mode 100644
index 000000000000..01d2b9027adb
--- /dev/null
+++ b/net-mail/postfix/files/digest-postfix-1.1.11.20020917
@@ -0,0 +1,2 @@
+MD5 d5c4edd83db08a4306840fef321bb42a postfix-1.1.11-20020917.tar.gz 1287821
+MD5 1fc29989315ab5570486929c24187626 pfixtls-0.8.11a-1.1.11-20020917-0.9.6g.tar.gz 196206
diff --git a/net-mail/postfix/files/digest-postfix-1.1.8-r1 b/net-mail/postfix/files/digest-postfix-1.1.8-r1
deleted file mode 100644
index d67c9d9bb7de..000000000000
--- a/net-mail/postfix/files/digest-postfix-1.1.8-r1
+++ /dev/null
@@ -1,2 +0,0 @@
-MD5 3b07a59e8bdb46af8c1d82f085a62d73 postfix-1.1.8.tar.gz 1187634
-MD5 a7f37543d0e265ba06058648846d600d pfixtls-0.8.8-1.1.8-0.9.6d.tar.gz 195225
diff --git a/net-mail/postfix/files/saslv2.diff b/net-mail/postfix/files/saslv2.diff
deleted file mode 100644
index 879b7640aabe..000000000000
--- a/net-mail/postfix/files/saslv2.diff
+++ /dev/null
@@ -1,42 +0,0 @@
-diff -urN postfix-1.1.11-20020613/src/lmtp/lmtp.h postfix-1.1.11-20020613-modified/src/lmtp/lmtp.h
---- postfix-1.1.11-20020613/src/lmtp/lmtp.h Tue May 22 13:37:14 2001
-+++ postfix-1.1.11-20020613-modified/src/lmtp/lmtp.h Mon Jul 22 17:04:54 2002
-@@ -12,8 +12,8 @@
- * SASL library.
- */
- #ifdef USE_SASL_AUTH
--#include <sasl.h>
--#include <saslutil.h>
-+#include <sasl/sasl.h>
-+#include <sasl/saslutil.h>
- #endif
-
- /*
-diff -urN postfix-1.1.11-20020613/src/smtp/smtp.h postfix-1.1.11-20020613-modified/src/smtp/smtp.h
---- postfix-1.1.11-20020613/src/smtp/smtp.h Thu May 23 14:18:02 2002
-+++ postfix-1.1.11-20020613-modified/src/smtp/smtp.h Mon Jul 22 17:04:41 2002
-@@ -12,8 +12,8 @@
- * SASL library.
- */
- #ifdef USE_SASL_AUTH
--#include <sasl.h>
--#include <saslutil.h>
-+#include <sasl/sasl.h>
-+#include <sasl/saslutil.h>
- #endif
-
- /*
-diff -urN postfix-1.1.11-20020613/src/smtpd/smtpd.h postfix-1.1.11-20020613-modified/src/smtpd/smtpd.h
---- postfix-1.1.11-20020613/src/smtpd/smtpd.h Fri Mar 29 15:10:13 2002
-+++ postfix-1.1.11-20020613-modified/src/smtpd/smtpd.h Mon Jul 22 17:04:22 2002
-@@ -17,8 +17,8 @@
- * SASL library.
- */
- #ifdef USE_SASL_AUTH
--#include <sasl.h>
--#include <saslutil.h>
-+#include <sasl/sasl.h>
-+#include <sasl/saslutil.h>
- #endif
-
- /*
diff --git a/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2 b/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2
deleted file mode 100644
index ff87843c55cf..000000000000
--- a/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2
+++ /dev/null
Binary files differ
diff --git a/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2 b/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2
new file mode 100644
index 000000000000..fdf1837fa63d
--- /dev/null
+++ b/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2
Binary files differ
diff --git a/net-mail/postfix/files/tls+ipv6.diff b/net-mail/postfix/files/tls+ipv6.diff
deleted file mode 100644
index c85d32017337..000000000000
--- a/net-mail/postfix/files/tls+ipv6.diff
+++ /dev/null
@@ -1,10732 +0,0 @@
-diff -Pur postfix-1.1.11.20020613-orig/Makefile.in postfix-1.1.11-20020613/Makefile.in
---- postfix-1.1.11.20020613-orig/Makefile.in Sat Jun 8 20:49:42 2002
-+++ postfix-1.1.11.20020613/Makefile.in Wed Jun 26 15:26:47 2002
-@@ -6,7 +6,8 @@
- src/lmtp src/trivial-rewrite src/qmgr 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/nqmgr src/qmqpd src/spawn src/flush src/virtual
-+ src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual \
-+ src/tlsmgr
- MANDIRS = proto man html
-
- default: update
-diff -Pur postfix-1.1.11.20020613-orig/conf/master.cf postfix-1.1.11-20020613/conf/master.cf
---- postfix-1.1.11.20020613-orig/conf/master.cf Sat Jun 8 20:21:38 2002
-+++ postfix-1.1.11.20020613/conf/master.cf Wed Jun 26 15:26:47 2002
-@@ -70,11 +70,16 @@
- # (yes) (yes) (yes) (never) (50)
- # ==========================================================================
- smtp inet n - n - - smtpd
-+#smtps inet n - n - - smtpd
-+# -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
-+#submission inet n - n - - smtpd
-+# -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 nqmgr
-+#tlsmgr fifo - - n 300 1 tlsmgr
- rewrite unix - - n - - trivial-rewrite
- bounce unix - - n - 0 bounce
- defer unix - - n - 0 bounce
-diff -Pur postfix-1.1.11.20020613-orig/conf/postfix-files postfix-1.1.11-20020613/conf/postfix-files
---- postfix-1.1.11.20020613-orig/conf/postfix-files Sun May 26 23:27:31 2002
-+++ postfix-1.1.11.20020613/conf/postfix-files Wed Jun 26 15:26:47 2002
-@@ -69,6 +69,7 @@
- $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/virtual:f:root:-:755
- $command_directory/postalias:f:root:-:755
-@@ -139,6 +140,7 @@
- $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/trivial-rewrite.8:f:root:-:644
- $manpage_directory/man8/virtual.8:f:root:-:644
- $sample_directory/sample-aliases.cf:f:root:-:644
-@@ -166,6 +168,7 @@
- $sample_directory/sample-rewrite.cf:f:root:-:644
- $sample_directory/sample-smtp.cf:f:root:-:644
- $sample_directory/sample-smtpd.cf:f:root:-:644
-+$sample_directory/sample-tls.cf:f:root:-:644
- $sample_directory/sample-transport.cf:f:root:-:644
- $sample_directory/sample-virtual.cf:f:root:-:644
- $readme_directory/DB_README:f:root:-:644
-diff -Pur postfix-1.1.11.20020613-orig/conf/sample-auth.cf postfix-1.1.11-20020613/conf/sample-auth.cf
---- postfix-1.1.11.20020613-orig/conf/sample-auth.cf Fri Mar 29 22:36:53 2002
-+++ postfix-1.1.11.20020613/conf/sample-auth.cf Wed Jun 26 15:26:47 2002
-@@ -117,3 +117,15 @@
- #
- #smtp_sasl_security_options =
- smtp_sasl_security_options = noplaintext
-+
-+# Sending AUTH data over an unencrypted channel poses a security risk. When
-+# smtpd_tls_enforce_tls is set, AUTH will only be announced and accepted,
-+# once the TLS layer has been activated via the STARTTLS protocol. If
-+# TLS layer encryption is optional, it may however still be useful to only
-+# offer AUTH, when TLS is active. To not break compatiblity with unpatched
-+# postfix versions, the default is to accept AUTH without encryption. In
-+# order to change this behaviour, set smtpd_tls_auth_only = yes.
-+# THIS OPTION ONLY WORKS WITH SSL/TLS SUPPORT COMPILED IN.
-+#
-+# smtpd_tls_auth_only = no
-+
-diff -Pur postfix-1.1.11.20020613-orig/conf/sample-smtp.cf postfix-1.1.11-20020613/conf/sample-smtp.cf
---- postfix-1.1.11.20020613-orig/conf/sample-smtp.cf Tue Mar 26 22:46:30 2002
-+++ postfix-1.1.11.20020613/conf/sample-smtp.cf Wed Jun 26 15:26:47 2002
-@@ -188,6 +188,14 @@
- #
- smtp_helo_timeout = 300s
-
-+# The smtp_starttls_timeout parameter limits the time in seconds to write and
-+# read operations during TLS start and stop handhake procedures.
-+#
-+# In case of problems the client does NOT try the next address on
-+# the mail exchanger list.
-+#
-+# smtp_starttls_timeout = 300s
-+
- # The smtp_mail_timeout parameter specifies the SMTP client timeout
- # for sending the SMTP MAIL FROM command, and for receiving the server
- # response.
-diff -Pur postfix-1.1.11.20020613-orig/conf/sample-smtpd.cf postfix-1.1.11-20020613/conf/sample-smtpd.cf
---- postfix-1.1.11.20020613-orig/conf/sample-smtpd.cf Sat Jun 8 20:21:38 2002
-+++ postfix-1.1.11.20020613/conf/sample-smtpd.cf Wed Jun 26 15:26:47 2002
-@@ -116,6 +116,11 @@
- #
- strict_rfc821_envelopes = no
-
-+# The smtpd_starttls_timeout parameter limits the time in seconds to write and
-+# read operations during TLS start and stop handhake procedures.
-+#
-+# smtpd_starttls_timeout = 300s
-+
- #
- # TARPIT CONTROLS
- #
-diff -Pur postfix-1.1.11.20020613-orig/conf/sample-tls.cf postfix-1.1.11-20020613/conf/sample-tls.cf
---- postfix-1.1.11.20020613-orig/conf/sample-tls.cf Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11.20020613/conf/sample-tls.cf Wed Jun 26 15:26:47 2002
-@@ -0,0 +1,497 @@
-+# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
-+# HERE JUST SERVES AS AN EXAMPLE.
-+#
-+# This file contains example settings of Postfix configuration
-+# parameters that control the behaviour of the TLS extensions.
-+#
-+# We strictly seperate between server side TLS (smtpd_) and client side
-+# TLS (smtp_), as for practical reasons we might choose differently.
-+
-+# Section with SMTPD specific settings
-+
-+# To use TLS we do need a certificate and a private key. Both must be in
-+# "pem" format, the private key must not be encrypted, that does mean:
-+# it must be accessable without password. Both parts (certificate and
-+# private key) may be in the same file.
-+#
-+# Both RSA and DSA are certificates are supported. Typically you will only
-+# have RSA certificates issued by a commercial CA, also the tools supplied
-+# with OpenSSL will by default issue RSA certificates.
-+# You can have both at the same time, in this case the cipher used decides,
-+# which certificate is presented. For Netscape and OpenSSL clients without
-+# special cipher choices, the RSA certificate is preferred.
-+#
-+# In order to check the 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 of "root CA". Create the server.pem file by
-+# 'cat server_cert.pem intemediate_CA.pem root_CA.pem > server.pem'
-+#
-+# 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_[d]cert_file.
-+#
-+# A certificate supplied here must be useable as SSL server certificate and
-+# hence pass the "openssl verify -purpose sslserver ..." test.
-+#
-+smtpd_tls_cert_file = /etc/postfix/server.pem
-+smtpd_tls_key_file = $smtpd_tls_cert_file
-+#
-+# Its DSA counterparts:
-+smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem
-+smtpd_tls_dkey_file = $smtpd_tls_dcert_file
-+
-+# The certificate was issued by a certification authority (CA), the CA-cert
-+# of which must be available, if not in the certificate file.
-+# This file may also contain the 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. No default is supplied for this value as of now.
-+#
-+# smtpd_tls_CAfile = /etc/postfix/CAcert.pem
-+
-+# To verify the peer certificate, we need to know the certificates of
-+# certification authorities. These certificates in "pem" format are
-+# collected in a directory. The same CAs are offered to clients for
-+# client verification. Don't forget to create the necessary "hash"
-+# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
-+# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
-+# no default and you explicitly have to set the value here!
-+#
-+# To use this option in chroot mode, this directory itself or a copy of it
-+# must be inside the chroot jail. Please note also, that the CAs in this
-+# directory are not listed to the client, so that e.g. Netscape might not
-+# offer certificates issued by them.
-+#
-+# I therefore discourage the use of this option.
-+#
-+smtpd_tls_CApath = /etc/postfix/certs
-+
-+# To get additional information during the TLS setup and negotiations
-+# you can increase the loglevel from 0..4:
-+# 0: No output about the TLS subsystem
-+# 1: Printout startup and certificate information
-+# 2: 1 + Printout of levels during negotiation
-+# 3: 2 + Hex and ASCII dump of negotiation process
-+# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
-+# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
-+# discouraged.
-+#
-+# smtpd_tls_loglevel = 0
-+
-+# To include information about the protocol and cipher used as well as the
-+# client and issuer CommonName into the "Received:" header, set the
-+# smtpd_tls_received_header variable to true. The default is no, as the
-+# information is not necessarily authentic. Only the final destination
-+# is reliable, since the headers might have been changed in between.
-+#
-+#smtpd_tls_received_header = yes
-+
-+# By default TLS is disabled, so no difference to plain postfix is visible.
-+# Explicitely switch it on using "smtpd_use_tls". (Note: when invoked
-+# via "sendmail -bs", STARTTLS is never offered due to insufficient
-+# privileges to access the private key. This is intended behaviour.)
-+#
-+smtpd_use_tls = yes
-+
-+# You can ENFORCE the use of TLS, so that no commands (except QUIT of course)
-+# are allowed without TLS. According to RFC2487 this MUST NOT be applied
-+# in case of a publicly-referenced SMTP server. So this option is off
-+# by default and should only seldom be used. Using this option implies
-+# smtpd_use_tls = yes. (Note: when invoked via "sendmail -bs", STARTTLS
-+# is never offered due to insufficient privileges to access the private key.
-+# This is intended behaviour.)
-+#
-+# smtpd_enforce_tls = no
-+
-+# Besides RFC2487 some clients, namely Outlook [Express] prefer to run the
-+# non-standard "wrapper" mode, not the STARTTLS enhancement to SMTP.
-+# 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. Port 465 (smtps)
-+# was once chosen for this feature.
-+#
-+# smtpd_tls_wrappermode = no
-+
-+# To receive a client certificate, the server must explicitly ask for one.
-+# Hence netscape will either complain if no certificate is available (for
-+# the list of CAs in /etc/postfix/certs) or will offer you client certificates
-+# to choose from. This might be annoying, so this option is "off" by default.
-+# You will however need the certificate if you want to to e.g. certificate
-+# based relaying.
-+#
-+# smtpd_tls_ask_ccert = no
-+
-+# You may also decide to REQUIRE a client certificate to allow TLS connections.
-+# I don't think it will be necessary often, it is however included here for
-+# completeness. This option implies smtpd_tls_ask_ccert = yes
-+#
-+# Please be aware, that this will inhibit TLS connections without a proper
-+# certificate and only makes sense, when normal submission is disabled and
-+# TLS is enforced (smtpd_enforce_tls). Otherwise clients may bypass 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 would be set and an information
-+# is logged.
-+#
-+# smtpd_tls_req_ccert = no
-+
-+# The verification depth for client certificates. A depth of 1 is sufficient,
-+# if the certificate ist directly issued by a CA listed in the CA locations.
-+# The default value (5) should also suffice for longer chains (root CA issues
-+# special CA which then issues the actual certificate...)
-+#
-+# smtpd_tls_ccert_verifydepth = 5
-+
-+# Sending AUTH data over an unencrypted channel poses a security risk. When
-+# smtpd_tls_enforce_tls is set, AUTH will only be announced and accepted,
-+# once the TLS layer has been activated via the STARTTLS protocol. If
-+# TLS layer encryption is optional, it may however still be useful to only
-+# offer AUTH, when TLS is active. To not break compatiblity with unpatched
-+# postfix versions, the default is to accept AUTH without encryption. In
-+# order to change this behaviour, set smtpd_tls_auth_only = yes.
-+#
-+# smtpd_tls_auth_only = no
-+
-+# The server and client negotiate a session, which takes some computer time
-+# and network bandwidth. The session is cached only in the smtpd process
-+# actually using this session and is lost when the process dies.
-+# To share the session information between the smtpd processes, a disc based
-+# session cache can be used based on the SDBM databases (routines included
-+# in Postfix/TLS). Since concurrent writing must be supported, only SDBM
-+# can be used.
-+#
-+smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache
-+
-+# The cached sessions time out after a certain amount of time. For Postfix/TLS
-+# I do not use the OpenSSL default of 300sec, but a longer time of 3600sec
-+# (=1 hour). RFC2246 recommends a maximum of 24 hours.
-+#
-+# smtpd_tls_session_cache_timeout = 3600s
-+
-+# Two additional options has been added for relay control to the UCE rules:
-+# permit_tls_clientcerts (a)
-+# and
-+# permit_tls_all_clientcerts. (b)
-+#
-+# If one of these options is added to
-+# smtpd_recipient_restrictions,
-+# postfix will relay if
-+# (a) a valid (it passed the verification) client certificate is presented
-+# and its fingerprint is listed in the list of client certs
-+# (relay_clientcerts),
-+# (b) any valid (it passed the verification) client certificate is presented.
-+#
-+# Option (b) must only be used, if a special CA issues the certificates and
-+# only this CA is listed as trusted CA. If other CAs are trusted, any owner
-+# of a valid (SSL client)-certificate can relay. Option (b) can be practical
-+# for a specically created email relay. It is however recommended to stay with
-+# option (a) and list all certificates, as (b) does not permit any control
-+# when a certificate must no longer be used (e.g. an employee leaving).
-+#
-+# smtpd_recipient_restrictions = ... permit_tls_clientcerts ...
-+
-+# The list of client certificates for which relaying will be allowed.
-+# Unfortunately the routines for lists in postfix use whitespaces as
-+# seperators and choke on special chars. So using the certificate
-+# X509ONELINES is quite impractical. We will use the fingerprints at
-+# this point, as they are difficult to fake but easy to use for lookup.
-+# As postmap (when using e.g. db) insists of having a pair of key and value,
-+# but 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
-+#
-+# relay_clientcerts = hash:/etc/postfix/relay_clientcerts
-+
-+# To influence the 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, just the string!!!
-+#
-+# smtpd_tls_cipherlist = DEFAULT
-+
-+# If you want to take advantage of ciphers with EDH, DH parameters are needed.
-+# There are built in DH parameters for both 1025bit and 512bit available. It
-+# is however better to have "own" parameters, since otherwise it would "pay"
-+# for a possible attacker to start a brute force attack against these
-+# parameters commonly 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 parameters, use
-+# openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
-+# openssl gendh -out /etc/postfix/dh_512.pem -2 -rand /var/run/egd-pool 512
-+# (your source for "entropy" might vary; on Linux there is /dev/random, on
-+# other system, you might consider the "Entropy Gathering Daemon EGD",
-+# available at http://www.lothar.com/tech/crypto/.
-+#
-+smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
-+smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
-+
-+# The smtpd_starttls_timeout parameter limits the time in seconds to write and
-+# read operations during TLS start and stop handhake procedures.
-+#
-+# smtpd_starttls_timeout = 300s
-+
-+# Section with SMTP specific settings
-+
-+# During the startup negotiation we might present a certificate to the server.
-+# Netscape is rather clever here and lets the user select between only those
-+# certs that will match the CAs accepted from the server. As I simply use
-+# the integrated "SSL_connect()" from the OpenSSL package, this is not
-+# possible by now and we have to chose just one cert.
-+# So for now the default is to use _no_ cert and key unless explictly
-+# set here. It is possible to use the same key/cert pair as for the server.
-+# If a cert is to be presented, it must be in "pem" format, the private key
-+# must not be encrypted, that does mean: it must be accessable without
-+# password. Both parts (certificate and private key) may be in the
-+# same file.
-+#
-+# In order to check the 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 "client.dom.ain" was issued by "intermediate CA"
-+# which itself has a certificate of "root CA". Create the client.pem file by
-+# 'cat client_cert.pem intemediate_CA.pem root_CA.pem > client.pem'
-+#
-+# If you want to accept 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_[d]cert_file.
-+#
-+# A certificate supplied here must be useable as SSL client certificate and
-+# hence pass the "openssl verify -purpose sslclient ..." test.
-+#
-+smtp_tls_cert_file = /etc/postfix/client.pem
-+smtp_tls_key_file = $smtp_tls_cert_file
-+
-+# The certificate was issued by a certification authority (CA), the CA-cert
-+# of which must be available, if not in the certificate file.
-+# This file may also contain the 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. No default is supplied for this value as of now.
-+#
-+smtp_tls_CAfile = /etc/postfix/CAcert.pem
-+
-+# To verify the peer certificate, we need to know the certificates of
-+# certification authorities. These certificates in "pem" format are
-+# collected in a directory. Don't forget to create the necessary "hash"
-+# links with $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs. A typical
-+# place for the CA-certs may also be $OPENSSL_HOME/certs, so there is
-+# no default and you explicitly have to set the value here!
-+#
-+# To use this option in chroot mode, this directory itself or a copy of it
-+# must be inside the chroot jail.
-+#
-+smtp_tls_CApath = /etc/postfix/certs
-+
-+# To get additional information during the TLS setup and negotiations
-+# you can increase the loglevel from 0..4:
-+# 0: No output about the TLS subsystem
-+# 1: Printout startup and certificate information
-+# 2: 1 + Printout of levels during negotiation
-+# 3: 2 + Hex and ASCII dump of negotiation process
-+# 4: 3 + Hex and ASCII dump of complete transmission after STARTTLS
-+# Use loglevel 3 only in case of problems. Use of loglevel 4 is strongly
-+# discouraged.
-+#
-+smtp_tls_loglevel = 0
-+
-+# The server and client negotiate a session, which takes some computer time
-+# and network bandwidth. The session is cached only in the smtpd process
-+# actually using this session and is lost when the process dies.
-+# To share the session information between the smtp processes, a disc based
-+# session cache can be used based on the SDBM databases (routines included
-+# in Postfix/TLS). Since concurrent writing must be supported, only SDBM
-+# can be used.
-+#
-+smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache
-+
-+# The cached sessions time out after a certain amount of time. For Postfix/TLS
-+# I do not use the OpenSSL default of 300sec, but a longer time of 3600sec
-+# (=1 hour). RFC2246 recommends a maximum of 24 hours.
-+#
-+# smtp_tls_session_cache_timeout = 3600s
-+
-+# By default TLS is disabled, so no difference to plain postfix is visible.
-+# If you enable TLS it will be used when offered by the server.
-+# WARNING: I didn't have access to other software (except those explicitely
-+# listed) to test the interaction. On corresponding mailing list
-+# there was a discussion going on about MS exchange servers offering
-+# STARTTLS even if it is not configured, so it might be wise to not
-+# use this option on your central mail hub, as you don't know in advance
-+# whether you are going to hit such host. Use the recipient/site specific
-+# options instead.
-+# HINT: I have it switched on on my mailservers and did experience one
-+# single failure since client side TLS is implemented. (There was one
-+# misconfired MS Exchange server; I contacted ths admin.) Hence, I am happy
-+# with it running all the time, but I am interested in testing anyway.
-+# You have been warned, however :-)
-+#
-+# In case of failure, a "4xx" code is issued and the mail stays in the queue.
-+#
-+# Explicitely switch it on here, if you want it.
-+#
-+smtp_use_tls = yes
-+
-+# You can ENFORCE the use of TLS, so that only connections with TLS will
-+# be accepted. Additionally, the hostname of the receiving host is matched
-+# against the CommonName in the certificate. Also, the certificate must
-+# be verified "Ok", so that a CA trusted by the client must have issued
-+# the certificate. If the certificate doesn't verify or the hostname doesn't
-+# match, a "4xx" will be issued and the mail stays in the queue.
-+# The hostname used in the check is beyond question, as it must be the
-+# principle hostname (no CNAME allowed here).
-+# The behaviour may be changed with the smtp_tls_enforce_peername option
-+#
-+# This option is useful only if you are definitely sure that you will only
-+# connect to servers supporting RFC2487 _and_ with valid certificates.
-+# I use it for my clients which will only send email to one mailhub, which
-+# does offer the necessary STARTTLS support.
-+#
-+# smtp_enforce_tls = no
-+
-+# As of RFC2487 the requirements for hostname checking for MTA clients are
-+# not set. When in smtp_enforce_tls mode, the option smtp_tls_enforce_peername
-+# can be set to "no" to disable strict peername checking. In this case, the
-+# mail delivery will be continued, if a TLS connection was established
-+# _and_ the peer certificate passed verification _but_ regardless of the
-+# CommonName listed in the certificate. This option only applies to the
-+# default setting smtp_enforce_tls_mode, special settings in the
-+# smtp_tls_per_site table override smtp_tls_enforce_peername.
-+#
-+# This 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 is logged).
-+#
-+# smtp_tls_enforce_peername = yes
-+
-+# As generally trying TLS can be a bad idea (some hosts offer STARTTLS but
-+# the negotiation will fail leading to unexplainable failures, it may be
-+# a good idea to decide based on the recipient or the mailhub to which you are
-+# connecting.
-+#
-+# Deciding per recipient may be difficult, since a singe email can have
-+# several recipients. We use the "nexthop" mechanism inside postfix.
-+# When an email is to be delivered, the "nexthop" is obtained. If it matches
-+# an entry in the smtp_tls_per_site list, appropriate action is taken.
-+# Since entries in the transport table or the use of a relay_host override
-+# the nexthop setting, in these cases the relay_host etc must be listed
-+# in the table. In any case, the hostname of the peer to be contacted is
-+# looked up (that is: the MX or the name of the host, if no MX is given).
-+#
-+# Special hint for enforcement mode:
-+# Since there is no secure mechanism for DNS lookups available, the
-+# recommended setup is: put the sensible domains with their mailhost
-+# into the transport table (since you can asure security of this table
-+# unlike DNS), then set MUST mode for this mailhost.
-+#
-+# Format of the table:
-+# The keys entries are on the left hand side, no wildcards allowed. On the
-+# right hand side the keywords NONE (don't use TLS at all), MAY (try to use
-+# STARTTLS if offered, no problem if not), MUST (enforce usage of STARTTLS,
-+# check server certificate CommonName against server FQDN), MUST_NOPEERMATCH
-+# (enforce usage of STARTTLS and verify certificate, but ignore differences
-+# between CommonName and server FQDN).
-+# dom.ain NONE
-+# host.dom.ain MAY
-+# important.host MUST
-+# some.host.dom.ain MUST_NOPEERMATCH
-+#
-+# If an entry is not matched, the default policy is applied; if the default
-+# policy is "enforce", NONE explicitely switches it off, otherwise the
-+# "enforce" mode is used even for MAY entries.
-+#
-+smtp_tls_per_site = hash:/etc/postfix/tls_per_site
-+
-+# The verification depth for server certificates. A depth of 1 is sufficient,
-+# if the certificate ist directly issued by a CA listed in the CA locations.
-+# The default value (5) should also suffice for longer chains (root CA issues
-+# special CA which then issues the actual certificate...)
-+#
-+# smtp_tls_scert_verifydepth = 5
-+
-+# As we decide on a "per site" basis, wether to use TLS or not, it would be
-+# good to have a list of sites, that offered "STARTTLS'. We can collect it
-+# ourselves with this option.
-+#
-+# If activated and TLS is not already enabled for this host, a line is added
-+# to the logfile:
-+# postfix/smtp[pid]: Host offered STARTTLS: [name.of.host]
-+#
-+smtp_tls_note_starttls_offer = yes
-+
-+# To influence the 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, just the string!!!
-+#
-+# smtp_tls_cipherlist = DEFAULT
-+
-+# The smtp_starttls_timeout parameter limits the time in seconds to write and
-+# read operations during TLS start and stop handhake procedures.
-+#
-+# In case of problems the client does NOT try the next address on
-+# the mail exchanger list.
-+#
-+# smtp_starttls_timeout = 300s
-+
-+# In order to seed the PRNG Pseude Random Number Generator, random data is
-+# needed. The PRNG pool is maintained by the "tlsmgr" daemon and is used
-+# (read) by the smtp[d] processes after adding some more entropy by stirring
-+# in time and process id.
-+# The file, which is from time to time rewritten by the tlsmgr, is created
-+# if not existant. A default value is given; the default should probably
-+# be on the /var partition but _not_ inside chroot jail.
-+#
-+# tls_random_exchange_name = /etc/postfix/prng_exch
-+
-+# To feed the PRNG pool, entropy is being read from an external source,
-+# both at startup and during run.
-+# Specify a good entropy source here, like EGD or /dev/urandom; make sure
-+# to only use non-blocking sources.
-+# In both cases, 32 bytes are read at each re-seeding event (which is an
-+# amount of 256bits and hence good enough for 128bit symmetric keys).
-+# You must specify the type of source: "dev:" for a device special file
-+# or "egd:" for a source with EGD compatible socket interface. A maximum
-+# 255 bytes is read from these sources in each step.
-+# If you specify a normal file, a larger amount of data can be read.
-+#
-+# The entropy source is queried again after a certain amount of time. The
-+# time is calculated using the PRNG, it is between 0 and the time specified,
-+# default is a maximum of 1 hour.
-+#
-+# tls_random_source = dev:/dev/urandom
-+tls_random_source = egd:/var/run/egd-pool
-+# tls_random_bytes = 32
-+# tls_random_reseed_period = 3600s
-+
-+# The PRNG pool inside tlsmgr is used to re-generate the 1024 byte file
-+# being read by smtp[d]. The time, after which the exchange file is
-+# rewritten is calculated using the PRNG, it is between 0 and the time
-+# specified, default is a maximum of 60 seconds.
-+#
-+# tls_random_upd_period = 60s
-+
-+# If you have a entropy source available, that is not easily drained (like
-+# /dev/urandom), the daemons can also load additional entropy on startup from
-+# the source specified. By default an amount of 32 bytes is read, the
-+# equivalent to 256 bits. This is more than enough to generate a 128bit
-+# (or 168bit) session key, but we may have to generate more than one.
-+# Usage of this option may drain EGD (consider the case of 50 smtp starting
-+# up with a full queue and "postfix start", which will request 1600bytes
-+# of entropy). This is however not fatal, as long as "entropy" data could
-+# be read from the exchange file.
-+#
-+# tls_daemon_random_source = dev:/dev/urandom
-+tls_daemon_random_source = egd:/var/run/egd-pool
-+# tls_daemon_random_bytes = 32
-+
-diff -Pur postfix-1.1.11.20020613-orig/makedefs postfix-1.1.11-20020613/makedefs
---- postfix-1.1.11.20020613-orig/makedefs Sat May 4 15:36:19 2002
-+++ postfix-1.1.11.20020613/makedefs Wed Jun 26 15:26:47 2002
-@@ -52,6 +52,21 @@
- SYSTEM=`(uname -s) 2>/dev/null`
- RELEASE=`(uname -r) 2>/dev/null`
- VERSION=`(uname -v) 2>/dev/null`
-+if test -f /usr/include/netinet6/in6.h; then
-+ grep __KAME__ /usr/include/netinet6/in6.h 2>&1 >/dev/null
-+ if [ $? = 1 ]; then
-+ INET6=
-+ else
-+ if [ -f /usr/local/v6/lib/libinet6.a ]; then
-+ INET6=kame
-+ else
-+ INET6=kame-merged
-+ fi
-+ fi
-+fi
-+if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then
-+ INET6=linux
-+fi
-
- case "$VERSION" in
- dcosx*) SYSTEM=$VERSION;;
-@@ -295,6 +310,26 @@
- esac
-
- : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
-+
-+case "$INET6" in
-+kame)
-+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
-+ if test -f /usr/local/v6/lib/libinet6.a; then
-+ SYSLIBS="$SYSLIBS -L/usr/local/v6/lib -linet6"
-+ fi
-+ ;;
-+kame-merged)
-+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
-+ ;;
-+linux)
-+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family"
-+ if test -f /usr/include/libinet6/netinet/ip6.h -a \
-+ -f /usr/lib/libinet6.a; then
-+ CCARGS="$CCARGS -I/usr/include/libinet6 -DUSAGI_LIBINET6"
-+ SYSLIBS="$SYSLIBS -linet6"
-+ fi
-+ ;;
-+esac
-
- export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
-
-diff -Pur postfix-1.1.11.20020613-orig/man/man8/tlsmgr.8 postfix-1.1.11-20020613/man/man8/tlsmgr.8
---- postfix-1.1.11.20020613-orig/man/man8/tlsmgr.8 Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11.20020613/man/man8/tlsmgr.8 Wed Jun 26 15:26:47 2002
-@@ -0,0 +1,130 @@
-+.TH TLSMGR 8
-+.ad
-+.fi
-+.SH NAME
-+tlsmgr
-+\-
-+Postfix TLS session cache and PRNG handling manager
-+.SH SYNOPSIS
-+.na
-+.nf
-+\fBtlsmgr\fR [generic Postfix daemon options]
-+.SH DESCRIPTION
-+.ad
-+.fi
-+The tlsmgr process does housekeeping on the session cache database
-+files. It runs through the databases and removes expired entries
-+and entries written by older (incompatible) versions.
-+
-+The tlsmgr is responsible for the PRNG handling. The used internal
-+OpenSSL PRNG has a pool size of 8192 bits (= 1024 bytes). The pool
-+is initially seeded at startup from an external source (EGD or
-+/dev/urandom) and additional seed is obtained later during program
-+run at a configurable period. The exact time of seed query is
-+using random information and is equally distributed in the range of
-+[0-\fBtls_random_reseed_period\fR] with a \fBtls_random_reseed_period\fR
-+having a default of 1 hour.
-+
-+Tlsmgr can be run chrooted and with dropped privileges, as it will
-+connect to the entropy source at startup.
-+
-+The PRNG is additionally seeded internally by the data found in the
-+session cache and timevalues.
-+
-+Tlsmgr reads the old value of the exchange file at startup to keep
-+entropy already collected during previous runs.
-+
-+From the PRNG random pool a cryptographically strong 1024 byte random
-+sequence is written into the PRNG exchange file. The file is updated
-+periodically with the time changing randomly from
-+[0-\fBtls_random_prng_update_period\fR].
-+.SH STANDARDS
-+.na
-+.nf
-+.SH SECURITY
-+.na
-+.nf
-+.ad
-+.fi
-+Tlsmgr is not security-sensitive. It only deals with external data
-+to be fed into the PRNG, the contents is never trusted. The session
-+cache housekeeping will only remove entries if expired and will never
-+touch the contents of the cached data.
-+.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
-+session caches and/or the size of the session cache files.
-+.SH CONFIGURATION PARAMETERS
-+.na
-+.nf
-+.ad
-+.fi
-+The following \fBmain.cf\fR parameters are especially relevant to
-+this program. See the Postfix \fBmain.cf\fR file for syntax details
-+and for default values. Use the \fBpostfix reload\fR command after
-+a configuration change.
-+.SH Session Cache
-+.ad
-+.fi
-+.IP \fBsmtpd_tls_session_cache_database\fR
-+Name of the SDBM file (type sdbm:) containing the SMTP server session
-+cache. If the file does not exist, it is created.
-+.IP \fBsmtpd_tls_session_cache_timeout\fR
-+Expiry time of SMTP server session cache entries in seconds. Entries
-+older than this are removed from the session cache. A cleanup-run is
-+performed periodically every \fBsmtpd_tls_session_cache_timeout\fR
-+seconds. Default is 3600 (= 1 hour).
-+.IP \fBsmtp_tls_session_cache_database\fR
-+Name of the SDBM file (type sdbm:) containing the SMTP client session
-+cache. If the file does not exist, it is created.
-+.IP \fBsmtp_tls_session_cache_timeout\fR
-+Expiry time of SMTP client session cache entries in seconds. Entries
-+older than this are removed from the session cache. A cleanup-run is
-+performed periodically every \fBsmtp_tls_session_cache_timeout\fR
-+seconds. Default is 3600 (= 1 hour).
-+.SH Pseudo Random Number Generator
-+.ad
-+.fi
-+.IP \fBtls_random_source\fR
-+Name of the EGD socket or device or regular file to obtain entropy
-+from. The type of entropy source must be specified by preceding the
-+name with the appropriate type: egd:/path/to/egd_socket,
-+dev:/path/to/devicefile, or /path/to/regular/file.
-+tlsmgr opens \fBtls_random_source\fR and tries to read
-+\fBtls_random_bytes\fR from it.
-+.IP \fBtls_random_bytes\fR
-+Number of bytes to be read from \fBtls_random_source\fR.
-+Default value is 32 bytes. If using EGD, a maximum of 255 bytes is read.
-+.IP \fBtls_random_exchange_name\fR
-+Name of the file written by tlsmgr and read by smtp and smtpd at
-+startup. The length is 1024 bytes. Default value is
-+/etc/postfix/prng_exch.
-+.IP \fBtls_random_reseed_period\fR
-+Time in seconds until the next reseed from external sources is due.
-+This is the maximum value. The actual point in time is calculated
-+with a random factor equally distributed between 0 and this maximum
-+value. Default is 3600 (= 60 minutes).
-+.IP \fBtls_random_prng_update_period\fR
-+Time in seconds until the PRNG exchange file is updated with new
-+pseude random values. This is the maximum value. The actual point
-+in time is calculated with a random factor equally distributed
-+between 0 and this maximum value. Default is 60 (= 1 minute).
-+.SH SEE ALSO
-+.na
-+.nf
-+smtp(8) SMTP client
-+smtpd(8) SMTP server
-+.SH LICENSE
-+.na
-+.nf
-+.ad
-+.fi
-+The Secure Mailer license must be distributed with this software.
-+.SH AUTHOR(S)
-+.na
-+.nf
-diff -Pur postfix-1.1.11.20020613-orig/src/dns/dns_lookup.c postfix-1.1.11-20020613/src/dns/dns_lookup.c
---- postfix-1.1.11.20020613-orig/src/dns/dns_lookup.c Sun Feb 4 19:16:20 2001
-+++ postfix-1.1.11.20020613/src/dns/dns_lookup.c Wed Jun 26 15:26:47 2002
-@@ -132,6 +132,9 @@
- } DNS_REPLY;
-
- #define INET_ADDR_LEN 4 /* XXX */
-+#ifdef INET6
-+#define INET6_ADDR_LEN 16
-+#endif
-
- /* dns_query - query name server and pre-parse the reply */
-
-@@ -337,6 +340,19 @@
- memcpy(temp, pos, fixed->length);
- data_len = fixed->length;
- break;
-+#ifdef INET6
-+ case T_AAAA:
-+ if (fixed->length != INET6_ADDR_LEN) {
-+ msg_warn("extract_answer: bad IPv6 address length: %d", fixed->length);
-+ return (0);
-+ }
-+ if (fixed->length > sizeof(temp))
-+ msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
-+ fixed->length);
-+ memcpy(temp, pos, fixed->length);
-+ data_len = fixed->length;
-+ break;
-+#endif
- case T_TXT:
- data_len = MIN2(pos[0] + 1, MIN2(fixed->length + 1, sizeof(temp)));
- for (src = pos + 1, dst = (unsigned char *) (temp);
-diff -Pur postfix-1.1.11.20020613-orig/src/global/Makefile.in postfix-1.1.11-20020613/src/global/Makefile.in
---- postfix-1.1.11.20020613-orig/src/global/Makefile.in Tue Jun 11 03:13:13 2002
-+++ postfix-1.1.11.20020613/src/global/Makefile.in Wed Jun 26 15:26:47 2002
-@@ -20,7 +20,7 @@
- tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
- flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
- verp_sender.c match_parent_style.c mime_state.c header_token.c \
-- strip_addr.c
-+ strip_addr.c pfixtls.c wildcard_inet_addr.c
- OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
- debug_peer.o debug_process.o defer.o deliver_completed.o \
- deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
-@@ -42,7 +42,7 @@
- tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
- flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
- verp_sender.o match_parent_style.o mime_state.o header_token.o \
-- strip_addr.o
-+ strip_addr.o pfixtls.o wildcard_inet_addr.o
- HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
- config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
- deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
-@@ -60,7 +60,7 @@
- sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
- mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
- match_parent_style.h quote_flags.h mime_state.h header_token.h \
-- lex_822.h strip_addr.h
-+ lex_822.h strip_addr.h pfixtls.h wildcard_inet_addr.h
- TESTSRC = rec2stream.c stream2rec.c recdump.c
- WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
- -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-@@ -1160,3 +1160,16 @@
- xtext.o: ../../include/vbuf.h
- xtext.o: ../../include/vstring.h
- xtext.o: xtext.h
-+pfixtls.o: pfixtls.c
-+pfixtls.o: ../../include/sys_defs.h
-+pfixtls.o: ../../include/iostuff.h
-+pfixtls.o: ../../include/mymalloc.h
-+pfixtls.o: ../../include/vstring.h
-+pfixtls.o: ../../include/vstream.h
-+pfixtls.o: ../../include/dict.h
-+pfixtls.o: ../../include/myflock.h
-+pfixtls.o: ../../include/stringops.h
-+pfixtls.o: ../../include/msg.h
-+pfixtls.o: ../../include/connect.h
-+pfixtls.o: mail_params.h
-+pfixtls.o: pfixtls.h
-diff -Pur postfix-1.1.11.20020613-orig/src/global/mail_params.c postfix-1.1.11-20020613/src/global/mail_params.c
---- postfix-1.1.11.20020613-orig/src/global/mail_params.c Sat Jun 8 20:21:40 2002
-+++ postfix-1.1.11.20020613/src/global/mail_params.c Wed Jun 26 15:26:47 2002
-@@ -223,6 +223,31 @@
- int var_in_flow_delay;
- char *var_par_dom_match;
- char *var_config_dirs;
-+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;
-
- char *var_import_environ;
- char *var_export_environ;
-@@ -467,6 +492,26 @@
- VAR_SHOWQ_SERVICE, DEF_SHOWQ_SERVICE, &var_showq_service, 1, 0,
- VAR_ERROR_SERVICE, DEF_ERROR_SERVICE, &var_error_service, 1, 0,
- VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0,
-+ 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,
-+ VAR_TLS_DAEMON_RAND_SOURCE, DEF_TLS_DAEMON_RAND_SOURCE, &var_tls_daemon_rand_source, 0, 0,
- 0,
- };
- static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
-@@ -489,6 +534,9 @@
- 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,
-+ 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, 0, 0,
- 0,
- };
- static CONFIG_TIME_TABLE time_defaults[] = {
-@@ -499,6 +547,8 @@
- 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,
-+ 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,
- 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,
-diff -Pur postfix-1.1.11.20020613-orig/src/global/mail_params.h postfix-1.1.11-20020613/src/global/mail_params.h
---- postfix-1.1.11.20020613-orig/src/global/mail_params.h Mon Jun 10 19:49:56 2002
-+++ postfix-1.1.11.20020613/src/global/mail_params.h Wed Jun 26 15:26:47 2002
-@@ -458,6 +458,34 @@
- #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"
-+#define DEF_TLS_RAND_SOURCE ""
-+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_SOURCE "tls_daemon_random_source"
-+#define DEF_TLS_DAEMON_RAND_SOURCE ""
-+extern char *var_tls_daemon_rand_source;
-+
-+#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 "60s"
-+extern int var_tls_prng_upd_period;
-+
- /*
- * Queue manager: relocated databases.
- */
-@@ -678,6 +706,10 @@
- #define DEF_SMTP_HELO_TMOUT "300s"
- extern int var_smtp_helo_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;
-@@ -734,6 +766,12 @@
- #define DEF_SMTP_BIND_ADDR ""
- extern char *var_smtp_bind_addr;
-
-+#ifdef INET6
-+#define VAR_SMTP_BIND_ADDR6 "smtp_bind_address6"
-+#define DEF_SMTP_BIND_ADDR6 ""
-+extern char *var_smtp_bind_addr6;
-+#endif
-+
- #define VAR_SMTP_HELO_NAME "smtp_helo_name"
- #define DEF_SMTP_HELO_NAME "$myhostname"
- extern char *var_smtp_helo_name;
-@@ -767,6 +805,10 @@
- #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;
-@@ -795,6 +837,150 @@
- #define DEF_SMTPD_NOOP_CMDS ""
- extern char *var_smtpd_noop_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.
- */
-@@ -953,6 +1139,16 @@
- #define DEF_LMTP_QUIT_TMOUT "300s"
- extern int var_lmtp_quit_tmout;
-
-+#define VAR_LMTP_BIND_ADDR "lmtp_bind_address"
-+#define DEF_LMTP_BIND_ADDR ""
-+extern char *var_lmtp_bind_addr;
-+
-+#ifdef INET6
-+#define VAR_LMTP_BIND_ADDR6 "lmtp_bind_address6"
-+#define DEF_LMTP_BIND_ADDR6 ""
-+extern char *var_lmtp_bind_addr6;
-+#endif
-+
- /*
- * Cleanup service. Header info that exceeds $header_size_limit bytes forces
- * the start of the message body.
-@@ -1088,6 +1284,10 @@
- #define DEF_RELAY_DOMAINS "$mydestination"
- extern char *var_relay_domains;
-
-+#define VAR_RELAY_CCERTS "relay_clientcerts"
-+#define DEF_RELAY_CCERTS ""
-+extern char *var_relay_ccerts;
-+
- #define VAR_CLIENT_CHECKS "smtpd_client_restrictions"
- #define DEF_CLIENT_CHECKS ""
- extern char *var_client_checks;
-@@ -1167,6 +1367,8 @@
- #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;
-diff -Pur postfix-1.1.11.20020613-orig/src/global/mail_proto.h postfix-1.1.11-20020613/src/global/mail_proto.h
---- postfix-1.1.11.20020613-orig/src/global/mail_proto.h Sun May 12 16:46:59 2002
-+++ postfix-1.1.11.20020613/src/global/mail_proto.h Wed Jun 26 15:26:47 2002
-@@ -34,6 +34,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"
-diff -Pur postfix-1.1.11.20020613-orig/src/global/mynetworks.c postfix-1.1.11-20020613/src/global/mynetworks.c
---- postfix-1.1.11.20020613-orig/src/global/mynetworks.c Sun Feb 25 02:46:07 2001
-+++ postfix-1.1.11.20020613/src/global/mynetworks.c Wed Jun 26 15:26:47 2002
-@@ -50,6 +50,11 @@
- #include <vstring.h>
- #include <inet_addr_list.h>
- #include <name_mask.h>
-+#ifdef INET6
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <netdb.h>
-+#endif
-
- /* Global library. */
-
-@@ -75,6 +80,9 @@
- const char *mynetworks(void)
- {
- static VSTRING *result;
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+#endif
-
- if (result == 0) {
- char *myname = "mynetworks";
-@@ -87,6 +95,9 @@
- int junk;
- int i;
- int mask_style;
-+#ifdef INET6
-+ struct sockaddr *sa;
-+#endif
-
- mask_style = name_mask("mynetworks mask style", mask_styles,
- var_mynetworks_style);
-@@ -96,8 +107,19 @@
- my_mask_list = own_inet_mask_list();
-
- for (i = 0; i < my_addr_list->used; i++) {
-+#ifdef INET6
-+ sa = (struct sockaddr *)&my_addr_list->addrs[i];
-+ if (sa->sa_family != AF_INET) {
-+ if (sa->sa_family == AF_INET6)
-+ vstring_sprintf_append(result, "XAATODOmynetworks ");
-+ continue;
-+ }
-+ addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
-+ mask = ntohl(((struct sockaddr_in *)&my_mask_list->addrs[i])->sin_addr.s_addr);
-+#else
- addr = ntohl(my_addr_list->addrs[i].s_addr);
- mask = ntohl(my_mask_list->addrs[i].s_addr);
-+#endif
-
- switch (mask_style) {
-
-@@ -119,8 +141,15 @@
- mask = IN_CLASSD_NET;
- shift = IN_CLASSD_NSHIFT;
- } else {
-+#ifdef INET6
-+ if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
-+ NI_NUMERICHOST))
-+ strncpy(hbuf, "???", sizeof(hbuf));
-+ msg_fatal("%s: bad address class: %s", myname, hbuf);
-+#else
- msg_fatal("%s: bad address class: %s",
- myname, inet_ntoa(my_addr_list->addrs[i]));
-+#endif
- }
- break;
-
-diff -Pur postfix-1.1.11.20020613-orig/src/global/own_inet_addr.c postfix-1.1.11-20020613/src/global/own_inet_addr.c
---- postfix-1.1.11.20020613-orig/src/global/own_inet_addr.c Tue Jul 31 20:38:29 2001
-+++ postfix-1.1.11.20020613/src/global/own_inet_addr.c Wed Jun 26 15:26:47 2002
-@@ -39,6 +39,10 @@
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
-+#ifdef INET6
-+#include <sys/socket.h>
-+#include <netdb.h>
-+#endif
-
- #ifdef STRCASECMP_IN_STRINGS_H
- #include <strings.h>
-@@ -101,10 +105,11 @@
- */
- else {
- bufp = hosts = mystrdup(var_inet_interfaces);
-- while ((host = mystrtok(&bufp, sep)) != 0)
-+ while ((host = mystrtok(&bufp, sep)) != 0) {
- if (inet_addr_host(addr_list, host) == 0)
- msg_fatal("config variable %s: host not found: %s",
- VAR_INET_INTERFACES, host);
-+ }
- myfree(hosts);
-
- /*
-@@ -121,15 +126,39 @@
- msg_fatal("could not find any active network interfaces");
- for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
- for (nlocal = 0; /* see below */ ; nlocal++) {
-- if (nlocal >= local_addrs.used)
-+ if (nlocal >= local_addrs.used) {
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ if (getnameinfo((struct sockaddr *)&addr_list->addrs[nvirtual],
-+ SS_LEN(addr_list->addrs[nvirtual]), hbuf,
-+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
-+ strncpy(hbuf, "???", sizeof(hbuf));
-+ msg_fatal("parameter %s: no local interface found for %s",
-+ VAR_INET_INTERFACES, hbuf);
-+#else
- msg_fatal("parameter %s: no local interface found for %s",
- VAR_INET_INTERFACES,
- inet_ntoa(addr_list->addrs[nvirtual]));
-+#endif
-+ }
-+#ifdef INET6
-+ if (addr_list->addrs[nvirtual].ss_family ==
-+ local_addrs.addrs[nlocal].ss_family &&
-+ SS_LEN(addr_list->addrs[nvirtual]) ==
-+ SS_LEN(local_addrs.addrs[nlocal]) &&
-+ memcmp(&addr_list->addrs[nvirtual],
-+ &local_addrs.addrs[nlocal],
-+ SS_LEN(local_addrs.addrs[nlocal])) == 0) {
-+ inet_addr_list_append(mask_list, (struct sockaddr *)&local_masks.addrs[nlocal]);
-+ break;
-+ }
-+#else
- if (addr_list->addrs[nvirtual].s_addr
- == local_addrs.addrs[nlocal].s_addr) {
- inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
- break;
- }
-+#endif
- }
- }
- inet_addr_list_free(&local_addrs);
-@@ -139,6 +168,42 @@
-
- /* own_inet_addr - is this my own internet address */
-
-+#ifdef INET6
-+int own_inet_addr(struct sockaddr * addr)
-+{
-+ int i;
-+ char *p, *q;
-+ int l;
-+ struct sockaddr *sa;
-+
-+ if (addr_list.used == 0)
-+ own_inet_addr_init(&addr_list, &mask_list);
-+
-+ for (i = 0; i < addr_list.used; i++) {
-+ sa = (struct sockaddr *)&addr_list.addrs[i];
-+ if (addr->sa_family != sa->sa_family)
-+ continue;
-+ switch (addr->sa_family) {
-+ case AF_INET:
-+ p = (char *)&((struct sockaddr_in *)addr)->sin_addr;
-+ q = (char *)&((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr;
-+ l = sizeof(struct in_addr);
-+ break;
-+ case AF_INET6:
-+ /* XXX scope */
-+ p = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
-+ q = (char *)&((struct sockaddr_in6 *)&addr_list.addrs[i])->sin6_addr;
-+ l = sizeof(struct in6_addr);
-+ break;
-+ default:
-+ continue;
-+ }
-+ if (memcmp(p, q, l) == 0)
-+ return (1);
-+ }
-+ return (0);
-+}
-+#else
- int own_inet_addr(struct in_addr * addr)
- {
- int i;
-@@ -149,8 +214,8 @@
- for (i = 0; i < addr_list.used; i++)
- if (addr->s_addr == addr_list.addrs[i].s_addr)
- return (1);
-- return (0);
- }
-+#endif
-
- /* own_inet_addr_list - return list of addresses */
-
-diff -Pur postfix-1.1.11.20020613-orig/src/global/own_inet_addr.h postfix-1.1.11-20020613/src/global/own_inet_addr.h
---- postfix-1.1.11.20020613-orig/src/global/own_inet_addr.h Sat Feb 24 02:25:32 2001
-+++ postfix-1.1.11.20020613/src/global/own_inet_addr.h Wed Jun 26 15:26:48 2002
-@@ -15,11 +15,18 @@
- * System library.
- */
- #include <netinet/in.h>
-+#ifdef INET6
-+#include <sys/socket.h>
-+#endif
-
- /*
- * External interface.
- */
-+#ifdef INET6
-+extern int own_inet_addr(struct sockaddr *);
-+#else
- extern int own_inet_addr(struct in_addr *);
-+#endif
- extern struct INET_ADDR_LIST *own_inet_addr_list(void);
- extern struct INET_ADDR_LIST *own_inet_mask_list(void);
-
-diff -Pur postfix-1.1.11.20020613-orig/src/global/peer_name.c postfix-1.1.11-20020613/src/global/peer_name.c
---- postfix-1.1.11.20020613-orig/src/global/peer_name.c Sun Jan 28 16:23:02 2001
-+++ postfix-1.1.11.20020613/src/global/peer_name.c Wed Jun 26 15:26:48 2002
-@@ -69,12 +69,32 @@
- PEER_NAME *peer_name(int sock)
- {
- static PEER_NAME peer;
-- struct sockaddr_in sin;
-- SOCKADDR_SIZE len = sizeof(sin);
-+ union sockunion {
-+ struct {
-+ u_char si_len;
-+ u_char si_family;
-+ u_short si_port;
-+ } su_si;
-+ struct sockaddr peer_un;
-+ struct sockaddr_in peer_un4;
-+#ifdef INET6
-+ struct sockaddr_in6 peer_un6;
-+#endif
-+ } p_un;
-+#define sun p_un.peer_un
-+#define sin p_un.peer_un4
-+#ifdef INET6
-+#define sin6 p_un.peer_un6
-+ static char hbuf[NI_MAXHOST];
-+ static char abuf[NI_MAXHOST];
-+#else
- struct hostent *hp;
-+#endif
-+ SOCKADDR_SIZE len = sizeof(p_un);
-
-- if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
-- switch (sin.sin_family) {
-+ if (getpeername(sock, (struct sockaddr *)&p_un, &len) == 0) {
-+ switch (p_un.peer_un.sa_family) {
-+#ifndef INET6
- case AF_INET:
- peer.type = PEER_TYPE_INET;
- hp = gethostbyaddr((char *) &(sin.sin_addr),
-@@ -83,6 +103,24 @@
- hp->h_name : "unknown");
- peer.addr = inet_ntoa(sin.sin_addr);
- return (&peer);
-+#else
-+ case AF_INET:
-+ peer.type = PEER_TYPE_INET;
-+ if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
-+ peer.name = "unknown";
-+ else
-+ peer.name = hbuf;
-+ peer.addr = abuf;
-+ return (&peer);
-+ case AF_INET6:
-+ peer.type = PEER_TYPE_INET6;
-+ if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
-+ peer.name = "unknown";
-+ else
-+ peer.name = hbuf;
-+ peer.addr = abuf;
-+ return (&peer);
-+#endif
- case AF_UNSPEC:
- case AF_UNIX:
- peer.type = PEER_TYPE_LOCAL;
-diff -Pur postfix-1.1.11.20020613-orig/src/global/peer_name.h postfix-1.1.11-20020613/src/global/peer_name.h
---- postfix-1.1.11.20020613-orig/src/global/peer_name.h Fri Dec 11 19:55:32 1998
-+++ postfix-1.1.11.20020613/src/global/peer_name.h Wed Jun 26 15:26:48 2002
-@@ -22,6 +22,9 @@
- #define PEER_TYPE_UNKNOWN 0
- #define PEER_TYPE_INET 1
- #define PEER_TYPE_LOCAL 2
-+#ifdef INET6
-+#define PEER_TYPE_INET6 3
-+#endif
-
- extern PEER_NAME *peer_name(int);
-
-diff -Pur postfix-1.1.11.20020613-orig/src/global/pfixtls.c postfix-1.1.11-20020613/src/global/pfixtls.c
---- postfix-1.1.11.20020613-orig/src/global/pfixtls.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11.20020613/src/global/pfixtls.c Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,2742 @@
-+/*++
-+/* NAME
-+/* pfixtls
-+/* SUMMARY
-+/* interface to openssl routines
-+/* SYNOPSIS
-+/* #include <pfixtls.h>
-+/*
-+/* const long scache_db_version;
-+/* const long openssl_version;
-+/*
-+/* int pfixtls_serverengine;
-+/*
-+/* int pfixtls_clientengine;
-+/*
-+/* int pfixtls_timed_read(fd, buf, len, timeout, unused_context)
-+/* int fd;
-+/* void *buf;
-+/* unsigned len;
-+/* int timeout;
-+/* void *context;
-+/*
-+/* int pfixtls_timed_write(fd, buf, len, timeout, unused_context);
-+/* int fd;
-+/* void *buf;
-+/* unsigned len;
-+/* int timeout;
-+/* void *context;
-+/*
-+/* int pfixtls_init_serverengine(verifydepth, askcert);
-+/* int verifydepth;
-+/* int askcert;
-+/*
-+/* int pfixtls_start_servertls(stream, timeout, peername, peeraddr,
-+/* tls_info, requirecert);
-+/* VSTREAM *stream;
-+/* int timeout;
-+/* const char *peername;
-+/* const char *peeraddr;
-+/* tls_info_t *tls_info;
-+/* int requirecert;
-+/*
-+/* int pfixtls_stop_servertls(stream, failure, tls_info);
-+/* VSTREAM *stream;
-+/* int failure;
-+/* tls_info_t *tls_info;
-+/*
-+/* int pfixtls_init_clientengine(verifydepth);
-+/* int verifydepth;
-+/*
-+/* int pfixtls_start_clienttls(stream, timeout, peername, peeraddr,
-+/* tls_info);
-+/* VSTREAM *stream;
-+/* int timeout;
-+/* const char *peername;
-+/* const char *peeraddr;
-+/* tls_info_t *tls_info;
-+/*
-+/* int pfixtls_stop_clienttls(stream, failure, tls_info);
-+/* VSTREAM *stream;
-+/* int failure;
-+/* tls_info_t *tls_info;
-+/*
-+/* DESCRIPTION
-+/* This module is the interface between Postfix and the OpenSSL library.
-+/*
-+/* pfixtls_timed_read() reads the requested number of bytes calling
-+/* SSL_read(). pfixtls_time_read() will only be called indirect
-+/* as a VSTREAM_FN function.
-+/* pfixtls_timed_write() is the corresponding write function.
-+/*
-+/* pfixtls_init_serverengine() is called once when smtpd is started
-+/* in order to initialize as much of the TLS stuff as possible.
-+/* The certificate handling is also decided during the setup phase,
-+/* so that a peer specific handling is not possible.
-+/*
-+/* pfixtls_init_clientengine() is the corresponding function called
-+/* in smtp. Here we take the peer's (server's) certificate in any
-+/* case.
-+/*
-+/* pfixtls_start_servertls() activates the TLS feature for the VSTREAM
-+/* passed as argument. We expect that all buffers are flushed and the
-+/* TLS handshake can begin immediately. Information about the peer
-+/* is stored into the tls_info structure passed as argument.
-+/*
-+/* pfixtls_stop_servertls() sends the "close notify" alert via
-+/* SSL_shutdown() to the peer and resets all connection specific
-+/* TLS data. As RFC2487 does not specify a seperate shutdown, it
-+/* is supposed 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, the session is cleared from the cache.
-+/*
-+/* pfixtls_start_clienttls() and pfixtls_stop_clienttls() are the
-+/* corresponding functions for smtp.
-+/*
-+/* Once the TLS connection is initiated, information about the TLS
-+/* state is available via the tls_info structure:
-+/* protocol holds the protocol name (SSLv2, SSLv3, TLSv1),
-+/* tls_info->cipher_name the cipher name (e.g. RC4/MD5),
-+/* tls_info->cipher_usebits the number of bits actually used (e.g. 40),
-+/* tls_info->cipher_algbits the number of bits the algorithm is based on
-+/* (e.g. 128).
-+/* The last two values may be different when talking to a crippled
-+/* - ahem - export controled peer (e.g. 40/128).
-+/*
-+/* The status of the peer certificate verification is available in
-+/* pfixtls_peer_verified. It is set to 1, when the certificate could
-+/* be verified.
-+/* If the peer offered a certifcate, part of the certificate data are
-+/* available as:
-+/* tls_info->peer_subject X509v3-oneline with the DN of the peer
-+/* tls_info->peer_CN extracted CommonName of the peer
-+/* tls_info->peer_issuer X509v3-oneline with the DN of the issuer
-+/* tls_info->peer_CN extracted CommonName of the issuer
-+/* tls_info->PEER_FINGERPRINT fingerprint of the certificate
-+/*
-+/* DESCRIPTION (SESSION CACHING)
-+/* In order to achieve high performance when using a lot of connections
-+/* with TLS, session caching is implemented. It reduces both the CPU load
-+/* (less cryptograpic operations) and the network load (the amount of
-+/* certificate data exchanged is reduced).
-+/* Since postfix uses a setup of independent processes for receiving
-+/* and sending email, the processes must exchange the session information.
-+/* Several connections at the same time between the identical peers can
-+/* occur, so uniqueness and race conditions have to be taken into
-+/* account.
-+/* I have checked both Apache-SSL (Ben Laurie), using a seperate "gcache"
-+/* process and Apache mod_ssl (Ralf S. Engelshall), using shared memory
-+/* between several identical processes spawned from one parent.
-+/*
-+/* Postfix/TLS uses a database approach based on the internal "dict"
-+/* interface. Since the session cache information is approximately
-+/* 1300 bytes binary data, it will not fit into the dbm/ndbm model.
-+/* It also needs write access to the database, ruling out most other
-+/* interface, leaving Berkeley DB, which however cannot handle concurrent
-+/* access by several processes. Hence a modified SDBM (public domain DBM)
-+/* with enhanced buffer size is used and concurrent write capability
-+/* is used. SDBM is part of Postfix/TLS.
-+/*
-+/* Realization:
-+/* Both (client and server) session cache are realized by individual
-+/* cache databases. A common database would not make sense, since the
-+/* key criteria are different (session ID for server, peername for
-+/* client).
-+/*
-+/* Server side:
-+/* Session created by OpenSSL have a 32 byte session id, yielding a
-+/* 64 char file name. I consider these sessions to be unique. If they
-+/* are not, the last session will win, overwriting the older one in
-+/* the database. Remember: everything that is lost is a temporary
-+/* information and not more than a renegotiation will happen.
-+/* Originating from the same client host, several sessions can come
-+/* in (e.g. from several users sending mail with Netscape at the same
-+/* time), so the session id is the correct identifier; the hostname
-+/* is of no importance, here.
-+/*
-+/* Client side:
-+/* We cannot recall sessions based on their session id, because we would
-+/* have to check every session on disk for a matching server name, so
-+/* the lookup has to be done based on the FQDN of the peer (receiving
-+/* host).
-+/* With regard to uniqueness, we might experience several open connections
-+/* to the same server at the same time. This is even very likely to
-+/* happen, since we might have several mails for the same destination
-+/* in the queue, when a queue run is started. So several smtp's might
-+/* negotiate sessions at the same time. We can however only save one
-+/* session for one host.
-+/* Like on the server side, the "last write" wins. The reason is
-+/* quite simple. If we don't want to overwrite old sessions, an old
-+/* session file will just stay in place until it is expired. In the
-+/* meantime we would lose "fresh" session however. So we will keep the
-+/* fresh one instead to avoid unnecessary renegotiations.
-+/*
-+/* Session lifetime:
-+/* RFC2246 recommends a session lifetime of less than 24 hours. The
-+/* default is 300 seconds (5 minutes) for OpenSSL and is also used
-+/* this way in e.g. mod_ssl. The typical usage for emails might be
-+/* humans typing in emails and sending them, which might take just
-+/* a while, so I think 3600 seconds (1 hour) is a good compromise.
-+/* If the environment is save (the cached session contains secret
-+/* key data), one might even consider using a longer timeout. Anyway,
-+/* since everlasting sessions must be avoided, the session timeout
-+/* is done based on the creation date of the session and so each
-+/* session will timeout eventually.
-+/*
-+/* Connection failures:
-+/* RFC2246 requires us to remove sessions if something went wrong.
-+/* Since the in-memory session cache of other smtp[d] processes cannot
-+/* be controlled by simple means, we completely rely on the disc
-+/* based session caching and remove all sessions from memory after
-+/* connection closure.
-+/*
-+/* Cache cleanup:
-+/* Since old entries have to be removed from the session cache, a
-+/* cleanup process is needed that runs through the collected session
-+/* files on regular basis. The task is performed by tlsmgr based on
-+/* the timestamp created by pfixtls and included in the saved session,
-+/* so that tlsmgr has not to care about the SSL_SESSION internal data.
-+/*
-+/* BUGS
-+/* The memory allocation policy of the OpenSSL library is not well
-+/* documented, especially when loading sessions from disc. Hence there
-+/* might be memory leaks.
-+/*
-+/* LICENSE
-+/* AUTHOR(S)
-+/* Lutz Jaenicke
-+/* BTU Cottbus
-+/* Allgemeine Elektrotechnik
-+/* Universitaetsplatz 3-4
-+/* D-03044 Cottbus, Germany
-+/*--*/
-+
-+/* System library. */
-+
-+#include <sys_defs.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <sys/time.h> /* gettimeofday, not in POSIX */
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <ctype.h>
-+
-+/* Utility library. */
-+
-+#include <iostuff.h>
-+#include <mymalloc.h>
-+#include <vstring.h>
-+#include <vstream.h>
-+#include <dict.h>
-+#include <myflock.h>
-+#include <stringops.h>
-+#include <msg.h>
-+#include <connect.h>
-+
-+/* Application-specific. */
-+
-+#include "mail_params.h"
-+#include "pfixtls.h"
-+
-+#define STR vstring_str
-+
-+const tls_info_t tls_info_zero = {
-+ 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
-+};
-+
-+#ifdef HAS_SSL
-+
-+/* OpenSSL library. */
-+
-+#include <openssl/lhash.h>
-+#include <openssl/bn.h>
-+#include <openssl/err.h>
-+#include <openssl/pem.h>
-+#include <openssl/x509.h>
-+#include <openssl/rand.h>
-+#include <openssl/ssl.h>
-+
-+/* We must keep some of the info available */
-+static const char hexcodes[] = "0123456789ABCDEF";
-+
-+/*
-+ * When saving sessions, we want to make sure, that the lenght of the key
-+ * is somehow limited. When saving client sessions, the hostname is used
-+ * as key. According to HP-UX 10.20, MAXHOSTNAMELEN=64. Maybe new standards
-+ * will increase this value, but as this will break compatiblity with existing
-+ * implementations, we won't see this for long. We therefore choose a limit
-+ * of 64 bytes.
-+ * The length of the (TLS) session id can be up to 32 bytes according to
-+ * RFC2246, so it fits well into the 64bytes limit.
-+ */
-+#define ID_MAXLENGTH 64 /* Max ID length in bytes */
-+
-+/*
-+ * The session_id_context is set, such that the client knows which services
-+ * on a host share the same session information (on the postfix host may
-+ * as well run a TLS-enabled webserver.
-+ */
-+static char server_session_id_context[] = "Postfix/TLS"; /* anything will do */
-+static int TLScontext_index = -1;
-+static int TLSpeername_index = -1;
-+static int do_dump = 0;
-+static DH *dh_512 = NULL, *dh_1024 = NULL;
-+static SSL_CTX *ctx = NULL;
-+
-+static int rand_exch_fd = -1;
-+
-+static DICT *scache_db = NULL;
-+const long scache_db_version = 0x00000003L;
-+const long openssl_version = OPENSSL_VERSION_NUMBER;
-+
-+
-+int pfixtls_serverengine = 0;
-+static int pfixtls_serveractive = 0; /* available or not */
-+
-+int pfixtls_clientengine = 0;
-+static int pfixtls_clientactive = 0; /* available or not */
-+
-+/*
-+ * Define a maxlength for certificate onelines. The length is checked by
-+ * all routines when copying.
-+ */
-+#define CCERT_BUFSIZ 256
-+
-+typedef struct {
-+ SSL *con;
-+ BIO *internal_bio; /* postfix/TLS side of pair */
-+ BIO *network_bio; /* netsork 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[129];
-+ int enforce_verify_errors;
-+ int enforce_CN;
-+} TLScontext_t;
-+
-+typedef struct {
-+ int pid;
-+ struct timeval tv;
-+} randseed_t;
-+
-+static randseed_t randseed;
-+
-+/*
-+ * Finally some "backup" DH-Parameters to be loaded, if no parameters are
-+ * explicitely loaded from file.
-+ */
-+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,
-+};
-+
-+/*
-+ * DESCRIPTION: Keeping control of the network interface using BIO-pairs.
-+ *
-+ * When the TLS layer is active, all input/output must be filtered through
-+ * it. On the other hand to handle timeout conditions, full control over
-+ * the network socket must be kept. This rules out the "normal way" of
-+ * connecting the TLS layer directly to the socket.
-+ * The TLS layer is realized with a BIO-pair:
-+ *
-+ * postfix | TLS-engine
-+ * | |
-+ * +--------> SSL_operations()
-+ * | /\ ||
-+ * | || \/
-+ * | BIO-pair (internal_bio)
-+ * +--------< BIO-pair (network_bio)
-+ * | |
-+ * socket |
-+ *
-+ * The normal postfix operations connect to the SSL operations to send
-+ * and retrieve (cleartext) data. Inside the TLS-engine the data are converted
-+ * to/from TLS protocol. The TLS functionality itself is only connected to
-+ * the internal_bio and hence only has status information about this internal
-+ * interface.
-+ * Thus, if the SSL_operations() return successfully (SSL_ERROR_NONE) or want
-+ * to read (SSL_ERROR_WANT_READ) there may as well be data inside the buffering
-+ * BIO-pair. So whenever an SSL_operation() returns without a fatal error,
-+ * the BIO-pair internal buffer must be flushed to the network.
-+ * NOTE: This is especially true in the SSL_ERROR_WANT_READ case: the TLS-layer
-+ * might want to read handshake data, that will never come since its own
-+ * written data will only reach the peer after flushing the buffer!
-+ *
-+ * The BIO-pair buffer size has been set to 8192 bytes, this is an arbitrary
-+ * value that can hold more data than the typical PMTU, so that it does
-+ * not force the generation of packets smaller than necessary.
-+ * It is also larger than the default VSTREAM_BUFSIZE (4096, see vstream.h),
-+ * so that large write operations could be handled within one call.
-+ * The internal buffer in the network/network_bio handling layer has been
-+ * 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.
-+ */
-+
-+const ssize_t BIO_bufsiz = 8192;
-+
-+/*
-+ * The interface layer between network and BIO-pair. The BIO-pair buffers
-+ * the data to/from the TLS layer. Hence, at any time, there may be data
-+ * in the buffer that must be written to the network. This writing has
-+ * highest priority because the handshake might fail otherwise.
-+ * Only then a read_request can be satisfied.
-+ */
-+static int network_biopair_interop(int fd, int timeout, BIO *network_bio)
-+{
-+ int want_write;
-+ int num_write;
-+ int write_pos;
-+ int from_bio;
-+ int want_read;
-+ int num_read;
-+ int to_bio;
-+#define NETLAYER_BUFFERSIZE 8192
-+ char buffer[8192];
-+
-+ while ((want_write = BIO_ctrl_pending(network_bio)) > 0) {
-+ if (want_write > NETLAYER_BUFFERSIZE)
-+ want_write = NETLAYER_BUFFERSIZE;
-+ from_bio = BIO_read(network_bio, buffer, want_write);
-+
-+ /*
-+ * Write the complete contents of the buffer. Since TLS performs
-+ * underlying handshaking, we cannot afford to leave the buffer
-+ * unflushed, as we could run into a deadlock trap (the peer
-+ * waiting for a final byte and we already waiting for his reply
-+ * in read position).
-+ */
-+ write_pos = 0;
-+ do {
-+ 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)
-+ return (-1); /* something happened to the socket */
-+ write_pos += num_write;
-+ } while (write_pos < from_bio);
-+ }
-+
-+ while ((want_read = BIO_ctrl_get_read_request(network_bio)) > 0) {
-+ if (want_read > NETLAYER_BUFFERSIZE)
-+ want_read = NETLAYER_BUFFERSIZE;
-+ if (timeout > 0 && read_wait(fd, timeout) < 0)
-+ return (-1);
-+ num_read = read(fd, buffer, want_read);
-+ if (num_read <= 0)
-+ return (-1); /* something happened to the socket */
-+ to_bio = BIO_write(network_bio, buffer, num_read);
-+ if (to_bio != num_read)
-+ msg_fatal("to_bio != num_read");
-+ }
-+
-+ return (0);
-+}
-+
-+static void pfixtls_print_errors(void);
-+
-+ /*
-+ * Function to perform the handshake for SSL_accept(), SSL_connect(),
-+ * and SSL_shutdown() and perform the SSL_read(), SSL_write() operations.
-+ * Call the underlying network_biopair_interop-layer to make sure the
-+ * write buffer is flushed after every operation (that did not fail with
-+ * a fatal error).
-+ */
-+static int do_tls_operation(int fd, int timeout, TLScontext_t *TLScontext,
-+ int (*hsfunc)(SSL *),
-+ int (*rfunc)(SSL *, void *, int),
-+ int (*wfunc)(SSL *, const void *, int),
-+ char *buf, int num)
-+{
-+ int status;
-+ int err;
-+ int retval = 0;
-+ int biop_retval;
-+ int done = 0;
-+
-+ while (!done) {
-+ if (hsfunc)
-+ status = hsfunc(TLScontext->con);
-+ else if (rfunc)
-+ status = rfunc(TLScontext->con, buf, num);
-+ else
-+ status = wfunc(TLScontext->con, (const char *)buf, num);
-+ 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(); /* Keep information for the logfile */
-+ msg_info("OpenSSL <= 0.9.5a workaround called: certificate errors ignored");
-+ err = SSL_get_error(TLScontext->con, status);
-+ }
-+ }
-+#endif
-+
-+ switch (err) {
-+ case SSL_ERROR_NONE: /* success */
-+ retval = status;
-+ done = 1; /* no break, flush buffer before */
-+ /* leaving */
-+ case SSL_ERROR_WANT_WRITE:
-+ case SSL_ERROR_WANT_READ:
-+ biop_retval = network_biopair_interop(fd, timeout,
-+ TLScontext->network_bio);
-+ if (biop_retval < 0)
-+ return (-1); /* fatal network error */
-+ break;
-+ case SSL_ERROR_ZERO_RETURN: /* connection was closed cleanly */
-+ case SSL_ERROR_SYSCALL:
-+ case SSL_ERROR_SSL:
-+ default:
-+ retval = status;
-+ done = 1;
-+ ;
-+ }
-+ };
-+ return retval;
-+}
-+
-+int pfixtls_timed_read(int fd, void *buf, unsigned buf_len, int timeout,
-+ void *context)
-+{
-+ int i;
-+ int ret;
-+ char mybuf[40];
-+ char *mybuf2;
-+ TLScontext_t *TLScontext;
-+
-+ TLScontext = (TLScontext_t *)context;
-+ if (!TLScontext)
-+ msg_fatal("Called tls_timed_read() without TLS-context");
-+
-+ ret = do_tls_operation(fd, timeout, TLScontext, NULL, SSL_read, NULL,
-+ (char *)buf, buf_len);
-+ if ((pfixtls_serveractive && var_smtpd_tls_loglevel >= 4) ||
-+ (pfixtls_clientactive && var_smtp_tls_loglevel >= 4)) {
-+ mybuf2 = (char *) buf;
-+ if (ret > 0) {
-+ i = 0;
-+ while ((i < 39) && (i < ret) && (mybuf2[i] != 0)) {
-+ mybuf[i] = mybuf2[i];
-+ i++;
-+ }
-+ mybuf[i] = '\0';
-+ msg_info("Read %d chars: %s", ret, mybuf);
-+ }
-+ }
-+ return (ret);
-+}
-+
-+int pfixtls_timed_write(int fd, void *buf, unsigned len, int timeout,
-+ void *context)
-+{
-+ int i;
-+ char mybuf[40];
-+ char *mybuf2;
-+ TLScontext_t *TLScontext;
-+
-+ TLScontext = (TLScontext_t *)context;
-+ if (!TLScontext)
-+ msg_fatal("Called tls_timed_write() without TLS-context");
-+
-+ if ((pfixtls_serveractive && var_smtpd_tls_loglevel >= 4) ||
-+ (pfixtls_clientactive && var_smtp_tls_loglevel >= 4)) {
-+ mybuf2 = (char *) buf;
-+ if (len > 0) {
-+ i = 0;
-+ while ((i < 39) && (i < len) && (mybuf2[i] != 0)) {
-+ mybuf[i] = mybuf2[i];
-+ i++;
-+ }
-+ mybuf[i] = '\0';
-+ msg_info("Write %d chars: %s", len, mybuf);
-+ }
-+ }
-+ return (do_tls_operation(fd, timeout, TLScontext, NULL, NULL, SSL_write,
-+ buf, len));
-+}
-+
-+/* Add some more entropy to the pool by adding the actual time */
-+
-+static void pfixtls_stir_seed(void)
-+{
-+ GETTIMEOFDAY(&randseed.tv);
-+ RAND_seed(&randseed, sizeof(randseed_t));
-+}
-+
-+/*
-+ * Skeleton taken from OpenSSL crypto/err/err_prn.c.
-+ * Query the error stack and print the error string into the logging facility.
-+ * Clear the error stack on the way.
-+ */
-+
-+static void pfixtls_print_errors(void)
-+{
-+ unsigned long l;
-+ char buf[256];
-+ const char *file;
-+ const char *data;
-+ int line;
-+ int flags;
-+ unsigned long es;
-+
-+ es = CRYPTO_thread_id();
-+ while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
-+ if (flags & ERR_TXT_STRING)
-+ msg_info("%lu:%s:%s:%d:%s:", es, ERR_error_string(l, buf),
-+ file, line, data);
-+ else
-+ msg_info("%lu:%s:%s:%d:", es, ERR_error_string(l, buf),
-+ file, line);
-+ }
-+}
-+
-+ /*
-+ * Set up the cert things on the server side. We do need both the
-+ * private key (in key_file) and the cert (in cert_file).
-+ * Both files may be identical.
-+ *
-+ * This function is taken from OpenSSL apps/s_cb.c
-+ */
-+
-+static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
-+{
-+ if (cert_file != NULL) {
-+ if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
-+ msg_info("unable to get certificate from '%s'", cert_file);
-+ pfixtls_print_errors();
-+ return (0);
-+ }
-+ if (key_file == NULL)
-+ key_file = cert_file;
-+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
-+ SSL_FILETYPE_PEM) <= 0) {
-+ msg_info("unable to get private key from '%s'", key_file);
-+ pfixtls_print_errors();
-+ return (0);
-+ }
-+ /* Now we know that a key and cert have been set against
-+ * the SSL context */
-+ if (!SSL_CTX_check_private_key(ctx)) {
-+ msg_info("Private key does not match the certificate public key");
-+ return (0);
-+ }
-+ }
-+ return (1);
-+}
-+
-+/* taken from OpenSSL apps/s_cb.c */
-+
-+static RSA *tmp_rsa_cb(SSL * s, int export, int keylength)
-+{
-+ static RSA *rsa_tmp = NULL;
-+
-+ if (rsa_tmp == NULL) {
-+ rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
-+ }
-+ return (rsa_tmp);
-+}
-+
-+
-+static DH *get_dh512(void)
-+{
-+ DH *dh;
-+
-+ if (dh_512 == NULL) {
-+ /* No parameter file loaded, use the compiled in parameters */
-+ if ((dh = DH_new()) == NULL) return(NULL);
-+ dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
-+ dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
-+ if ((dh->p == NULL) || (dh->g == NULL))
-+ return(NULL);
-+ else
-+ dh_512 = dh;
-+ }
-+ return (dh_512);
-+}
-+
-+static DH *get_dh1024(void)
-+{
-+ DH *dh;
-+
-+ if (dh_1024 == NULL) {
-+ /* No parameter file loaded, use the compiled in parameters */
-+ if ((dh = DH_new()) == NULL) return(NULL);
-+ dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
-+ dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
-+ if ((dh->p == NULL) || (dh->g == NULL))
-+ return(NULL);
-+ else
-+ dh_1024 = dh;
-+ }
-+ return (dh_1024);
-+}
-+
-+/* partly inspired by mod_ssl */
-+
-+static DH *tmp_dh_cb(SSL *s, int export, int keylength)
-+{
-+ DH *dh_tmp = NULL;
-+
-+ if (export) {
-+ if (keylength == 512)
-+ dh_tmp = get_dh512(); /* export cipher */
-+ else if (keylength == 1024)
-+ dh_tmp = get_dh1024(); /* normal */
-+ else
-+ dh_tmp = get_dh1024(); /* not on-the-fly (too expensive) */
-+ /* so use the 1024bit instead */
-+ }
-+ else {
-+ dh_tmp = get_dh1024(); /* sign-only certificate */
-+ }
-+ return (dh_tmp);
-+}
-+
-+
-+/*
-+ * Skeleton taken from OpenSSL apps/s_cb.c
-+ *
-+ * The verify_callback is called several times (directly or indirectly) from
-+ * crypto/x509/x509_vfy.c. It is called as a last check for several issues,
-+ * so this verify_callback() has the famous "last word". If it does return "0",
-+ * the handshake is immediately shut down and the connection fails.
-+ *
-+ * Postfix/TLS has two modes, the "use" mode and the "enforce" mode:
-+ *
-+ * In the "use" mode we never want the connection to fail just because there is
-+ * something wrong with the certificate (as we would have sent happily without
-+ * TLS). Therefore the return value is always "1".
-+ *
-+ * In the "enforce" mode we can shut down the connection as soon as possible.
-+ * In server mode TLS itself may be enforced (e.g. to protect passwords),
-+ * but certificates are optional. In this case the handshake must not fail
-+ * if we are unhappy with the certificate and return "1" in any case.
-+ * Only if a certificate is required the certificate must pass the verification
-+ * and failure to do so will result in immediate termination (return 0).
-+ * In the client mode the decision is made with respect to the peername
-+ * enforcement. If we strictly enforce the matching of the expected peername
-+ * the verification must fail immediatly on verification errors. We can also
-+ * immediatly check the expected peername, as it is the CommonName at level 0.
-+ * In all other cases, the problem is logged, so the SSL_get_verify_result()
-+ * will inform about the verification failure, but the handshake (and SMTP
-+ * connection will continue).
-+ *
-+ * The only error condition not handled inside the OpenSSL-Library is the
-+ * case of a too-long certificate chain, so we check inside verify_callback().
-+ * We only take care of this problem, if "ok = 1", because otherwise the
-+ * verification already failed because of another problem and we don't want
-+ * to overwrite the other error message. And if the verification failed,
-+ * there is no such thing as "more failed", "most failed"... :-)
-+ */
-+
-+static int verify_callback(int ok, X509_STORE_CTX * ctx)
-+{
-+ char buf[256];
-+ char *CN_lowercase;
-+ char *peername_left;
-+ X509 *err_cert;
-+ int err;
-+ int depth;
-+ int verify_depth;
-+ int hostname_matched;
-+ SSL *con;
-+ TLScontext_t *TLScontext;
-+
-+ 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, 256);
-+ if (((pfixtls_serverengine) && (var_smtpd_tls_loglevel >= 2)) ||
-+ ((pfixtls_clientengine) && (var_smtp_tls_loglevel >= 2)))
-+ msg_info("Peer cert verify depth=%d %s", depth, buf);
-+
-+ 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("verify error:num=%d:%s", err,
-+ X509_verify_cert_error_string(err));
-+ }
-+
-+ if (ok && (depth == 0) && pfixtls_clientengine) {
-+ /*
-+ * Check out the name certified against the hostname expected.
-+ * In case it does not match, print an information about the result.
-+ * If a matching is enforced, bump out with a verification error
-+ * immediately.
-+ */
-+ buf[0] = '\0';
-+ if (!X509_NAME_get_text_by_NID(X509_get_subject_name(err_cert),
-+ NID_commonName, buf, 256)) {
-+ msg_info("Could not parse server's subject CN");
-+ pfixtls_print_errors();
-+ }
-+ CN_lowercase = lowercase(buf);
-+ hostname_matched = 0;
-+ if (!strcmp(TLScontext->peername_save, CN_lowercase))
-+ hostname_matched = 1;
-+ else if ((strlen(CN_lowercase) > 2) &&
-+ (CN_lowercase[0] == '*') && (CN_lowercase[1] == '.')) {
-+ /*
-+ * Allow wildcard certificate matching. The proposed rules in
-+ * RFCs (2818: HTTP/TLS, 2830: LDAP/TLS) are different, RFC2874
-+ * does not specify a rule, so here the strict rule is applied.
-+ * An asterisk '*' is allowed as the leftmost component and may
-+ * replace the left most part of the hostname. Matching is done
-+ * by removing '*.' from the wildcard name and the `name.` from
-+ * the peername and compare what is left.
-+ */
-+ peername_left = strchr(TLScontext->peername_save, '.');
-+ if (peername_left) {
-+ if (!strcmp(peername_left + 1, CN_lowercase + 2))
-+ hostname_matched = 1;
-+ }
-+ }
-+
-+ if (!hostname_matched) {
-+ msg_info("Peer verification: CommonName in certificate does not match: %s != %s", CN_lowercase, TLScontext->peername_save);
-+ if (TLScontext->enforce_verify_errors && TLScontext->enforce_CN) {
-+ err = X509_V_ERR_CERT_REJECTED;
-+ X509_STORE_CTX_set_error(ctx, err);
-+ msg_info("Verify failure: Hostname mismatch");
-+ ok = 0;
-+ }
-+ }
-+ }
-+
-+ switch (ctx->error) {
-+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
-+ msg_info("issuer= %s", buf);
-+ break;
-+ case X509_V_ERR_CERT_NOT_YET_VALID:
-+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
-+ msg_info("cert not yet valid");
-+ break;
-+ case X509_V_ERR_CERT_HAS_EXPIRED:
-+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
-+ msg_info("cert has expired");
-+ break;
-+ }
-+ if (((pfixtls_serverengine) && (var_smtpd_tls_loglevel >= 2)) ||
-+ ((pfixtls_clientengine) && (var_smtp_tls_loglevel >= 2)))
-+ msg_info("verify return:%d", ok);
-+
-+ if (TLScontext->enforce_verify_errors)
-+ return (ok);
-+ else
-+ return (1);
-+}
-+
-+/* taken from OpenSSL apps/s_cb.c */
-+
-+static void apps_ssl_info_callback(SSL * s, int where, int ret)
-+{
-+ char *str;
-+ int w;
-+
-+ w = where & ~SSL_ST_MASK;
-+
-+ if (w & SSL_ST_CONNECT)
-+ str = "SSL_connect";
-+ else if (w & SSL_ST_ACCEPT)
-+ str = "SSL_accept";
-+ else
-+ str = "undefined";
-+
-+ 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.
-+ */
-+
-+#define TRUNCATE
-+#define DUMP_WIDTH 16
-+
-+static int pfixtls_dump(const char *s, int len)
-+{
-+ int ret = 0;
-+ char buf[160 + 1];
-+ char *ss;
-+ int i;
-+ int j;
-+ int rows;
-+ int trunc;
-+ unsigned char ch;
-+
-+ trunc = 0;
-+
-+#ifdef TRUNCATE
-+ for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
-+ trunc++;
-+#endif
-+
-+ rows = (len / DUMP_WIDTH);
-+ if ((rows * DUMP_WIDTH) < len)
-+ rows++;
-+
-+ for (i = 0; i < rows; i++) {
-+ buf[0] = '\0'; /* start with empty string */
-+ ss = buf;
-+
-+ sprintf(ss, "%04x ", i * DUMP_WIDTH);
-+ ss += strlen(ss);
-+ for (j = 0; j < DUMP_WIDTH; j++) {
-+ if (((i * DUMP_WIDTH) + j) >= len) {
-+ strcpy(ss, " ");
-+ } else {
-+ ch = ((unsigned char) *((char *) (s) + i * DUMP_WIDTH + j))
-+ & 0xff;
-+ sprintf(ss, "%02x%c", ch, j == 7 ? '|' : ' ');
-+ ss += 3;
-+ }
-+ }
-+ ss += strlen(ss);
-+ *ss++ = ' ';
-+ for (j = 0; j < DUMP_WIDTH; j++) {
-+ if (((i * DUMP_WIDTH) + j) >= len)
-+ break;
-+ ch = ((unsigned char) *((char *) (s) + i * DUMP_WIDTH + j)) & 0xff;
-+ *ss++ = (((ch >= ' ') && (ch <= '~')) ? ch : '.');
-+ if (j == 7) *ss++ = ' ';
-+ }
-+ *ss = 0;
-+ /*
-+ * if this is the last call then update the ddt_dump thing so that
-+ * we will move the selection point in the debug window
-+ */
-+ msg_info("%s", buf);
-+ ret += strlen(buf);
-+ }
-+#ifdef TRUNCATE
-+ if (trunc > 0) {
-+ sprintf(buf, "%04x - <SPACES/NULS>\n", len + trunc);
-+ msg_info("%s", buf);
-+ ret += strlen(buf);
-+ }
-+#endif
-+ return (ret);
-+}
-+
-+
-+
-+/* taken from OpenSSL apps/s_cb.c */
-+
-+static long bio_dump_cb(BIO * bio, int cmd, const char *argp, int argi,
-+ long argl, long ret)
-+{
-+ if (!do_dump)
-+ return (ret);
-+
-+ if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
-+ msg_info("read from %08X [%08lX] (%d bytes => %ld (0x%X))",
-+ (unsigned int)bio, (unsigned long)argp, argi,
-+ ret, (unsigned int)ret);
-+ pfixtls_dump(argp, (int) ret);
-+ return (ret);
-+ } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
-+ msg_info("write to %08X [%08lX] (%d bytes => %ld (0x%X))",
-+ (unsigned int)bio, (unsigned long)argp, argi,
-+ ret, (unsigned int)ret);
-+ pfixtls_dump(argp, (int) ret);
-+ }
-+ return (ret);
-+}
-+
-+
-+ /*
-+ * Callback to retrieve a session from the external session cache.
-+ */
-+static SSL_SESSION *get_session_cb(SSL *ssl, unsigned char *SessionID,
-+ int length, int *copy)
-+{
-+ SSL_SESSION *session;
-+ char idstring[2 * ID_MAXLENGTH + 1];
-+ int n;
-+ int uselength;
-+ int hex_length;
-+ const char *session_hex;
-+ pfixtls_scache_info_t scache_info;
-+ unsigned char nibble, *data, *sess_data;
-+
-+ if (length > ID_MAXLENGTH)
-+ uselength = ID_MAXLENGTH; /* Limit length of ID */
-+ else
-+ uselength = length;
-+
-+ for(n=0 ; n < uselength ; n++)
-+ sprintf(idstring + 2 * n, "%02x", SessionID[n]);
-+ if (var_smtpd_tls_loglevel >= 3)
-+ msg_info("Trying to reload Session from disc: %s", idstring);
-+
-+ session = NULL;
-+
-+ session_hex = dict_get(scache_db, idstring);
-+ if (session_hex) {
-+ hex_length = strlen(session_hex);
-+ data = (unsigned char *)mymalloc(hex_length / 2);
-+ if (!data) {
-+ msg_info("could not allocate memory for session reload");
-+ return(NULL);
-+ }
-+
-+ memset(data, 0, hex_length / 2);
-+ for (n = 0; n < hex_length; n++) {
-+ if ((session_hex[n] >= '0') && (session_hex[n] <= '9'))
-+ nibble = session_hex[n] - '0';
-+ else
-+ nibble = session_hex[n] - 'A' + 10;
-+ if (n % 2)
-+ data[n / 2] |= nibble;
-+ else
-+ data[n / 2] |= (nibble << 4);
-+ }
-+
-+ /*
-+ * First check the version numbers, since wrong session data might
-+ * hit us hard (SEGFAULT). We also have to check for expiry.
-+ */
-+ memcpy(&scache_info, data, sizeof(pfixtls_scache_info_t));
-+ if ((scache_info.scache_db_version != scache_db_version) ||
-+ (scache_info.openssl_version != openssl_version) ||
-+ (scache_info.timestamp + var_smtpd_tls_scache_timeout < time(NULL)))
-+ dict_del(scache_db, idstring);
-+ else {
-+ sess_data = data + sizeof(pfixtls_scache_info_t);
-+ session = d2i_SSL_SESSION(NULL, &sess_data,
-+ hex_length / 2 - sizeof(pfixtls_scache_info_t));
-+ if (!session)
-+ pfixtls_print_errors();
-+ }
-+ myfree((char *)data);
-+ }
-+
-+ if (session && (var_smtpd_tls_loglevel >= 3))
-+ msg_info("Successfully reloaded session from disc");
-+
-+ return (session);
-+}
-+
-+
-+static SSL_SESSION *load_clnt_session(const char *hostname,
-+ int enforce_peername)
-+{
-+ SSL_SESSION *session = NULL;
-+ char idstring[ID_MAXLENGTH + 1];
-+ int n;
-+ int uselength;
-+ int length;
-+ int hex_length;
-+ const char *session_hex;
-+ pfixtls_scache_info_t scache_info;
-+ unsigned char nibble, *data, *sess_data;
-+
-+ length = strlen(hostname);
-+ if (length > ID_MAXLENGTH)
-+ uselength = ID_MAXLENGTH; /* Limit length of ID */
-+ else
-+ uselength = length;
-+
-+ for(n=0 ; n < uselength ; n++)
-+ idstring[n] = tolower(hostname[n]);
-+ idstring[uselength] = '\0';
-+ if (var_smtp_tls_loglevel >= 3)
-+ msg_info("Trying to reload Session from disc: %s", idstring);
-+
-+ session_hex = dict_get(scache_db, idstring);
-+ if (session_hex) {
-+ hex_length = strlen(session_hex);
-+ data = (unsigned char *)mymalloc(hex_length / 2);
-+ if (!data) {
-+ msg_info("could not allocate memory for session reload");
-+ return(NULL);
-+ }
-+
-+ memset(data, 0, hex_length / 2);
-+ for (n = 0; n < hex_length; n++) {
-+ if ((session_hex[n] >= '0') && (session_hex[n] <= '9'))
-+ nibble = session_hex[n] - '0';
-+ else
-+ nibble = session_hex[n] - 'A' + 10;
-+ if (n % 2)
-+ data[n / 2] |= nibble;
-+ else
-+ data[n / 2] |= (nibble << 4);
-+ }
-+
-+ /*
-+ * First check the version numbers, since wrong session data might
-+ * hit us hard (SEGFAULT). We also have to check for expiry.
-+ * When we enforce_peername, we may find an old session, that was
-+ * saved when enforcement was not set. In this case the session will
-+ * be removed and a fresh session will be negotiated.
-+ */
-+ memcpy(&scache_info, data, sizeof(pfixtls_scache_info_t));
-+ if ((scache_info.scache_db_version != scache_db_version) ||
-+ (scache_info.openssl_version != openssl_version) ||
-+ (scache_info.timestamp + var_smtpd_tls_scache_timeout < time(NULL)))
-+ dict_del(scache_db, idstring);
-+ else if (enforce_peername && (!scache_info.enforce_peername))
-+ dict_del(scache_db, idstring);
-+ else {
-+ sess_data = data + sizeof(pfixtls_scache_info_t);
-+ session = d2i_SSL_SESSION(NULL, &sess_data,
-+ hex_length / 2 - sizeof(time_t));
-+ strncpy(SSL_SESSION_get_ex_data(session, TLSpeername_index),
-+ idstring, ID_MAXLENGTH + 1);
-+ if (!session)
-+ pfixtls_print_errors();
-+ }
-+ myfree((char *)data);
-+ }
-+
-+ if (session && (var_smtp_tls_loglevel >= 3))
-+ msg_info("Successfully reloaded session from disc");
-+
-+ return (session);
-+}
-+
-+
-+static void create_client_lookup_id(char *idstring, char *hostname)
-+{
-+ int n, len, uselength;
-+
-+ len = strlen(hostname);
-+ if (len > ID_MAXLENGTH)
-+ uselength = ID_MAXLENGTH; /* Limit length of ID */
-+ else
-+ uselength = len;
-+
-+ for (n = 0 ; n < uselength ; n++)
-+ idstring[n] = tolower(hostname[n]);
-+ idstring[uselength] = '\0';
-+}
-+
-+
-+static void create_server_lookup_id(char *idstring, SSL_SESSION *session)
-+{
-+ int n, uselength;
-+
-+ if (session->session_id_length > ID_MAXLENGTH)
-+ uselength = ID_MAXLENGTH; /* Limit length of ID */
-+ else
-+ uselength = session->session_id_length;
-+
-+ for(n = 0; n < uselength ; n++)
-+ sprintf(idstring + 2 * n, "%02x", session->session_id[n]);
-+}
-+
-+
-+static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *session)
-+{
-+ char idstring[2 * ID_MAXLENGTH + 1];
-+ char *hostname;
-+
-+ if (pfixtls_clientengine) {
-+ hostname = SSL_SESSION_get_ex_data(session, TLSpeername_index);
-+ create_client_lookup_id(idstring, hostname);
-+ if (var_smtp_tls_loglevel >= 3)
-+ msg_info("Trying to remove session from disc: %s", idstring);
-+ }
-+ else {
-+ create_server_lookup_id(idstring, session);
-+ if (var_smtpd_tls_loglevel >= 3)
-+ msg_info("Trying to remove session from disc: %s", idstring);
-+ }
-+
-+ if (scache_db)
-+ dict_del(scache_db, idstring);
-+}
-+
-+
-+/*
-+ * We need space to save the peername into the SSL_SESSION, as we must
-+ * look up the external database for client sessions by peername, not
-+ * by session id. We therefore allocate place for the peername string,
-+ * when a new SSL_SESSION is generated. It is filled later.
-+ */
-+static int new_peername_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
-+ int idx, long argl, void *argp)
-+{
-+ char *peername;
-+
-+ peername = (char *)mymalloc(ID_MAXLENGTH + 1);
-+ if (!peername)
-+ return 0;
-+ peername[0] = '\0'; /* initialize */
-+ return CRYPTO_set_ex_data(ad, idx, peername);
-+}
-+
-+/*
-+ * When the SSL_SESSION is removed again, we must free the memory to avoid
-+ * leaks.
-+ */
-+static void free_peername_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
-+ int idx, long argl, void *argp)
-+{
-+ myfree(CRYPTO_get_ex_data(ad, idx));
-+}
-+
-+/*
-+ * Duplicate application data, when a SSL_SESSION is duplicated
-+ */
-+static int dup_peername_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
-+ void *from_d, int idx, long argl, void *argp)
-+{
-+ char *peername_old, *peername_new;
-+
-+ peername_old = CRYPTO_get_ex_data(from, idx);
-+ peername_new = CRYPTO_get_ex_data(to, idx);
-+ if (!peername_old || !peername_new)
-+ return 0;
-+ memcpy(peername_new, peername_old, ID_MAXLENGTH + 1);
-+ return 1;
-+}
-+
-+
-+ /*
-+ * Save a new session to the external cache
-+ */
-+static int new_session_cb(SSL *ssl, SSL_SESSION *session)
-+{
-+ char idstring[2 * ID_MAXLENGTH + 1];
-+ int n;
-+ int dsize;
-+ int len;
-+ unsigned char *data, *sess_data;
-+ pfixtls_scache_info_t scache_info;
-+ char *hexdata, *hostname;
-+ TLScontext_t *TLScontext;
-+
-+ if (pfixtls_clientengine) {
-+ TLScontext = SSL_get_ex_data(ssl, TLScontext_index);
-+ hostname = TLScontext->peername_save;
-+ create_client_lookup_id(idstring, hostname);
-+ strncpy(SSL_SESSION_get_ex_data(session, TLSpeername_index),
-+ hostname, ID_MAXLENGTH + 1);
-+ /*
-+ * 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.
-+ */
-+ scache_info.enforce_peername =
-+ (TLScontext->enforce_verify_errors && TLScontext->enforce_CN);
-+
-+ if (var_smtp_tls_loglevel >= 3)
-+ msg_info("Trying to save session for hostID to disc: %s", idstring);
-+
-+#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
-+
-+ }
-+ else {
-+ create_server_lookup_id(idstring, session);
-+ if (var_smtpd_tls_loglevel >= 3)
-+ msg_info("Trying to save Session to disc: %s", idstring);
-+ }
-+
-+
-+ /*
-+ * Get the session and convert it into some "database" useable form.
-+ * First, get the length of the session to allocate the memory.
-+ */
-+ dsize = i2d_SSL_SESSION(session, NULL);
-+ if (dsize < 0) {
-+ msg_info("Could not access session");
-+ return 0;
-+ }
-+ data = (unsigned char *)mymalloc(dsize + sizeof(pfixtls_scache_info_t));
-+ if (!data) {
-+ msg_info("could not allocate memory for SSL session");
-+ return 0;
-+ }
-+
-+ /*
-+ * OpenSSL is not robust against wrong session data (might SEGFAULT),
-+ * so we secure it against version ids (session cache structure as well
-+ * as OpenSSL version).
-+ */
-+ scache_info.scache_db_version = scache_db_version;
-+ scache_info.openssl_version = openssl_version;
-+
-+ /*
-+ * Put a timestamp, so that expiration can be checked without
-+ * analyzing the session data itself. (We would need OpenSSL funtions,
-+ * since the SSL_SESSION is a private structure.)
-+ */
-+ scache_info.timestamp = time(NULL);
-+
-+ memcpy(data, &scache_info, sizeof(pfixtls_scache_info_t));
-+ sess_data = data + sizeof(pfixtls_scache_info_t);
-+
-+ /*
-+ * Now, obtain the session. Unfortunately, it is binary and dict_update
-+ * cannot handle binary data (it could contain '\0' in it) directly.
-+ * To save memory we could use base64 encoding. To make handling easier,
-+ * we simply use hex format.
-+ */
-+ len = i2d_SSL_SESSION(session, &sess_data);
-+ len += sizeof(pfixtls_scache_info_t);
-+
-+ hexdata = (char *)mymalloc(2 * len + 1);
-+
-+ if (!hexdata) {
-+ msg_info("could not allocate memory for SSL session (HEX)");
-+ myfree((char *)data);
-+ return 0;
-+ }
-+ for (n = 0; n < len; n++) {
-+ hexdata[n * 2] = hexcodes[(data[n] & 0xf0) >> 4];
-+ hexdata[(n * 2) + 1] = hexcodes[(data[n] & 0x0f)];
-+ }
-+ hexdata[len * 2] = '\0';
-+
-+ /*
-+ * The session id is a hex string, all uppercase. We are using SDBM as
-+ * compiled into Postfix with 8kB maximum entry size, so we set a limit
-+ * when caching. If the session is not cached, we have to renegotiate,
-+ * not more, not less. For a real session, this limit should never be
-+ * met
-+ */
-+ if (strlen(idstring) + strlen(hexdata) < 8000)
-+ dict_put(scache_db, idstring, hexdata);
-+
-+ myfree(hexdata);
-+ myfree((char *)data);
-+ return (1);
-+}
-+
-+
-+ /*
-+ * pfixtls_exchange_seed: read bytes from the seed exchange-file (expect
-+ * 1024 bytes)and immediately write back random bytes. Do so with EXCLUSIVE
-+ * lock, so * that each process will find a completely different (and
-+ * reseeded) file.
-+ */
-+static void pfixtls_exchange_seed(void)
-+{
-+ unsigned char buffer[1024];
-+
-+ if (rand_exch_fd == -1)
-+ return;
-+
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
-+ msg_info("Could not lock random exchange file: %s",
-+ strerror(errno));
-+
-+ lseek(rand_exch_fd, 0, SEEK_SET);
-+ if (read(rand_exch_fd, buffer, 1024) < 0)
-+ msg_fatal("reading exchange file failed");
-+ RAND_seed(buffer, 1024);
-+
-+ RAND_bytes(buffer, 1024);
-+ lseek(rand_exch_fd, 0, SEEK_SET);
-+ if (write(rand_exch_fd, buffer, 1024) != 1024)
-+ msg_fatal("Writing exchange file failed");
-+
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
-+ msg_fatal("Could not unlock random exchange file: %s",
-+ strerror(errno));
-+}
-+
-+ /*
-+ * This is the setup routine for the SSL server. As smtpd might be called
-+ * more than once, we only want to do the initialization one time.
-+ *
-+ * The skeleton of this function is taken from OpenSSL apps/s_server.c.
-+ */
-+
-+int pfixtls_init_serverengine(int verifydepth, int askcert)
-+{
-+ int off = 0;
-+ int verify_flags = SSL_VERIFY_NONE;
-+ int rand_bytes;
-+ int rand_source_dev_fd;
-+ int rand_source_socket_fd;
-+ unsigned char buffer[255];
-+ char *CApath;
-+ char *CAfile;
-+ char *s_cert_file;
-+ char *s_key_file;
-+ char *s_dcert_file;
-+ char *s_dkey_file;
-+ FILE *paramfile;
-+
-+ if (pfixtls_serverengine)
-+ return (0); /* already running */
-+
-+ if (var_smtpd_tls_loglevel >= 2)
-+ msg_info("starting 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();
-+
-+ /*
-+ * Side effect, call a non-existing function to disable TLS usage with an
-+ * outdated OpenSSL version. There is a security reason (verify_result
-+ * is not stored with the session data).
-+ */
-+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
-+ needs_openssl_095_or_later();
-+#endif
-+
-+ /*
-+ * Initialize the PRNG Pseudo Random Number Generator with some seed.
-+ */
-+ randseed.pid = getpid();
-+ GETTIMEOFDAY(&randseed.tv);
-+ RAND_seed(&randseed, sizeof(randseed_t));
-+
-+ /*
-+ * Access the external sources for random seed. We will only query them
-+ * once, this should be sufficient and we will stir our entropy by using
-+ * the prng-exchange file anyway.
-+ * For reliability, we don't consider failure to access the additional
-+ * source fatal, as we can run happily without it (considering that we
-+ * still have the exchange-file). We also don't care how much entropy
-+ * we get back, as we must run anyway. We simply stir in the buffer
-+ * regardless how many bytes are actually in it.
-+ */
-+ if (*var_tls_daemon_rand_source) {
-+ if (!strncmp(var_tls_daemon_rand_source, "dev:", 4)) {
-+ /*
-+ * Source is a random device
-+ */
-+ rand_source_dev_fd = open(var_tls_daemon_rand_source + 4, 0, 0);
-+ if (rand_source_dev_fd == -1)
-+ msg_info("Could not open entropy device %s",
-+ var_tls_daemon_rand_source);
-+ else {
-+ if (var_tls_daemon_rand_bytes > 255)
-+ var_tls_daemon_rand_bytes = 255;
-+ read(rand_source_dev_fd, buffer, var_tls_daemon_rand_bytes);
-+ RAND_seed(buffer, var_tls_daemon_rand_bytes);
-+ close(rand_source_dev_fd);
-+ }
-+ } else if (!strncmp(var_tls_daemon_rand_source, "egd:", 4)) {
-+ /*
-+ * Source is a EGD compatible socket
-+ */
-+ rand_source_socket_fd = unix_connect(var_tls_daemon_rand_source +4,
-+ BLOCKING, 10);
-+ if (rand_source_socket_fd == -1)
-+ msg_info("Could not connect to %s", var_tls_daemon_rand_source);
-+ else {
-+ if (var_tls_daemon_rand_bytes > 255)
-+ var_tls_daemon_rand_bytes = 255;
-+ buffer[0] = 1;
-+ buffer[1] = var_tls_daemon_rand_bytes;
-+ if (write(rand_source_socket_fd, buffer, 2) != 2)
-+ msg_info("Could not talk to %s",
-+ var_tls_daemon_rand_source);
-+ else if (read(rand_source_socket_fd, buffer, 1) != 1)
-+ msg_info("Could not read info from %s",
-+ var_tls_daemon_rand_source);
-+ else {
-+ rand_bytes = buffer[0];
-+ read(rand_source_socket_fd, buffer, rand_bytes);
-+ RAND_seed(buffer, rand_bytes);
-+ }
-+ close(rand_source_socket_fd);
-+ }
-+ } else {
-+ RAND_load_file(var_tls_daemon_rand_source,
-+ var_tls_daemon_rand_bytes);
-+ }
-+ }
-+
-+ if (*var_tls_rand_exch_name) {
-+ rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
-+ if (rand_exch_fd != -1)
-+ pfixtls_exchange_seed();
-+ }
-+
-+ randseed.pid = getpid();
-+ GETTIMEOFDAY(&randseed.tv);
-+ RAND_seed(&randseed, sizeof(randseed_t));
-+
-+ /*
-+ * The SSL/TLS speficications 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.
-+ */
-+ ctx = SSL_CTX_new(SSLv23_server_method());
-+ if (ctx == NULL) {
-+ pfixtls_print_errors();
-+ return (-1);
-+ };
-+
-+ /*
-+ * 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(ctx, off);
-+
-+ /*
-+ * Set the info_callback, that will print out messages during
-+ * communication on demand.
-+ */
-+ if (var_smtpd_tls_loglevel >= 2)
-+ SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
-+
-+ /*
-+ * Set the list of ciphers, if explicitely given; otherwise the
-+ * (reasonable) default list is kept.
-+ */
-+ if (strlen(var_smtpd_tls_cipherlist) != 0)
-+ if (SSL_CTX_set_cipher_list(ctx, var_smtpd_tls_cipherlist) == 0) {
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+
-+ /*
-+ * Now we must add the necessary certificate stuff: A server key, a
-+ * server certificate, and the CA certificates for both the server
-+ * cert and 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
-+ * seperate files for each CA pointed on by softlinks named by 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. On the other
-+ * hand, the file is not really readable.
-+ */
-+ if (strlen(var_smtpd_tls_CAfile) == 0)
-+ CAfile = NULL;
-+ else
-+ CAfile = var_smtpd_tls_CAfile;
-+ if (strlen(var_smtpd_tls_CApath) == 0)
-+ CApath = NULL;
-+ else
-+ CApath = var_smtpd_tls_CApath;
-+
-+ if (CAfile || CApath) {
-+ if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
-+ msg_info("TLS engine: cannot load CA data");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ if (!SSL_CTX_set_default_verify_paths(ctx)) {
-+ msg_info("TLS engine: cannot set verify paths");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ }
-+
-+ /*
-+ * Now we load the certificate and key from the files and check,
-+ * whether the cert matches the key (internally done by set_cert_stuff().
-+ * 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 (strlen(var_smtpd_tls_cert_file) == 0)
-+ s_cert_file = NULL;
-+ else
-+ s_cert_file = var_smtpd_tls_cert_file;
-+ if (strlen(var_smtpd_tls_key_file) == 0)
-+ s_key_file = NULL;
-+ else
-+ s_key_file = var_smtpd_tls_key_file;
-+
-+ if (strlen(var_smtpd_tls_dcert_file) == 0)
-+ s_dcert_file = NULL;
-+ else
-+ s_dcert_file = var_smtpd_tls_dcert_file;
-+ if (strlen(var_smtpd_tls_dkey_file) == 0)
-+ s_dkey_file = NULL;
-+ else
-+ s_dkey_file = var_smtpd_tls_dkey_file;
-+
-+ if (s_cert_file) {
-+ if (!set_cert_stuff(ctx, s_cert_file, s_key_file)) {
-+ msg_info("TLS engine: cannot load RSA cert/key data");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ }
-+ if (s_dcert_file) {
-+ if (!set_cert_stuff(ctx, s_dcert_file, s_dkey_file)) {
-+ msg_info("TLS engine: cannot load DSA cert/key data");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ }
-+ if (!s_cert_file && !s_dcert_file) {
-+ msg_info("TLS engine: do need at least RSA _or_ DSA cert/key data");
-+ return (-1);
-+ }
-+
-+ /*
-+ * Sometimes a temporary RSA key might be needed by the OpenSSL
-+ * library. The OpenSSL doc indicates, that this might happen when
-+ * export ciphers are in use. We have to provide one, so well, we
-+ * just do it.
-+ */
-+ SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
-+
-+ /*
-+ * We might also need dh parameters, which can either be loaded from
-+ * file (preferred) or we simply take the 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(ctx, tmp_dh_cb);
-+ if (strlen(var_smtpd_tls_dh1024_param_file) != 0) {
-+ if ((paramfile = fopen(var_smtpd_tls_dh1024_param_file, "r")) != NULL) {
-+ dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
-+ if (dh_1024 == NULL) {
-+ msg_info("TLS engine: cannot load 1024bit DH parameters");
-+ pfixtls_print_errors();
-+ }
-+ }
-+ else {
-+ msg_info("TLS engine: cannot load 1024bit DH parameters: %s: %s",
-+ var_smtpd_tls_dh1024_param_file, strerror(errno));
-+ }
-+ }
-+ if (strlen(var_smtpd_tls_dh512_param_file) != 0) {
-+ if ((paramfile = fopen(var_smtpd_tls_dh512_param_file, "r")) != NULL) {
-+ dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
-+ if (dh_512 == NULL) {
-+ msg_info("TLS engine: cannot load 512bit DH parameters");
-+ pfixtls_print_errors();
-+ }
-+ }
-+ else {
-+ msg_info("TLS engine: cannot load 512bit DH parameters: %s: %s",
-+ var_smtpd_tls_dh512_param_file, strerror(errno));
-+ }
-+ }
-+
-+ /*
-+ * 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(ctx, verify_flags, verify_callback);
-+ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
-+
-+ /*
-+ * Initialize the session cache. We only want external caching to
-+ * synchronize between server sessions, so we set it to a minimum value
-+ * of 1. If the external cache is disabled, we won't cache at all.
-+ * The recall of old sessions "get" and save to disk of just created
-+ * sessions "new" is handled by the appropriate callback functions.
-+ *
-+ * We must not forget to set a session id context to identify to which
-+ * kind of server process the session was related. In our case, the
-+ * context is just the name of the patchkit: "Postfix/TLS".
-+ */
-+ SSL_CTX_sess_set_cache_size(ctx, 1);
-+ SSL_CTX_set_timeout(ctx, var_smtpd_tls_scache_timeout);
-+ SSL_CTX_set_session_id_context(ctx, (void*)&server_session_id_context,
-+ sizeof(server_session_id_context));
-+
-+ /*
-+ * The session cache is realized by an external database file, that
-+ * must be opened before going to chroot jail. Since the session cache
-+ * data can become quite large, "[n]dbm" cannot be used as it has a
-+ * size limit that is by far to small.
-+ */
-+ if (*var_smtpd_tls_scache_db) {
-+ /*
-+ * Insert a test against other dbms here, otherwise while writing
-+ * a session (content to large), we will receive a fatal error!
-+ */
-+ if (strncmp(var_smtpd_tls_scache_db, "sdbm:", 5))
-+ msg_warn("Only sdbm: type allowed for %s",
-+ var_smtpd_tls_scache_db);
-+ else
-+ scache_db = dict_open(var_smtpd_tls_scache_db, O_RDWR,
-+ DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
-+ if (scache_db) {
-+ SSL_CTX_set_session_cache_mode(ctx,
-+ SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_AUTO_CLEAR);
-+ SSL_CTX_sess_set_get_cb(ctx, get_session_cb);
-+ SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
-+ SSL_CTX_sess_set_remove_cb(ctx, remove_session_cb);
-+ }
-+ else
-+ msg_warn("Could not open session cache %s",
-+ var_smtpd_tls_scache_db);
-+ }
-+
-+ /*
-+ * Finally create the global index to access TLScontext information
-+ * inside verify_callback.
-+ */
-+ TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
-+ NULL, NULL, NULL);
-+
-+ pfixtls_serverengine = 1;
-+ return (0);
-+}
-+
-+ /*
-+ * This is the actual startup routine for the connection. We expect
-+ * that the buffers are flushed and the "220 Ready to start TLS" was
-+ * send to the client, so that we can immediately can start the TLS
-+ * handshake process.
-+ */
-+int pfixtls_start_servertls(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 (!pfixtls_serverengine) { /* should never happen */
-+ msg_info("tls_engine not running");
-+ return (-1);
-+ }
-+ 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 verify_callback().
-+ */
-+ TLScontext = (TLScontext_t *)mymalloc(sizeof(TLScontext_t));
-+ if (!TLScontext) {
-+ msg_fatal("Could not allocate 'TLScontext' with mymalloc");
-+ }
-+ if ((TLScontext->con = (SSL *) SSL_new(ctx)) == NULL) {
-+ msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
-+ pfixtls_print_errors();
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+ if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
-+ msg_info("Could not set application data for 'TLScontext->con'");
-+ pfixtls_print_errors();
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ /*
-+ * Set the verification parameters to be checked in verify_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, 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.
-+ */
-+ if (!BIO_new_bio_pair(&TLScontext->internal_bio, BIO_bufsiz,
-+ &TLScontext->network_bio, BIO_bufsiz)) {
-+ msg_info("Could not obtain BIO_pair");
-+ pfixtls_print_errors();
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ /*
-+ * Before really starting anything, try to seed the PRNG a little bit
-+ * more.
-+ */
-+ pfixtls_stir_seed();
-+ pfixtls_exchange_seed();
-+
-+ /*
-+ * 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), bio_dump_cb);
-+
-+
-+ /* Dump the negotiation for loglevels 3 and 4 */
-+ if (var_smtpd_tls_loglevel >= 3)
-+ do_dump = 1;
-+
-+ /*
-+ * Now we expect the negotiation to begin. This whole process is like a
-+ * black box for us. We totally have to rely on the routines build into
-+ * the OpenSSL library. The only thing we can do we already have done
-+ * by choosing our own callbacks for session caching and certificate
-+ * verification.
-+ *
-+ * Error handling:
-+ * If the SSL handhake fails, we print out an error message and remove
-+ * everything that might be there. A session has to be removed anyway,
-+ * because RFC2246 requires it.
-+ */
-+ sts = do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
-+ SSL_accept, NULL, NULL, NULL, 0);
-+ if (sts <= 0) {
-+ msg_info("SSL_accept error from %s[%s]: %d", peername, peeraddr, sts);
-+ pfixtls_print_errors();
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ /* Only loglevel==4 dumps everything */
-+ if (var_smtpd_tls_loglevel < 4)
-+ do_dump = 0;
-+
-+ /*
-+ * Lets 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, CCERT_BUFSIZ);
-+ 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, CCERT_BUFSIZ);
-+ 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, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse client's subject CN");
-+ pfixtls_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, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse client's issuer CN");
-+ pfixtls_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, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse client's issuer Organization");
-+ pfixtls_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);
-+ }
-+
-+ /*
-+ * At this point we should have a certificate when required.
-+ * We may however have a cached session, so the callback would never
-+ * be called. We therefore double-check to make sure and remove the
-+ * session, if applicable.
-+ */
-+ 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(ctx, session);
-+ return (-1);
-+ }
-+ }
-+
-+ /*
-+ * 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));
-+
-+ pfixtls_serveractive = 1;
-+
-+ /*
-+ * The TLS engine is active, switch to the pfixtls_timed_read/write()
-+ * functions and store the context.
-+ */
-+ vstream_control(stream,
-+ VSTREAM_CTL_READ_FN, pfixtls_timed_read,
-+ VSTREAM_CTL_WRITE_FN, pfixtls_timed_write,
-+ VSTREAM_CTL_CONTEXT, (void *)TLScontext,
-+ VSTREAM_CTL_END);
-+
-+ 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);
-+ pfixtls_stir_seed();
-+
-+ return (0);
-+}
-+
-+ /*
-+ * Shut down the TLS connection, that does mean: remove all the information
-+ * and reset the flags! This is needed if the actual running smtpd is to
-+ * be restarted. We do not give back any value, as there is nothing to
-+ * be reported.
-+ * Since our session cache is external, we will remove the session from
-+ * memory in any case. The SSL_CTX_flush_sessions might be redundant here,
-+ * I however want to make sure nothing is left.
-+ * RFC2246 requires us to remove sessions if something went wrong, as
-+ * indicated by the "failure" value, so we remove it from the external
-+ * cache, too.
-+ */
-+int pfixtls_stop_servertls(VSTREAM *stream, int timeout, int failure,
-+ tls_info_t *tls_info)
-+{
-+ TLScontext_t *TLScontext;
-+ int retval;
-+
-+ if (pfixtls_serveractive) {
-+ TLScontext = (TLScontext_t *)vstream_context(stream);
-+ /*
-+ * Perform SSL_shutdown() twice, as the first attempt may return
-+ * to early: it will only 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 = do_tls_operation(vstream_fileno(stream), timeout,
-+ TLScontext, SSL_shutdown, NULL, NULL, NULL, 0);
-+ if (retval == 0)
-+ do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
-+ SSL_shutdown, NULL, NULL, NULL, 0);
-+ }
-+ /*
-+ * 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.
-+ */
-+ SSL_free(TLScontext->con);
-+ BIO_free(TLScontext->network_bio);
-+ myfree((char *)TLScontext);
-+ vstream_control(stream,
-+ VSTREAM_CTL_READ_FN, (VSTREAM_FN) NULL,
-+ VSTREAM_CTL_WRITE_FN, (VSTREAM_FN) NULL,
-+ VSTREAM_CTL_CONTEXT, (void *) NULL,
-+ VSTREAM_CTL_END);
-+ SSL_CTX_flush_sessions(ctx, time(NULL));
-+
-+ pfixtls_stir_seed();
-+ pfixtls_exchange_seed();
-+
-+ *tls_info = tls_info_zero;
-+ pfixtls_serveractive = 0;
-+
-+ }
-+
-+ return (0);
-+}
-+
-+
-+ /*
-+ * This is the setup routine for the SSL client. As smtpd might be called
-+ * more than once, we only want to do the initialization one time.
-+ *
-+ * The skeleton of this function is taken from OpenSSL apps/s_client.c.
-+ */
-+
-+int pfixtls_init_clientengine(int verifydepth)
-+{
-+ int off = 0;
-+ int verify_flags = SSL_VERIFY_NONE;
-+ int rand_bytes;
-+ int rand_source_dev_fd;
-+ int rand_source_socket_fd;
-+ unsigned char buffer[255];
-+ char *CApath;
-+ char *CAfile;
-+ char *c_cert_file;
-+ char *c_key_file;
-+
-+
-+ if (pfixtls_clientengine)
-+ return (0); /* already running */
-+
-+ if (var_smtp_tls_loglevel >= 2)
-+ msg_info("starting 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();
-+
-+ /*
-+ * Side effect, call a non-existing function to disable TLS usage with an
-+ * outdated OpenSSL version. There is a security reason (verify_result
-+ * is not stored with the session data).
-+ */
-+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
-+ needs_openssl_095_or_later();
-+#endif
-+
-+ /*
-+ * Initialize the PRNG Pseudo Random Number Generator with some seed.
-+ */
-+ randseed.pid = getpid();
-+ GETTIMEOFDAY(&randseed.tv);
-+ RAND_seed(&randseed, sizeof(randseed_t));
-+
-+ /*
-+ * Access the external sources for random seed. We will only query them
-+ * once, this should be sufficient and we will stir our entropy by using
-+ * the prng-exchange file anyway.
-+ * For reliability, we don't consider failure to access the additional
-+ * source fatal, as we can run happily without it (considering that we
-+ * still have the exchange-file). We also don't care how much entropy
-+ * we get back, as we must run anyway. We simply stir in the buffer
-+ * regardless how many bytes are actually in it.
-+ */
-+ if (*var_tls_daemon_rand_source) {
-+ if (!strncmp(var_tls_daemon_rand_source, "dev:", 4)) {
-+ /*
-+ * Source is a random device
-+ */
-+ rand_source_dev_fd = open(var_tls_daemon_rand_source + 4, 0, 0);
-+ if (rand_source_dev_fd == -1)
-+ msg_info("Could not open entropy device %s",
-+ var_tls_daemon_rand_source);
-+ else {
-+ if (var_tls_daemon_rand_bytes > 255)
-+ var_tls_daemon_rand_bytes = 255;
-+ read(rand_source_dev_fd, buffer, var_tls_daemon_rand_bytes);
-+ RAND_seed(buffer, var_tls_daemon_rand_bytes);
-+ close(rand_source_dev_fd);
-+ }
-+ } else if (!strncmp(var_tls_daemon_rand_source, "egd:", 4)) {
-+ /*
-+ * Source is a EGD compatible socket
-+ */
-+ rand_source_socket_fd = unix_connect(var_tls_daemon_rand_source +4,
-+ BLOCKING, 10);
-+ if (rand_source_socket_fd == -1)
-+ msg_info("Could not connect to %s", var_tls_daemon_rand_source);
-+ else {
-+ if (var_tls_daemon_rand_bytes > 255)
-+ var_tls_daemon_rand_bytes = 255;
-+ buffer[0] = 1;
-+ buffer[1] = var_tls_daemon_rand_bytes;
-+ if (write(rand_source_socket_fd, buffer, 2) != 2)
-+ msg_info("Could not talk to %s",
-+ var_tls_daemon_rand_source);
-+ else if (read(rand_source_socket_fd, buffer, 1) != 1)
-+ msg_info("Could not read info from %s",
-+ var_tls_daemon_rand_source);
-+ else {
-+ rand_bytes = buffer[0];
-+ read(rand_source_socket_fd, buffer, rand_bytes);
-+ RAND_seed(buffer, rand_bytes);
-+ }
-+ close(rand_source_socket_fd);
-+ }
-+ } else {
-+ RAND_load_file(var_tls_daemon_rand_source,
-+ var_tls_daemon_rand_bytes);
-+ }
-+ }
-+
-+ if (*var_tls_rand_exch_name) {
-+ rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
-+ if (rand_exch_fd != -1)
-+ pfixtls_exchange_seed();
-+ }
-+
-+ randseed.pid = getpid();
-+ GETTIMEOFDAY(&randseed.tv);
-+ RAND_seed(&randseed, sizeof(randseed_t));
-+
-+ /*
-+ * The SSL/TLS speficications 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.
-+ */
-+ ctx = SSL_CTX_new(SSLv23_client_method());
-+ if (ctx == NULL) {
-+ pfixtls_print_errors();
-+ return (-1);
-+ };
-+
-+ /*
-+ * 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(ctx, off);
-+
-+ /*
-+ * Set the info_callback, that will print out messages during
-+ * communication on demand.
-+ */
-+ if (var_smtp_tls_loglevel >= 2)
-+ SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
-+
-+ /*
-+ * Set the list of ciphers, if explicitely given; otherwise the
-+ * (reasonable) default list is kept.
-+ */
-+ if (strlen(var_smtp_tls_cipherlist) != 0)
-+ if (SSL_CTX_set_cipher_list(ctx, var_smtp_tls_cipherlist) == 0) {
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+
-+ /*
-+ * Now we must add the necessary certificate stuff: A client key, a
-+ * client certificate, and the CA certificates for both the client
-+ * cert and the verification of server certificates.
-+ * In fact, 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 callback hoods to
-+ * easily realize it.
-+ *
-+ * 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
-+ * seperate files for each CA pointed on by softlinks named by 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. On the other
-+ * hand, the file is not really readable.
-+ */
-+ if (strlen(var_smtp_tls_CAfile) == 0)
-+ CAfile = NULL;
-+ else
-+ CAfile = var_smtp_tls_CAfile;
-+ if (strlen(var_smtp_tls_CApath) == 0)
-+ CApath = NULL;
-+ else
-+ CApath = var_smtp_tls_CApath;
-+ if (CAfile || CApath) {
-+ if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
-+ msg_info("TLS engine: cannot load CA data");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ if (!SSL_CTX_set_default_verify_paths(ctx)) {
-+ msg_info("TLS engine: cannot set verify paths");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+ }
-+
-+ if (strlen(var_smtp_tls_cert_file) == 0)
-+ c_cert_file = NULL;
-+ else
-+ c_cert_file = var_smtp_tls_cert_file;
-+ if (strlen(var_smtp_tls_key_file) == 0)
-+ c_key_file = NULL;
-+ else
-+ c_key_file = var_smtp_tls_key_file;
-+ if (c_cert_file || c_key_file)
-+ if (!set_cert_stuff(ctx, c_cert_file, c_key_file)) {
-+ msg_info("TLS engine: cannot load cert/key data");
-+ pfixtls_print_errors();
-+ return (-1);
-+ }
-+
-+ /*
-+ * Sometimes a temporary RSA key might be needed by the OpenSSL
-+ * library. The OpenSSL doc indicates, that this might happen when
-+ * export ciphers are in use. We have to provide one, so well, we
-+ * just do it.
-+ */
-+ SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
-+
-+ /*
-+ * Finally, the setup for the server certificate checking, done
-+ * "by the book".
-+ */
-+ SSL_CTX_set_verify(ctx, verify_flags, verify_callback);
-+
-+ /*
-+ * Initialize the session cache. We only want external caching to
-+ * synchronize between server sessions, so we set it to a minimum value
-+ * of 1. If the external cache is disabled, we won't cache at all.
-+ *
-+ * In case of the client, there is no callback used in OpenSSL, so
-+ * we must call the session cache functions manually during the process.
-+ */
-+ SSL_CTX_sess_set_cache_size(ctx, 1);
-+ SSL_CTX_set_timeout(ctx, var_smtp_tls_scache_timeout);
-+
-+ /*
-+ * The session cache is realized by an external database file, that
-+ * must be opened before going to chroot jail. Since the session cache
-+ * data can become quite large, "[n]dbm" cannot be used as it has a
-+ * size limit that is by far to small.
-+ */
-+ if (*var_smtp_tls_scache_db) {
-+ /*
-+ * Insert a test against other dbms here, otherwise while writing
-+ * a session (content to large), we will receive a fatal error!
-+ */
-+ if (strncmp(var_smtp_tls_scache_db, "sdbm:", 5))
-+ msg_warn("Only sdbm: type allowed for %s",
-+ var_smtp_tls_scache_db);
-+ else
-+ scache_db = dict_open(var_smtp_tls_scache_db, O_RDWR,
-+ DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
-+ if (!scache_db)
-+ msg_warn("Could not open session cache %s",
-+ var_smtp_tls_scache_db);
-+ /*
-+ * It is practical to have OpenSSL automatically save newly created
-+ * sessions for us by callback. Therefore we have to enable the
-+ * internal session cache for the client side. Disable automatic
-+ * clearing, as smtp has limited lifetime anyway and we can call
-+ * the cleanup routine at will.
-+ */
-+ SSL_CTX_set_session_cache_mode(ctx,
-+ SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_NO_AUTO_CLEAR);
-+ SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
-+ }
-+
-+ /*
-+ * Finally create the global index to access TLScontext information
-+ * inside verify_callback.
-+ */
-+ TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
-+ NULL, NULL, NULL);
-+ TLSpeername_index = SSL_SESSION_get_ex_new_index(0,
-+ "TLSpeername ex_data index",
-+ new_peername_func,
-+ dup_peername_func,
-+ free_peername_func);
-+
-+ pfixtls_clientengine = 1;
-+ return (0);
-+}
-+
-+ /*
-+ * 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 can start the TLS
-+ * handshake process.
-+ */
-+int pfixtls_start_clienttls(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 (!pfixtls_clientengine) { /* should never happen */
-+ msg_info("tls_engine not running");
-+ return (-1);
-+ }
-+ if (var_smtpd_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 verify_callback().
-+ */
-+ TLScontext = (TLScontext_t *)mymalloc(sizeof(TLScontext_t));
-+ if (!TLScontext) {
-+ msg_fatal("Could not allocate 'TLScontext' with mymalloc");
-+ }
-+ if ((TLScontext->con = (SSL *) SSL_new(ctx)) == NULL) {
-+ msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
-+ pfixtls_print_errors();
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+ if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
-+ msg_info("Could not set application data for 'TLScontext->con'");
-+ pfixtls_print_errors();
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ /*
-+ * Set the verification parameters to be checked in verify_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, 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.
-+ */
-+ if (!BIO_new_bio_pair(&TLScontext->internal_bio, BIO_bufsiz,
-+ &TLScontext->network_bio, BIO_bufsiz)) {
-+ msg_info("Could not obtain BIO_pair");
-+ pfixtls_print_errors();
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ old_session = NULL;
-+
-+ /*
-+ * Find out the hashed HostID for the client cache and try to
-+ * load the session from the cache.
-+ */
-+ strncpy(TLScontext->peername_save, peername, ID_MAXLENGTH + 1);
-+ TLScontext->peername_save[ID_MAXLENGTH] = '\0'; /* just in case */
-+ (void)lowercase(TLScontext->peername_save);
-+ if (scache_db) {
-+ old_session = load_clnt_session(peername, enforce_peername);
-+ if (old_session) {
-+ SSL_set_session(TLScontext->con, old_session);
-+#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.
-+ */
-+ pfixtls_stir_seed();
-+ pfixtls_exchange_seed();
-+
-+ /*
-+ * 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), bio_dump_cb);
-+
-+
-+ /* Dump the negotiation for loglevels 3 and 4 */
-+ if (var_smtp_tls_loglevel >= 3)
-+ do_dump = 1;
-+
-+ /*
-+ * Now we expect the negotiation to begin. This whole process is like a
-+ * black box for us. We totally have to rely on the routines build into
-+ * the OpenSSL library. The only thing we can do we already have done
-+ * by choosing our own callback certificate verification.
-+ *
-+ * Error handling:
-+ * If the SSL handhake fails, we print out an error message and remove
-+ * everything that might be there. A session has to be removed anyway,
-+ * because RFC2246 requires it.
-+ */
-+ sts = do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
-+ SSL_connect, NULL, NULL, NULL, 0);
-+ if (sts <= 0) {
-+ msg_info("SSL_connect error to %s: %d", peername, sts);
-+ pfixtls_print_errors();
-+ session = SSL_get_session(TLScontext->con);
-+ if (session) {
-+ SSL_CTX_remove_session(ctx, session);
-+ if (var_smtp_tls_loglevel >= 2)
-+ msg_info("SSL session removed");
-+ }
-+ if ((old_session) && (!SSL_session_reused(TLScontext->con)))
-+ SSL_SESSION_free(old_session); /* Must also be removed */
-+ SSL_free(TLScontext->con);
-+ myfree((char *)TLScontext);
-+ return (-1);
-+ }
-+
-+ if (!SSL_session_reused(TLScontext->con)) {
-+ SSL_SESSION_free(old_session); /* Remove unused session */
-+ }
-+ else if (var_smtp_tls_loglevel >= 3)
-+ msg_info("Reusing old session");
-+
-+ /* Only loglevel==4 dumps everything */
-+ if (var_smtp_tls_loglevel < 4)
-+ do_dump = 0;
-+
-+ /*
-+ * Lets 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;
-+
-+ TLScontext->peer_CN[0] = '\0';
-+ if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
-+ NID_commonName, TLScontext->peer_CN, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse server's subject CN");
-+ pfixtls_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, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse server's issuer CN");
-+ pfixtls_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, CCERT_BUFSIZ)) {
-+ msg_info("Could not parse server's issuer Organization");
-+ pfixtls_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));
-+
-+ pfixtls_clientactive = 1;
-+
-+ /*
-+ * The TLS engine is active, switch to the pfixtls_timed_read/write()
-+ * functions.
-+ */
-+ vstream_control(stream,
-+ VSTREAM_CTL_READ_FN, pfixtls_timed_read,
-+ VSTREAM_CTL_WRITE_FN, pfixtls_timed_write,
-+ VSTREAM_CTL_CONTEXT, (void *)TLScontext,
-+ VSTREAM_CTL_END);
-+
-+ 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);
-+
-+ pfixtls_stir_seed();
-+
-+ return (0);
-+}
-+
-+ /*
-+ * Shut down the TLS connection, that does mean: remove all the information
-+ * and reset the flags! This is needed if the actual running smtp is to
-+ * be restarted. We do not give back any value, as there is nothing to
-+ * be reported.
-+ * Since our session cache is external, we will remove the session from
-+ * memory in any case. The SSL_CTX_flush_sessions might be redundant here,
-+ * I however want to make sure nothing is left.
-+ * RFC2246 requires us to remove sessions if something went wrong, as
-+ * indicated by the "failure" value,so we remove it from the external
-+ * cache, too.
-+ */
-+int pfixtls_stop_clienttls(VSTREAM *stream, int timeout, int failure,
-+ tls_info_t *tls_info)
-+{
-+ TLScontext_t *TLScontext;
-+ int retval;
-+
-+ if (pfixtls_clientactive) {
-+ TLScontext = (TLScontext_t *)vstream_context(stream);
-+ /*
-+ * Perform SSL_shutdown() twice, as the first attempt may return
-+ * to early: it will only 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 = do_tls_operation(vstream_fileno(stream), timeout,
-+ TLScontext, SSL_shutdown, NULL, NULL, NULL, 0);
-+ if (retval == 0)
-+ do_tls_operation(vstream_fileno(stream), timeout, TLScontext,
-+ SSL_shutdown, NULL, NULL, NULL, 0);
-+ }
-+ /*
-+ * 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.
-+ */
-+ SSL_free(TLScontext->con);
-+ BIO_free(TLScontext->network_bio);
-+ myfree((char *)TLScontext);
-+ vstream_control(stream,
-+ VSTREAM_CTL_READ_FN, (VSTREAM_FN) NULL,
-+ VSTREAM_CTL_WRITE_FN, (VSTREAM_FN) NULL,
-+ VSTREAM_CTL_CONTEXT, (void *) NULL,
-+ VSTREAM_CTL_END);
-+ SSL_CTX_flush_sessions(ctx, time(NULL));
-+
-+ pfixtls_stir_seed();
-+ pfixtls_exchange_seed();
-+
-+ *tls_info = tls_info_zero;
-+ pfixtls_clientactive = 0;
-+
-+ }
-+
-+ return (0);
-+}
-+
-+
-+#endif /* HAS_SSL */
-diff -Pur postfix-1.1.11-20020613-orig/src/global/pfixtls.h postfix-1.1.11-20020613/src/global/pfixtls.h
---- postfix-1.1.11-20020613-orig/src/global/pfixtls.h Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/global/pfixtls.h Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,76 @@
-+/*++
-+/* NAME
-+/* pfixtls 3h
-+/* SUMMARY
-+/* TLS routines
-+/* SYNOPSIS
-+/* include "pfixtls.h"
-+/* DESCRIPTION
-+/* .nf
-+/*--*/
-+
-+#ifndef PFIXTLS_H_INCLUDED
-+#define PFIXTLS_H_INCLUDED
-+
-+typedef struct {
-+ int peer_verified;
-+ 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;
-+
-+#ifdef HAS_SSL
-+
-+typedef struct {
-+ long scache_db_version;
-+ long openssl_version;
-+ time_t timestamp; /* We could add other info here... */
-+ int enforce_peername;
-+} pfixtls_scache_info_t;
-+
-+extern const long scache_db_version;
-+extern const long openssl_version;
-+
-+int pfixtls_timed_read(int fd, void *buf, unsigned len, int timout,
-+ void *unused_timeout);
-+int pfixtls_timed_write(int fd, void *buf, unsigned len, int timeout,
-+ void *unused_timeout);
-+
-+extern int pfixtls_serverengine;
-+int pfixtls_init_serverengine(int verifydepth, int askcert);
-+int pfixtls_start_servertls(VSTREAM *stream, int timeout,
-+ const char *peername, const char *peeraddr,
-+ tls_info_t *tls_info, int require_cert);
-+int pfixtls_stop_servertls(VSTREAM *stream, int timeout, int failure,
-+ tls_info_t *tls_info);
-+
-+extern int pfixtls_clientengine;
-+int pfixtls_init_clientengine(int verifydepth);
-+int pfixtls_start_clienttls(VSTREAM *stream, int timeout,
-+ int enforce_peername,
-+ const char *peername,
-+ tls_info_t *tls_info);
-+int pfixtls_stop_clienttls(VSTREAM *stream, int timeout, int failure,
-+ tls_info_t *tls_info);
-+
-+#endif /* PFIXTLS_H_INCLUDED */
-+#endif
-+
-+/* LICENSE
-+/* .ad
-+/* .fi
-+/* AUTHOR(S)
-+/* Lutz Jaenicke
-+/* BTU Cottbus
-+/* Allgemeine Elektrotechnik
-+/* Universitaetsplatz 3-4
-+/* D-03044 Cottbus, Germany
-+/*--*/
-diff -Pur postfix-1.1.11-20020613-orig/src/global/resolve_local.c postfix-1.1.11-20020613/src/global/resolve_local.c
---- postfix-1.1.11-20020613-orig/src/global/resolve_local.c Thu Jan 31 20:56:29 2002
-+++ postfix-1.1.11-20020613/src/global/resolve_local.c Wed Jun 26 15:26:48 2002
-@@ -42,6 +42,7 @@
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
-+#include <netdb.h>
-
- #ifndef INADDR_NONE
- #define INADDR_NONE 0xffffffff
-@@ -79,7 +80,12 @@
- {
- char *saved_addr = mystrdup(addr);
- char *dest;
-+#ifdef INET6
-+ struct addrinfo hints, *res, *res0;
-+ int error;
-+#else
- struct in_addr ipaddr;
-+#endif
- int len;
-
- #define RETURN(x) { myfree(saved_addr); return(x); }
-@@ -111,9 +117,25 @@
- if (*dest == '[' && dest[len - 1] == ']') {
- dest++;
- dest[len -= 2] = 0;
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ error = getaddrinfo(dest, NULL, &hints, &res0);
-+ if (!error) {
-+ for (res = res0; res; res = res->ai_next) {
-+ if (own_inet_addr(res->ai_addr)) {
-+ freeaddrinfo(res0);
-+ RETURN(1);
-+ }
-+ }
-+ freeaddrinfo(res0);
-+ }
-+#else
- if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
- && own_inet_addr(&ipaddr))
- RETURN(1);
-+#endif
- }
-
- /*
-diff -Pur postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.c postfix-1.1.11-20020613/src/global/wildcard_inet_addr.c
---- postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/global/wildcard_inet_addr.c Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,82 @@
-+/* System library. */
-+
-+#include <sys_defs.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <string.h>
-+#ifdef INET6
-+#include <sys/socket.h>
-+#endif
-+#include <netdb.h>
-+
-+#ifdef STRCASECMP_IN_STRINGS_H
-+#include <strings.h>
-+#endif
-+
-+/* Utility library. */
-+
-+#include <msg.h>
-+#include <mymalloc.h>
-+#include <inet_addr_list.h>
-+#include <inet_addr_local.h>
-+#include <inet_addr_host.h>
-+#include <stringops.h>
-+
-+/* Global library. */
-+
-+#include <mail_params.h>
-+#include <wildcard_inet_addr.h>
-+
-+/* Application-specific. */
-+static INET_ADDR_LIST addr_list;
-+
-+/* wildcard_inet_addr_init - initialize my own address list */
-+
-+static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list)
-+{
-+#ifdef INET6
-+ struct addrinfo hints, *res, *res0;
-+ char hbuf[NI_MAXHOST];
-+ int error;
-+#ifdef NI_WITHSCOPEID
-+ const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
-+#else
-+ const int niflags = NI_NUMERICHOST;
-+#endif
-+
-+ inet_addr_list_init(addr_list);
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE;
-+ error = getaddrinfo(NULL, "0", &hints, &res0);
-+ if (error)
-+ msg_fatal("could not get list of wildcard addresses");
-+ for (res = res0; res; res = res->ai_next) {
-+ if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
-+ continue;
-+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, niflags) != 0)
-+ continue;
-+ if (inet_addr_host(addr_list, hbuf) == 0)
-+ continue; /* msg_fatal("config variable %s: host not found: %s",
-+ VAR_INET_INTERFACES, hbuf); */
-+ }
-+ freeaddrinfo(res0);
-+#else
-+ if (inet_addr_host(addr_list, "0.0.0.0") == 0)
-+ msg_fatal("config variable %s: host not found: %s",
-+ VAR_INET_INTERFACES, "0.0.0.0");
-+#endif
-+}
-+
-+/* wildcard_inet_addr_list - return list of addresses */
-+
-+INET_ADDR_LIST *wildcard_inet_addr_list(void)
-+{
-+ if (addr_list.used == 0)
-+ wildcard_inet_addr_init(&addr_list);
-+
-+ return (&addr_list);
-+}
-diff -Pur postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.h postfix-1.1.11-20020613/src/global/wildcard_inet_addr.h
---- postfix-1.1.11-20020613-orig/src/global/wildcard_inet_addr.h Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/global/wildcard_inet_addr.h Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,36 @@
-+#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_
-+#define _WILDCARD_INET_ADDR_H_INCLUDED_
-+
-+/*++
-+/* NAME
-+/* wildcard_inet_addr_list 3h
-+/* SUMMARY
-+/* grab the list of wildcard IP addresses.
-+/* SYNOPSIS
-+/* #include <own_inet_addr.h>
-+/* DESCRIPTION
-+/* .nf
-+/*--*/
-+
-+ /*
-+ * System library.
-+ */
-+#include <netinet/in.h>
-+#ifdef INET6
-+#include <sys/socket.h>
-+#endif
-+
-+ /*
-+ * External interface.
-+ */
-+extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void);
-+
-+/* LICENSE
-+/* .ad
-+/* .fi
-+/* foo
-+/* AUTHOR(S)
-+/* Jun-ichiro itojun Hagino
-+/*--*/
-+
-+#endif
-diff -Pur postfix-1.1.11-20020613-orig/src/lmtp/lmtp.c postfix-1.1.11-20020613/src/lmtp/lmtp.c
---- postfix-1.1.11-20020613-orig/src/lmtp/lmtp.c Sat May 11 02:07:05 2002
-+++ postfix-1.1.11-20020613/src/lmtp/lmtp.c Wed Jun 26 15:26:48 2002
-@@ -190,6 +190,12 @@
- /* .IP \fBlmtp_quit_timeout\fR
- /* Timeout for sending the \fBQUIT\fR command, and for
- /* receiving the server response.
-+/* .IP \fBlmtp_bind_address\fR
-+/* Numerical source network address (IPv4) to bind to when making
-+/* a connection.
-+/* .IP \fBlmtp_bind_address6\fR
-+/* Numerical source network address (IPv6) to bind to when making
-+/* a connection.
- /* SEE ALSO
- /* bounce(8) non-delivery status reports
- /* local(8) local mail delivery
-@@ -276,6 +282,8 @@
- char *var_lmtp_sasl_opts;
- char *var_lmtp_sasl_passwd;
- bool var_lmtp_sasl_enable;
-+char *var_lmtp_bind_addr;
-+char *var_lmtp_bind_addr6;
-
- /*
- * Global variables.
-@@ -514,6 +522,10 @@
- VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
- VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
- VAR_LMTP_SASL_OPTS, DEF_LMTP_SASL_OPTS, &var_lmtp_sasl_opts, 0, 0,
-+ VAR_LMTP_BIND_ADDR, DEF_LMTP_BIND_ADDR, &var_lmtp_bind_addr, 0, 0,
-+#ifdef INET6
-+ VAR_LMTP_BIND_ADDR6, DEF_LMTP_BIND_ADDR6, &var_lmtp_bind_addr6, 0, 0,
-+#endif
- 0,
- };
- static CONFIG_INT_TABLE int_table[] = {
-diff -Pur postfix-1.1.11-20020613-orig/src/lmtp/lmtp_connect.c postfix-1.1.11-20020613/src/lmtp/lmtp_connect.c
---- postfix-1.1.11-20020613-orig/src/lmtp/lmtp_connect.c Thu Mar 22 02:01:46 2001
-+++ postfix-1.1.11-20020613/src/lmtp/lmtp_connect.c Wed Jun 26 15:26:48 2002
-@@ -92,11 +92,13 @@
- #include <iostuff.h>
- #include <timed_connect.h>
- #include <stringops.h>
-+#include <inet_addr_list.h>
-
- /* Global library. */
-
- #include <mail_params.h>
- #include <mail_proto.h>
-+#include <own_inet_addr.h>
-
- /* DNS library. */
-
-@@ -166,13 +168,42 @@
- const char *destination, VSTRING *why)
- {
- char *myname = "lmtp_connect_addr";
-- struct sockaddr_in sin;
-- int sock;
-+#ifdef INET6
-+ struct sockaddr_storage ss;
-+#else
-+ struct sockaddr ss;
-+#endif
-+ struct sockaddr *sa;
-+ struct sockaddr_in *sin;
-+#ifdef INET6
-+ struct sockaddr_in6 *sin6;
-+#endif
-+ SOCKADDR_SIZE salen;
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+#else
-+ char hbuf[sizeof("255.255.255.255") + 1];
-+#endif
-+ int sock = -1;
-+ INET_ADDR_LIST *addr_list;
-+ char *bind_addr;
-+
-+ sa = (struct sockaddr *)&ss;
-+ sin = (struct sockaddr_in *)&ss;
-+#ifdef INET6
-+ sin6 = (struct sockaddr_in6 *)&ss;
-+#endif
-
- /*
- * Sanity checks.
- */
-- if (addr->data_len > sizeof(sin.sin_addr)) {
-+#ifdef INET6
-+ if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) ||
-+ ((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr))))
-+#else
-+ if (addr->data_len > sizeof(sin->sin_addr))
-+#endif
-+ {
- msg_warn("%s: skip address with length %d", myname, addr->data_len);
- lmtp_errno = LMTP_RETRY;
- return (0);
-@@ -181,25 +212,168 @@
- /*
- * Initialize.
- */
-- memset((char *) &sin, 0, sizeof(sin));
-- sin.sin_family = AF_INET;
-+ switch (addr->type) {
-+#ifdef INET6
-+ case T_AAAA:
-+ bind_addr = var_lmtp_bind_addr6;
-+ memset(sin6, 0, sizeof(*sin6));
-+ sin6->sin6_family = AF_INET6;
-+ salen = sizeof(*sin6);
-+ break;
-+#endif
-+ default: /* T_A: */
-+ bind_addr = var_lmtp_bind_addr;
-+ memset(sin, 0, sizeof(*sin));
-+ sin->sin_family = AF_INET;
-+ salen = sizeof(*sin);
-+ break;
-+ };
-+#ifdef HAS_SALEN
-+ sa->sa_len = salen;
-+#endif
-
-- if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
-+ if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
- msg_fatal("%s: socket: %m", myname);
-
- /*
-+ * Allow the sysadmin to specify the source address
-+ */
-+
-+ if (*bind_addr) {
-+#ifndef INET6
-+ struct sockaddr_in sin;
-+
-+ memset(&sin, 0, sizeof(sin));
-+ sin.sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin.sin_len = sizeof(sin);
-+#endif
-+ sin.sin_addr.s_addr = inet_addr(bind_addr);
-+ if (sin.sin_addr.s_addr == INADDR_NONE)
-+ msg_fatal("%s: bad %s parameter: %s",
-+ myname, VAR_LMTP_BIND_ADDR, var_smtp_bind_addr);
-+ if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0)
-+ msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+#else
-+ char hbufl[NI_MAXHOST];
-+ struct addrinfo hints, *res;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
-+ snprintf(hbufl, sizeof(hbufl)-1, "%s", bind_addr);
-+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) {
-+ (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl,
-+ sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbufl);
-+ freeaddrinfo(res);
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbufl);
-+ }
-+#endif
-+ }
-+
-+ /*
-+ * If running on a virtual host, start connections from the
-+ * right address.
-+ */
-+
-+ else if ((addr_list = own_inet_addr_list())->used == 1) {
-+#ifndef INET6
-+ struct sockaddr_in sin;
-+ unsigned long inaddr; /* XXX BAD!*/
-+
-+ memset(&sin, 0, sizeof(sin));
-+ sin.sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin.sin_len = sizeof(sin);
-+#endif
-+ memcpy((char *)&sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
-+ inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr);
-+ if (!IN_CLASSA(inaddr)
-+ /* XXX Are the two following lines correct? */
-+ || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) ==
-+ IN_LOOPBACKNET)) {
-+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
-+ msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+ }
-+#else
-+ char hbufl[NI_MAXHOST];
-+ struct addrinfo hints, *res = NULL, *loopback = NULL;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ if (getaddrinfo(NULL, "0", &hints, &loopback) != 0)
-+ loopback = NULL;
-+
-+ /*
-+ * getnameinfo -> getaddrinfo loop is here so that we can
-+ * get rid of port
-+ */
-+ (void)getnameinfo((struct sockaddr *)addr_list->addrs,
-+ SA_LEN((struct sockaddr *)addr_list->addrs),
-+ hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
-+ hbufl[sizeof(hbufl) - 1] = 0;
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
-+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 &&
-+ !(res->ai_addrlen == loopback->ai_addrlen &&
-+ memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) {
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbufl);
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbufl);
-+ }
-+ if (res)
-+ freeaddrinfo(res);
-+ if (loopback)
-+ freeaddrinfo(loopback);
-+#endif
-+ }
-+
-+ /*
- * Connect to the LMTP server.
- */
-- sin.sin_port = port;
-- memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-+ switch (addr->type) {
-+#ifdef INET6
-+ case T_AAAA:
-+ /* XXX scope-unfriendly */
-+ memset(sin6, 0, sizeof(*sin6));
-+ sin6->sin6_port = port;
-+ sin6->sin6_family = AF_INET6;
-+ salen = sizeof(*sin6);
-+ memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
-+ inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf));
-+ break;
-+#endif
-+ default: /* T_A: */
-+ memset(sin, 0, sizeof(*sin));
-+ sin->sin_port = port;
-+ sin->sin_family = AF_INET;
-+ salen = sizeof(*sin6);
-+ memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
-+ inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
-+ break;
-+ }
-+#ifdef HAS_SA_LEN
-+ sa->sa_len = salen;
-+#endif
-
- if (msg_verbose)
- msg_info("%s: trying: %s[%s] port %d...",
-- myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
-+ myname, addr->name, hbuf, ntohs(port));
-
-- return (lmtp_connect_sock(sock, (struct sockaddr *) & sin, sizeof(sin),
-- addr->name, inet_ntoa(sin.sin_addr),
-- destination, why));
-+ return (lmtp_connect_sock(sock, (struct sockaddr *)sa, salen,
-+ addr->name, hbuf, destination, why));
- }
-
- /* lmtp_connect_sock - connect a socket over some transport */
-diff -Pur postfix-1.1.11-20020613-orig/src/master/master_ent.c postfix-1.1.11-20020613/src/master/master_ent.c
---- postfix-1.1.11-20020613-orig/src/master/master_ent.c Sun Dec 23 20:08:58 2001
-+++ postfix-1.1.11-20020613/src/master/master_ent.c Wed Jun 26 15:26:48 2002
-@@ -284,8 +284,13 @@
- inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
- serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
- } else if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
-+#ifdef INET6
-+ MASTER_INET_ADDRLIST(serv) = wildcard_inet_addr_list();
-+ serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
-+#else
- MASTER_INET_ADDRLIST(serv) = 0; /* wild-card */
- serv->listen_fd_count = 1;
-+#endif
- } else {
- MASTER_INET_ADDRLIST(serv) = own_inet_addr_list(); /* virtual */
- serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
-diff -Pur postfix-1.1.11-20020613-orig/src/master/master_listen.c postfix-1.1.11-20020613/src/master/master_listen.c
---- postfix-1.1.11-20020613-orig/src/master/master_listen.c Tue May 1 00:47:57 2001
-+++ postfix-1.1.11-20020613/src/master/master_listen.c Wed Jun 26 15:26:48 2002
-@@ -64,13 +64,22 @@
-
- #include "master.h"
-
-+#ifdef INET6
-+#include <netdb.h>
-+#include <stdio.h>
-+#endif
-+
- /* master_listen_init - enable connection requests */
-
- void master_listen_init(MASTER_SERV *serv)
- {
- char *myname = "master_listen_init";
- char *end_point;
-- int n;
-+ int n,m,tmpfd;
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ SOCKADDR_SIZE salen;
-+#endif
-
- /*
- * Find out what transport we should use, then create one or more
-@@ -111,18 +120,31 @@
- serv->listen_fd[0] =
- inet_listen(MASTER_INET_PORT(serv),
- serv->max_proc > var_proc_limit ?
-- serv->max_proc : var_proc_limit, NON_BLOCKING);
-+ serv->max_proc : var_proc_limit, NON_BLOCKING, 1);
- close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
- } else { /* virtual or host:port */
-- for (n = 0; n < serv->listen_fd_count; n++) {
-+ for (m = n = 0; n < serv->listen_fd_count; n++) {
-+#ifdef INET6
-+ if (getnameinfo((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n],
-+ SA_LEN((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n]),
-+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) {
-+ strncpy(hbuf, "?????", sizeof(hbuf));
-+ }
-+ end_point = concatenate(hbuf, ":", MASTER_INET_PORT(serv), (char *) 0);
-+#else
- end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
- ":", MASTER_INET_PORT(serv), (char *) 0);
-- serv->listen_fd[n]
-+#endif
-+ tmpfd
- = inet_listen(end_point, serv->max_proc > var_proc_limit ?
-- serv->max_proc : var_proc_limit, NON_BLOCKING);
-- close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC);
-+ serv->max_proc : var_proc_limit, NON_BLOCKING, 0);
-+ if (tmpfd >= 0) {
-+ serv->listen_fd[m] = tmpfd;
-+ close_on_exec(serv->listen_fd[m++], CLOSE_ON_EXEC);
-+ }
- myfree(end_point);
- }
-+ serv->listen_fd_count=m;
- }
- break;
- default:
-diff -Pur postfix-1.1.11-20020613-orig/src/qmgr/qmgr_message.c postfix-1.1.11-20020613/src/qmgr/qmgr_message.c
---- postfix-1.1.11-20020613-orig/src/qmgr/qmgr_message.c Tue Jun 11 01:55:20 2002
-+++ postfix-1.1.11-20020613/src/qmgr/qmgr_message.c Wed Jun 26 15:26:48 2002
-@@ -507,7 +507,11 @@
- * every front-ent program.
- */
- if ((at = strrchr(recipient->address, '@')) != 0
-+#ifdef INET6
-+ && (at + 1)[strspn(at + 1, "[]0123456789.:abcdef")] != 0
-+#else
- && (at + 1)[strspn(at + 1, "[]0123456789.")] != 0
-+#endif
- && valid_hostname(at + 1, DONT_GRIPE) == 0) {
- qmgr_bounce_recipient(message, recipient,
- "bad host/domain syntax: \"%s\"", at + 1);
-diff -Pur postfix-1.1.11-20020613-orig/src/qmqpd/qmqpd_peer.c postfix-1.1.11-20020613/src/qmqpd/qmqpd_peer.c
---- postfix-1.1.11-20020613-orig/src/qmqpd/qmqpd_peer.c Thu Jul 5 22:09:35 2001
-+++ postfix-1.1.11-20020613/src/qmqpd/qmqpd_peer.c Wed Jun 26 15:29:19 2002
-@@ -70,6 +70,11 @@
- )
- #endif
-
-+#ifdef INET6
-+#define GAI_STRERROR(error) \
-+ ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
-+#endif
-+
- /* Utility library. */
-
- #include <msg.h>
-@@ -79,7 +84,6 @@
-
- /* Global library. */
-
--
- /* Application-specific. */
-
- #include "qmqpd.h"
-@@ -88,16 +92,23 @@
-
- void qmqpd_peer_init(QMQPD_STATE *state)
- {
-- struct sockaddr_in sin;
-- SOCKADDR_SIZE len = sizeof(sin);
-+#ifdef INET6
-+ struct sockaddr_storage ss;
-+#else
-+ struct sockaddr ss;
-+ struct in_addr *in;
- struct hostent *hp;
-- int i;
-+#endif
-+ struct sockaddr *sa;
-+ SOCKADDR_SIZE len;
-+
-+ sa = (struct sockaddr *)&ss;
-+ len = sizeof(ss);
-
- /*
- * Look up the peer address information.
- */
-- if (getpeername(vstream_fileno(state->client),
-- (struct sockaddr *) & sin, &len) >= 0) {
-+ if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
- errno = 0;
- }
-
-@@ -112,16 +123,50 @@
- /*
- * Look up and "verify" the client hostname.
- */
-- else if (errno == 0 && sin.sin_family == AF_INET) {
-- state->addr = mystrdup(inet_ntoa(sin.sin_addr));
-- hp = gethostbyaddr((char *) &(sin.sin_addr),
-- sizeof(sin.sin_addr), AF_INET);
-- if (hp == 0) {
-+ else if (errno == 0 && (sa->sa_family == AF_INET
-+#ifdef INET6
-+ || sa->sa_family == AF_INET6
-+#endif
-+ )) {
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ char abuf[NI_MAXHOST];
-+ struct addrinfo hints, *rnull = NULL;
-+#else
-+ char abuf[sizeof("255.255.255.255") + 1];
-+ char *hbuf;
-+#endif
-+ int error = -1;
-+
-+#ifdef INET6
-+ (void)getnameinfo(sa, len, abuf, sizeof(abuf), NULL, 0,
-+ NI_NUMERICHOST);
-+#else
-+ in = &((struct sockaddr_in *)sa)->sin_addr;
-+ inet_ntop(AF_INET, in, abuf, sizeof(abuf));
-+#endif
-+
-+ state->addr = mystrdup(abuf);
-+#ifdef INET6
-+ error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0,
-+ NI_NAMEREQD);
-+#else
-+ hbuf = NULL;
-+ hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
-+ if (hp) {
-+ error = 0;
-+ hbuf = mystrdup(hp->h_name);
-+ state->name = mystrdup("unknown");
-+ } else {
-+ error = 1;
-+ }
-+#endif
-+ if (error) {
- state->name = mystrdup("unknown");
-- } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-+ } else if (!valid_hostname(hbuf, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- } else {
-- state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
-+ state->name = mystrdup(hbuf); /* hp->name is clobbered!! */
-
- /*
- * Reject the hostname if it does not list the peer address.
-@@ -131,16 +176,31 @@
- state->name = mystrdup("unknown"); \
- }
-
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = AF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ error = getaddrinfo(state->name, NULL, &hints, &rnull);
-+ if (error) {
-+ msg_warn("%s: hostname %s verification failed: %s",
-+ state->addr, state->name, GAI_STRERROR(error));
-+ REJECT_PEER_NAME(state);
-+ }
-+ /* memcmp() isn't needed if we use getaddrinfo */
-+ if (rnull)
-+ freeaddrinfo(rnull);
-+#else
- hp = gethostbyname(state->name); /* clobbers hp->name!! */
- if (hp == 0) {
- msg_warn("%s: hostname %s verification failed: %s",
- state->addr, state->name, HSTRERROR(h_errno));
- REJECT_PEER_NAME(state);
-- } else if (hp->h_length != sizeof(sin.sin_addr)) {
-+ } else if (hp->h_length != sizeof(*in)) {
- msg_warn("%s: hostname %s verification failed: bad address size %d",
- state->addr, state->name, hp->h_length);
- REJECT_PEER_NAME(state);
- } else {
-+ int i;
- for (i = 0; /* void */ ; i++) {
- if (hp->h_addr_list[i] == 0) {
- msg_warn("%s: address not listed for hostname %s",
-@@ -148,12 +208,12 @@
- REJECT_PEER_NAME(state);
- break;
- }
-- if (memcmp(hp->h_addr_list[i],
-- (char *) &sin.sin_addr,
-- sizeof(sin.sin_addr)) == 0)
-+ if (memcmp(hp->h_addr_list[i], (char *)in,
-+ sizeof(*in)) == 0)
- break; /* keep peer name */
- }
- }
-+#endif
- }
- }
-
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/Makefile.in postfix-1.1.11-20020613/src/smtp/Makefile.in
---- postfix-1.1.11-20020613-orig/src/smtp/Makefile.in Tue Jun 11 03:14:03 2002
-+++ postfix-1.1.11-20020613/src/smtp/Makefile.in Wed Jun 26 15:26:48 2002
-@@ -84,6 +84,7 @@
- smtp.o: ../../include/iostuff.h
- smtp.o: ../../include/attr.h
- smtp.o: ../../include/mail_server.h
-+smtp.o: ../../include/pfixtls.h
- smtp.o: smtp.h
- smtp.o: smtp_sasl.h
- smtp_addr.o: smtp_addr.c
-@@ -103,6 +104,7 @@
- smtp_addr.o: ../../include/argv.h
- smtp_addr.o: ../../include/deliver_request.h
- smtp_addr.o: ../../include/recipient_list.h
-+smtp_addr.o: ../../include/pfixtls.h
- smtp_addr.o: smtp_addr.h
- smtp_chat.o: smtp_chat.c
- smtp_chat.o: ../../include/sys_defs.h
-@@ -123,6 +125,7 @@
- smtp_chat.o: ../../include/cleanup_user.h
- smtp_chat.o: ../../include/mail_error.h
- smtp_chat.o: ../../include/name_mask.h
-+smtp_chat.o: ../../include/pfixtls.h
- smtp_chat.o: smtp.h
- smtp_connect.o: smtp_connect.c
- smtp_connect.o: ../../include/sys_defs.h
-@@ -139,10 +142,12 @@
- smtp_connect.o: ../../include/mail_params.h
- smtp_connect.o: ../../include/own_inet_addr.h
- smtp_connect.o: ../../include/dns.h
-+smtp_connect.o: ../../include/get_port.h
- smtp_connect.o: smtp.h
- smtp_connect.o: ../../include/argv.h
- smtp_connect.o: ../../include/deliver_request.h
- smtp_connect.o: ../../include/recipient_list.h
-+smtp_connetc.o: ../../include/pfixtls.h
- smtp_connect.o: smtp_addr.h
- smtp_proto.o: smtp_proto.c
- smtp_proto.o: ../../include/sys_defs.h
-@@ -174,6 +179,7 @@
- smtp_proto.o: ../../include/attr.h
- smtp_proto.o: ../../include/mime_state.h
- smtp_proto.o: ../../include/header_opts.h
-+smtp_proto.o: ../../include/pfixtls.h
- smtp_proto.o: smtp.h
- smtp_proto.o: ../../include/argv.h
- smtp_proto.o: smtp_sasl.h
-@@ -219,9 +225,12 @@
- smtp_session.o: ../../include/stringops.h
- smtp_session.o: ../../include/vstring.h
- smtp_session.o: smtp.h
-+smtp_session.o: ../../include/mail_params.h
-+smtp_session.o: ../../include/pfixtls.h
- smtp_session.o: ../../include/argv.h
- smtp_session.o: ../../include/deliver_request.h
- smtp_session.o: ../../include/recipient_list.h
-+smtp_session.o: ../../include/maps.h
- smtp_state.o: smtp_state.c
- smtp_state.o: ../../include/sys_defs.h
- smtp_state.o: ../../include/mymalloc.h
-@@ -235,6 +244,7 @@
- smtp_state.o: ../../include/argv.h
- smtp_state.o: ../../include/deliver_request.h
- smtp_state.o: ../../include/recipient_list.h
-+smtp_state.o: ../../include/pfixtls.h
- smtp_state.o: smtp_sasl.h
- smtp_trouble.o: smtp_trouble.c
- smtp_trouble.o: ../../include/sys_defs.h
-@@ -254,6 +264,7 @@
- smtp_trouble.o: ../../include/name_mask.h
- smtp_trouble.o: smtp.h
- smtp_trouble.o: ../../include/argv.h
-+smtp_trouble.o: ../../include/pfixtls.h
- smtp_unalias.o: smtp_unalias.c
- smtp_unalias.o: ../../include/sys_defs.h
- smtp_unalias.o: ../../include/htable.h
-@@ -266,3 +277,4 @@
- smtp_unalias.o: ../../include/argv.h
- smtp_unalias.o: ../../include/deliver_request.h
- smtp_unalias.o: ../../include/recipient_list.h
-+smtp_unalias.o: ../../include/pfixtls.h
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/sasl_problem_diff postfix-1.1.11-20020613/src/smtp/sasl_problem_diff
---- postfix-1.1.11-20020613-orig/src/smtp/sasl_problem_diff Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/smtp/sasl_problem_diff Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,17 @@
-+--- smtp_proto.c.old Wed May 15 14:01:56 2002
-++++ smtp_proto.c Fri May 24 21:13:50 2002
-+@@ -372,8 +372,13 @@
-+ else if (strcasecmp(word, "STARTTLS") == 0)
-+ state->features |= SMTP_FEATURE_STARTTLS;
-+ #ifdef USE_SASL_AUTH
-+- else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
-++ else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0) {
-++ if (state->sasl_mechanism_list) {
-++ myfree(state->sasl_mechanism_list);
-++ state->sasl_mechanism_list = 0;
-++ }
-+ smtp_sasl_helo_auth(state, words);
-++ }
-+ #endif
-+ }
-+ }
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp.c postfix-1.1.11-20020613/src/smtp/smtp.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp.c Mon May 27 01:07:04 2002
-+++ postfix-1.1.11-20020613/src/smtp/smtp.c Wed Jun 26 15:26:48 2002
-@@ -100,7 +100,11 @@
- /* .IP \fBsmtp_never_send_ehlo\fR
- /* Never send EHLO at the start of a connection.
- /* .IP \fBsmtp_bind_address\fR
--/* Numerical source network address to bind to when making a connection.
-+/* Numerical source network address (IPv4) to bind to when making
-+/* a connection.
-+/* .IP \fBsmtp_bind_address6\fR
-+/* Numerical source network address (IPv6) to bind to when making
-+/* a connection.
- /* .IP \fBsmtp_line_length_limit\fR
- /* Length limit for SMTP message content lines. Zero means no limit.
- /* Some SMTP servers misbehave on long lines.
-@@ -240,6 +244,7 @@
- #include <debug_peer.h>
- #include <mail_error.h>
- #include <deliver_pass.h>
-+#include <pfixtls.h>
-
- /* Single server skeleton. */
-
-@@ -256,6 +261,7 @@
- */
- int var_smtp_conn_tmout;
- int var_smtp_helo_tmout;
-+int var_smtp_starttls_tmout;
- int var_smtp_mail_tmout;
- int var_smtp_rcpt_tmout;
- int var_smtp_data0_tmout;
-@@ -277,11 +283,20 @@
- char *var_smtp_sasl_passwd;
- bool var_smtp_sasl_enable;
- char *var_smtp_bind_addr;
-+#ifdef INET6
-+char *var_smtp_bind_addr6;
-+#endif
- bool var_smtp_rand_addr;
- int var_smtp_pix_thresh;
- int var_smtp_pix_delay;
- int var_smtp_line_limit;
- char *var_smtp_helo_name;
-+int var_smtp_use_tls;
-+int var_smtp_enforce_tls;
-+int var_smtp_tls_enforce_peername;
-+char *var_smtp_tls_per_site;
-+int var_smtp_tls_scert_vd;
-+int var_smtp_tls_note_starttls_offer;
-
- /*
- * Global variables. smtp_errno is set by the address lookup routines and by
-@@ -391,6 +406,7 @@
-
- static void pre_init(char *unused_name, char **unused_argv)
- {
-+
- debug_peer_init();
-
- if (var_smtp_sasl_enable)
-@@ -400,6 +416,14 @@
- 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
-+ */
-+#ifdef HAS_SSL
-+ if (var_smtp_use_tls || var_smtp_enforce_tls || var_smtp_tls_per_site[0])
-+ pfixtls_init_clientengine(var_smtp_tls_scert_vd);
-+ smtp_tls_list_init();
-+#endif
- }
-
- /* pre_accept - see if tables have changed */
-@@ -434,7 +458,11 @@
- 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,
- VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
-+#ifdef INET6
-+ VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
-+#endif
- VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 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[] = {
-@@ -448,6 +476,7 @@
- VAR_SMTP_QUIT_TMOUT, DEF_SMTP_QUIT_TMOUT, &var_smtp_quit_tmout, 1, 0,
- 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_STARTTLS_TMOUT, DEF_SMTP_STARTTLS_TMOUT, &var_smtp_starttls_tmout, 1, 0,
- 0,
- };
- static CONFIG_INT_TABLE int_table[] = {
-@@ -463,6 +492,10 @@
- VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
- VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
- VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
-+ VAR_SMTP_USE_TLS, DEF_SMTP_USE_TLS, &var_smtp_use_tls,
-+ VAR_SMTP_ENFORCE_TLS, DEF_SMTP_ENFORCE_TLS, &var_smtp_enforce_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,
- 0,
- };
-
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp.h postfix-1.1.11-20020613/src/smtp/smtp.h
---- postfix-1.1.11-20020613-orig/src/smtp/smtp.h Thu May 23 21:18:02 2002
-+++ postfix-1.1.11-20020613/src/smtp/smtp.h Wed Jun 26 15:26:48 2002
-@@ -27,6 +27,7 @@
- * Global library.
- */
- #include <deliver_request.h>
-+#include <pfixtls.h>
-
- /*
- * State information associated with each SMTP delivery. We're bundling the
-@@ -79,9 +80,14 @@
- char *addr; /* mail exchanger */
- char *namaddr; /* mail exchanger */
- int best; /* most preferred host */
-+ int tls_use_tls; /* can do TLS */
-+ int tls_enforce_tls; /* must do TLS */
-+ int tls_enforce_peername; /* cert must match */
-+ tls_info_t tls_info; /* TLS connection state */
- } SMTP_SESSION;
-
--extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, char *, char *);
-+extern void smtp_tls_list_init(void);
-+extern SMTP_SESSION *smtp_session_alloc(char *, VSTREAM *, char *, char *);
- extern void smtp_session_free(SMTP_SESSION *);
-
- /*
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp_addr.c postfix-1.1.11-20020613/src/smtp/smtp_addr.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp_addr.c Sun Jul 8 17:05:26 2001
-+++ postfix-1.1.11-20020613/src/smtp/smtp_addr.c Wed Jun 26 15:26:48 2002
-@@ -134,18 +134,68 @@
- static void smtp_print_addr(char *what, DNS_RR *addr_list)
- {
- DNS_RR *addr;
-- struct in_addr in_addr;
-+#ifdef INET6
-+ struct sockaddr_storage ss;
-+#else
-+ struct sockaddr ss;
-+#endif
-+ struct sockaddr_in *sin;
-+#ifdef INET6
-+ struct sockaddr_in6 *sin6;
-+ char hbuf[NI_MAXHOST];
-+#else
-+ char hbuf[sizeof("255.255.255.255") + 1];
-+#endif
-
- msg_info("begin %s address list", what);
- for (addr = addr_list; addr; addr = addr->next) {
-- if (addr->data_len > sizeof(addr)) {
-- msg_warn("skipping address length %d", addr->data_len);
-- } else {
-- memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
-- msg_info("pref %4d host %s/%s",
-- addr->pref, addr->name,
-- inet_ntoa(in_addr));
-+ if (addr->class != C_IN) {
-+ msg_warn("skipping unsupported address (class=%u)", addr->class);
-+ continue;
- }
-+ switch (addr->type) {
-+ case T_A:
-+ if (addr->data_len != sizeof(sin->sin_addr)) {
-+ msg_warn("skipping invalid address (AAAA, len=%u)",
-+ addr->data_len);
-+ continue;
-+ }
-+ sin = (struct sockaddr_in *)&ss;
-+ memset(sin, 0, sizeof(*sin));
-+ sin->sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin->sin_len = sizeof(*sin);
-+#endif
-+ memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
-+ break;
-+#ifdef INET6
-+ case T_AAAA:
-+ if (addr->data_len != sizeof(sin6->sin6_addr)) {
-+ msg_warn("skipping invalid address (AAAA, len=%u)",
-+ addr->data_len);
-+ continue;
-+ }
-+ sin6 = (struct sockaddr_in6 *)&ss;
-+ memset(sin6, 0, sizeof(*sin6));
-+ sin6->sin6_family = AF_INET6;
-+#ifdef HAS_SA_LEN
-+ sin6->sin6_len = sizeof(*sin6);
-+#endif
-+ memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
-+ break;
-+#endif
-+ default:
-+ msg_warn("skipping unsupported address (type=%u)", addr->type);
-+ continue;
-+ }
-+
-+#ifdef INET6
-+ (void)getnameinfo((struct sockaddr *)&ss, SS_LEN(ss),
-+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
-+#else
-+ (void)inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
-+#endif
-+ msg_info("pref %4d host %s/%s", addr->pref, addr->name, hbuf);
- }
- msg_info("end %s address list", what);
- }
-@@ -155,15 +205,23 @@
- static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
- {
- char *myname = "smtp_addr_one";
-+#ifndef INET6
- struct in_addr inaddr;
-- DNS_FIXED fixed;
- DNS_RR *addr = 0;
- DNS_RR *rr;
- struct hostent *hp;
-+#else
-+ struct addrinfo hints, *res0, *res;
-+ int error = -1;
-+ char *addr;
-+ size_t addrlen;
-+#endif
-+ DNS_FIXED fixed;
-
- if (msg_verbose)
- msg_info("%s: host %s", myname, host);
-
-+#ifndef INET6
- /*
- * Interpret a numerical name as an address.
- */
-@@ -216,6 +274,48 @@
- smtp_errno = SMTP_FAIL;
- break;
- }
-+#else
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ error = getaddrinfo(host, NULL, &hints, &res0);
-+ if (error) {
-+ switch (error) {
-+ case EAI_AGAIN:
-+ smtp_errno = SMTP_RETRY;
-+ break;
-+ default:
-+ vstring_sprintf(why, "[%s]: %s",host,gai_strerror(error));
-+ smtp_errno = SMTP_FAIL;
-+ break;
-+ }
-+ return (addr_list);
-+ }
-+ for (res = res0; res; res = res->ai_next) {
-+ memset((char *) &fixed, 0, sizeof(fixed));
-+ switch(res->ai_family) {
-+ case AF_INET6:
-+ /* XXX not scope friendly */
-+ fixed.type = T_AAAA;
-+ addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
-+ addrlen = sizeof(struct in6_addr);
-+ break;
-+ case AF_INET:
-+ fixed.type = T_A;
-+ addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
-+ addrlen = sizeof(struct in_addr);
-+ break;
-+ default:
-+ msg_warn("%s: unknown address family %d for %s",
-+ myname, res->ai_family, host);
-+ continue;
-+ }
-+ addr_list = dns_rr_append(addr_list,
-+ dns_rr_create(host, &fixed, pref, addr, addrlen));
-+ }
-+ if (res0)
-+ freeaddrinfo(res0);
-+#endif
- return (addr_list);
- }
-
-@@ -251,6 +351,9 @@
- INET_ADDR_LIST *self;
- DNS_RR *addr;
- int i;
-+#ifdef INET6
-+ struct sockaddr *sa;
-+#endif
-
- /*
- * Find the first address that lists any address that this mail system is
-@@ -260,12 +363,36 @@
-
- self = own_inet_addr_list();
- for (addr = addr_list; addr; addr = addr->next) {
-- for (i = 0; i < self->used; i++)
-+ for (i = 0; i < self->used; i++) {
-+#ifdef INET6
-+ sa = (struct sockaddr *)&self->addrs[i];
-+ switch(addr->type) {
-+ case T_AAAA:
-+ /* XXX scope */
-+ if (sa->sa_family != AF_INET6)
-+ break;
-+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
-+ addr->data, sizeof(struct in6_addr)) == 0) {
-+ return(addr);
-+ }
-+ break;
-+ case T_A:
-+ if (sa->sa_family != AF_INET)
-+ break;
-+ if (memcmp(&((struct sockaddr_in *)sa)->sin_addr,
-+ addr->data, sizeof(struct in_addr)) == 0) {
-+ return(addr);
-+ }
-+ break;
-+ }
-+#else
- if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
- if (msg_verbose)
- msg_info("%s: found at pref %d", myname, addr->pref);
- return (addr);
- }
-+#endif
-+ }
- }
-
- /*
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp_connect.c postfix-1.1.11-20020613/src/smtp/smtp_connect.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp_connect.c Sun Jul 8 21:40:03 2001
-+++ postfix-1.1.11-20020613/src/smtp/smtp_connect.c Wed Jun 26 15:26:48 2002
-@@ -81,6 +81,7 @@
- /* System library. */
-
- #include <sys_defs.h>
-+#include <stdlib.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-@@ -110,12 +111,14 @@
- #include <inet_addr_list.h>
- #include <iostuff.h>
- #include <timed_connect.h>
-+#include <get_port.h>
- #include <stringops.h>
-
- /* Global library. */
-
- #include <mail_params.h>
- #include <own_inet_addr.h>
-+#include <pfixtls.h>
-
- /* DNS library. */
-
-@@ -128,23 +131,50 @@
-
- /* smtp_connect_addr - connect to explicit address */
-
--static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
-+static SMTP_SESSION *smtp_connect_addr(char *dest, DNS_RR *addr, unsigned port,
- VSTRING *why)
- {
- char *myname = "smtp_connect_addr";
-- struct sockaddr_in sin;
-- int sock;
-+#ifdef INET6
-+ struct sockaddr_storage ss;
-+#else
-+ struct sockaddr ss;
-+#endif
-+ struct sockaddr *sa;
-+ struct sockaddr_in *sin;
-+#ifdef INET6
-+ struct sockaddr_in6 *sin6;
-+#endif
-+ SOCKADDR_SIZE salen;
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+#else
-+ char hbuf[sizeof("255.255.255.255") + 1];
-+#endif
-+ int sock = -1;
- INET_ADDR_LIST *addr_list;
- int conn_stat;
- int saved_errno;
- VSTREAM *stream;
- int ch;
-- unsigned long inaddr;
-+ char *bind_addr;
-+
-+ sa = (struct sockaddr *)&ss;
-+ sin = (struct sockaddr_in *)&ss;
-+#ifdef INET6
-+ sin6 = (struct sockaddr_in6 *)&ss;
-+#endif
-
- /*
- * Sanity checks.
- */
-- if (addr->data_len > sizeof(sin.sin_addr)) {
-+#ifdef INET6
-+ if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) ||
-+ ((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr))))
-+#else
-+ if (addr->data_len > sizeof(sin->sin_addr))
-+#endif
-+ {
- msg_warn("%s: skip address with length %d", myname, addr->data_len);
- smtp_errno = SMTP_RETRY;
- return (0);
-@@ -153,18 +183,42 @@
- /*
- * Initialize.
- */
-- memset((char *) &sin, 0, sizeof(sin));
-- sin.sin_family = AF_INET;
--
-- if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
-- msg_fatal("%s: socket: %m", myname);
--
-+ switch (addr->type) {
-+#ifdef INET6
-+ case T_AAAA:
-+ bind_addr = var_smtp_bind_addr6;
-+ memset(sin6, 0, sizeof(*sin6));
-+ sin6->sin6_family = AF_INET6;
-+ salen = sizeof(*sin6);
-+ break;
-+#endif
-+ default: /* T_A: */
-+ bind_addr = var_smtp_bind_addr;
-+ memset(sin, 0, sizeof(*sin));
-+ sin->sin_family = AF_INET;
-+ salen = sizeof(*sin);
-+ break;
-+ }
-+#ifdef HAS_SA_LEN
-+ sa->sa_len = salen;
-+#endif
-+ if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
-+ msg_warn("%s: socket: %m", myname);
-+
- /*
- * Allow the sysadmin to specify the source address, for example, as "-o
- * smtp_bind_address=x.x.x.x" in the master.cf file.
- */
-- if (*var_smtp_bind_addr) {
-- sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
-+ if (*bind_addr) {
-+#ifndef INET6
-+ struct sockaddr_in sin;
-+
-+ memset(&sin, 0, sizeof(sin));
-+ sin.sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin.sin_len = sizeof(sin);
-+#endif
-+ sin.sin_addr.s_addr = inet_addr(bind_addr);
- if (sin.sin_addr.s_addr == INADDR_NONE)
- msg_fatal("%s: bad %s parameter: %s",
- myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
-@@ -172,6 +226,25 @@
- msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
- if (msg_verbose)
- msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+#else
-+ char hbufl[NI_MAXHOST];
-+ struct addrinfo hints, *res;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
-+ snprintf(hbufl, sizeof(hbufl)-1, "%s", bind_addr);
-+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) {
-+ (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl,
-+ sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbufl);
-+ freeaddrinfo(res);
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbufl);
-+ }
-+#endif
- }
-
- /*
-@@ -179,8 +252,17 @@
- * the mail appears to come from the "right" machine address.
- */
- else if ((addr_list = own_inet_addr_list())->used == 1) {
-+#ifndef INET6
-+ struct sockaddr_in sin;
-+ unsigned long inaddr; /*XXX BAD!*/
-+
-+ memset(&sin, 0, sizeof(sin));
-+ sin.sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin.sin_len = sizeof(sin);
-+#endif
- memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
-- inaddr = ntohl(sin.sin_addr.s_addr);
-+ inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr);
- if (!IN_CLASSA(inaddr)
- || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
- if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
-@@ -188,30 +270,85 @@
- if (msg_verbose)
- msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
- }
-+#else
-+ char hbufl[NI_MAXHOST];
-+ struct addrinfo hints, *res = NULL, *loopback = NULL;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ if (getaddrinfo(NULL, "0", &hints, &loopback) != 0)
-+ loopback = NULL;
-+
-+ /*
-+ * getnameinfo -> getaddrinfo loop is here so that we can
-+ * get rid of port.
-+ */
-+ (void)getnameinfo((struct sockaddr *)addr_list->addrs, SA_LEN((struct sockaddr *)addr_list->addrs),
-+ hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
-+ hbufl[sizeof(hbufl)-1] = 0;
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = sa->sa_family;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
-+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 &&
-+ !(res->ai_addrlen == loopback->ai_addrlen &&
-+ memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) {
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbufl);
-+ if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbufl);
-+ }
-+ if (res)
-+ freeaddrinfo(res);
-+ if (loopback)
-+ freeaddrinfo(loopback);
-+#endif
- }
-
- /*
- * Connect to the SMTP server.
- */
-- sin.sin_port = port;
-- memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-+ switch (addr->type) {
-+#ifdef INET6
-+ case T_AAAA:
-+ /* XXX scope unfriendly */
-+ memset(sin6, 0, sizeof(*sin6));
-+ sin6->sin6_port = port;
-+ sin6->sin6_family = AF_INET6;
-+ salen = sizeof(*sin6);
-+ memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
-+ inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf));
-+ break;
-+#endif
-+ default: /* T_A */
-+ memset(sin, 0, sizeof(*sin));
-+ sin->sin_port = port;
-+ sin->sin_family = AF_INET;
-+ salen = sizeof(*sin);
-+ memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
-+ inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
-+ break;
-+ }
-+#ifdef HAS_SA_LEN
-+ sa->sa_len = salen;
-+#endif
-
- if (msg_verbose)
- msg_info("%s: trying: %s[%s] port %d...",
-- myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
-+ myname, addr->name, hbuf, ntohs(port));
- if (var_smtp_conn_tmout > 0) {
- non_blocking(sock, NON_BLOCKING);
-- conn_stat = timed_connect(sock, (struct sockaddr *) & sin,
-- sizeof(sin), var_smtp_conn_tmout);
-+ conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
- saved_errno = errno;
- non_blocking(sock, BLOCKING);
- errno = saved_errno;
- } else {
-- conn_stat = connect(sock, (struct sockaddr *) & sin, sizeof(sin));
-+ conn_stat = connect(sock, sa, salen);
- }
- if (conn_stat < 0) {
- vstring_sprintf(why, "connect to %s[%s]: %m",
-- addr->name, inet_ntoa(sin.sin_addr));
-+ addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
-@@ -221,8 +358,8 @@
- * Skip this host if it takes no action within some time limit.
- */
- if (read_wait(sock, var_smtp_helo_tmout) < 0) {
-- vstring_sprintf(why, "connect to %s[%s]: read timeout",
-- addr->name, inet_ntoa(sin.sin_addr));
-+ vstring_sprintf(why, "connect to %s [%s]: read timeout",
-+ addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
-@@ -233,8 +370,8 @@
- */
- stream = vstream_fdopen(sock, O_RDWR);
- if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
-- vstring_sprintf(why, "connect to %s[%s]: server dropped connection",
-- addr->name, inet_ntoa(sin.sin_addr));
-+ vstring_sprintf(why, "connect to %s [%s]: server dropped connection",
-+ addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
-@@ -246,7 +383,7 @@
- */
- if (ch == '4' && var_smtp_skip_4xx_greeting) {
- vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
-- addr->name, inet_ntoa(sin.sin_addr));
-+ addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
-@@ -257,12 +394,12 @@
- */
- if (ch == '5' && var_smtp_skip_5xx_greeting) {
- vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
-- addr->name, inet_ntoa(sin.sin_addr));
-+ addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
- }
-- return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
-+ return (smtp_session_alloc(dest, stream, addr->name, hbuf));
- }
-
- /* smtp_connect_host - direct connection to host */
-@@ -272,7 +409,7 @@
- SMTP_SESSION *session = 0;
- DNS_RR *addr_list;
- DNS_RR *addr;
--
-+
- /*
- * Try each address in the specified order until we find one that works.
- * The addresses belong to the same A record, so we have no information
-@@ -280,7 +417,7 @@
- */
- addr_list = smtp_host_addr(host, why);
- for (addr = addr_list; addr; addr = addr->next) {
-- if ((session = smtp_connect_addr(addr, port, why)) != 0) {
-+ if ((session = smtp_connect_addr(host, addr, port, why)) != 0) {
- session->best = 1;
- break;
- }
-@@ -309,7 +446,7 @@
- */
- addr_list = smtp_domain_addr(name, why, found_myself);
- for (addr = addr_list; addr; addr = addr->next) {
-- if ((session = smtp_connect_addr(addr, port, why)) != 0) {
-+ if ((session = smtp_connect_addr(name, addr, port, why)) != 0) {
- session->best = (addr->pref == addr_list->pref);
- break;
- }
-@@ -379,6 +516,7 @@
- msg_fatal("unknown service: %s/%s", service, protocol);
- *portp = sp->s_port;
- }
-+
- return (buf);
- }
-
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp_proto.c postfix-1.1.11-20020613/src/smtp/smtp_proto.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp_proto.c Sat Jun 1 15:07:27 2002
-+++ postfix-1.1.11-20020613/src/smtp/smtp_proto.c Wed Jun 26 15:26:48 2002
-@@ -103,6 +103,7 @@
- #include <quote_821_local.h>
- #include <mail_proto.h>
- #include <mime_state.h>
-+#include <pfixtls.h>
-
- /* Application-specific. */
-
-@@ -170,6 +171,8 @@
- char *words;
- char *word;
- int n;
-+ int oldfeatures;
-+ int rval;
-
- /*
- * Prepare for disaster.
-@@ -231,7 +234,8 @@
- session->namaddr,
- translit(resp->str, "\n", " ")));
- }
--
-+ if (var_smtp_always_ehlo)
-+ state->features |= SMTP_FEATURE_ESMTP;
- /*
- * Pick up some useful features offered by the SMTP server. XXX Until we
- * have a portable routine to convert from string to off_t with proper
-@@ -243,6 +247,7 @@
- * MicroSoft implemented AUTH based on an old draft.
- */
- lines = resp->str;
-+ oldfeatures = state->features; /* remember */
- while ((words = mystrtok(&lines, "\n")) != 0) {
- if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) {
- if (strcasecmp(word, "8BITMIME") == 0)
-@@ -259,6 +264,8 @@
- state->size_limit = off_cvt_string(word);
- }
- }
-+ else if (strcasecmp(word, "STARTTLS") == 0)
-+ state->features |= SMTP_FEATURE_STARTTLS;
- #ifdef USE_SASL_AUTH
- else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
- smtp_sasl_helo_auth(state, words);
-@@ -276,6 +283,128 @@
- msg_info("server features: 0x%x size %.0f",
- state->features, (double) state->size_limit);
-
-+#ifdef HAS_SSL
-+ if ((state->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);
-+ if ((session->tls_enforce_tls) &&
-+ !(state->features & SMTP_FEATURE_STARTTLS))
-+ {
-+ /*
-+ * We are enforced to use TLS but it is not offered, so we will give
-+ * up on this host. We won't even try STARTTLS, because we could
-+ * receive a "500 command unrecognized" which would bounce the
-+ * message. We instead want to delay until STARTTLS becomes
-+ * available.
-+ */
-+ return (smtp_site_fail(state, 450, "Could not start TLS: not offered"));
-+ }
-+ if ((session->tls_enforce_tls) && !pfixtls_clientengine) {
-+ /*
-+ * We would like to start client TLS, but our own TLS-engine is
-+ * not running.
-+ */
-+ return (smtp_site_fail(state, 450,
-+ "Could not start TLS: our TLS-engine not running"));
-+ }
-+ if ((state->features & SMTP_FEATURE_STARTTLS) &&
-+ ((session->tls_use_tls && pfixtls_clientengine) ||
-+ (session->tls_enforce_tls))) {
-+ /*
-+ * Try to use the TLS feature
-+ */
-+ smtp_chat_cmd(state, "STARTTLS");
-+ if ((resp = smtp_chat_resp(state))->code / 100 != 2) {
-+ state->features &= ~SMTP_FEATURE_STARTTLS;
-+ /*
-+ * At this point a political decision is necessary. If we
-+ * enforce usage of tls, we have to close the connection
-+ * now.
-+ */
-+ if (session->tls_enforce_tls)
-+ return (smtp_site_fail(state, resp->code,
-+ "host %s refused to start TLS: %s",
-+ session->host,
-+ translit(resp->str, "\n", " ")));
-+ } else {
-+ if (rval = pfixtls_start_clienttls(session->stream,
-+ var_smtp_starttls_tmout,
-+ session->tls_enforce_peername,
-+ session->host,
-+ &(session->tls_info)))
-+ return (smtp_site_fail(state, 450,
-+ "Could not start TLS: client failure"));
-+
-+
-+ /*
-+ * Now the connection is established and maybe we do have a
-+ * validated cert with a CommonName in it.
-+ * In enforce_peername state, the handshake would already have
-+ * been terminated so the check here is for logging only!
-+ */
-+ if (session->tls_info.peer_CN != NULL) {
-+ if (!session->tls_info.peer_verified) {
-+ msg_info("Peer certficate could not be verified");
-+ if (session->tls_enforce_tls) {
-+ pfixtls_stop_clienttls(session->stream,
-+ var_smtp_starttls_tmout, 1,
-+ &(session->tls_info));
-+ return(smtp_site_fail(state, 450, "TLS-failure: Could not verify certificate"));
-+ }
-+ }
-+ } else if (session->tls_enforce_tls) {
-+ pfixtls_stop_clienttls(session->stream,
-+ var_smtp_starttls_tmout, 1,
-+ &(session->tls_info));
-+ return (smtp_site_fail(state, 450, "TLS-failure: Cannot verify hostname"));
-+ }
-+
-+ /*
-+ * At this point we have to re-negotiate the "EHLO" to reget
-+ * the feature-list
-+ */
-+ state->features = oldfeatures;
-+#ifdef USE_SASL_AUTH
-+ if (state->sasl_mechanism_list) {
-+ myfree(state->sasl_mechanism_list);
-+ state->sasl_mechanism_list = 0;
-+ }
-+#endif
-+ if (state->features & SMTP_FEATURE_ESMTP) {
-+ smtp_chat_cmd(state, "EHLO %s", var_myhostname);
-+ if ((resp = smtp_chat_resp(state))->code / 100 != 2)
-+ state->features &= ~SMTP_FEATURE_ESMTP;
-+ }
-+ lines = resp->str;
-+ (void) mystrtok(&lines, "\n");
-+ while ((words = mystrtok(&lines, "\n")) != 0) {
-+ if (mystrtok(&words, "- ") &&
-+ (word = mystrtok(&words, " \t=")) != 0) {
-+ if (strcasecmp(word, "8BITMIME") == 0)
-+ state->features |= SMTP_FEATURE_8BITMIME;
-+ else if (strcasecmp(word, "PIPELINING") == 0)
-+ state->features |= SMTP_FEATURE_PIPELINING;
-+ else if (strcasecmp(word, "SIZE") == 0)
-+ state->features |= SMTP_FEATURE_SIZE;
-+ else if (strcasecmp(word, "STARTTLS") == 0)
-+ state->features |= SMTP_FEATURE_STARTTLS;
-+#ifdef USE_SASL_AUTH
-+ else if (var_smtp_sasl_enable &&
-+ strcasecmp(word, "AUTH") == 0)
-+ smtp_sasl_helo_auth(state, words);
-+#endif
-+ }
-+ }
-+ /*
-+ * Actually, at this point STARTTLS should not be offered
-+ * anymore, so we could check for a protocol violation, but
-+ * what should we do then?
-+ */
-+
-+ }
-+ }
-+#endif
- #ifdef USE_SASL_AUTH
- if (var_smtp_sasl_enable && (state->features & SMTP_FEATURE_AUTH))
- return (smtp_sasl_helo_login(state));
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp_session.c postfix-1.1.11-20020613/src/smtp/smtp_session.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp_session.c Mon Nov 20 19:06:05 2000
-+++ postfix-1.1.11-20020613/src/smtp/smtp_session.c Wed Jun 26 15:26:48 2002
-@@ -42,15 +42,42 @@
- #include <vstream.h>
- #include <stringops.h>
-
-+#include <mail_params.h>
-+#include <maps.h>
-+#include <pfixtls.h>
-+
- /* Application-specific. */
-
- #include "smtp.h"
-
-+#ifdef HAS_SSL
-+/* static lists */
-+static MAPS *tls_per_site;
-+
-+/* smtp_tls_list_init - initialize 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);
-+}
-+#endif
-+
- /* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
-
--SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
-+SMTP_SESSION *smtp_session_alloc(char *dest, VSTREAM *stream, char *host, char *addr)
- {
- SMTP_SESSION *session;
-+ const char *lookup;
-+ char *lookup_key;
-+ int host_dont_use = 0;
-+ int host_use = 0;
-+ int host_enforce = 0;
-+ int host_enforce_peername = 0;
-+ int recipient_dont_use = 0;
-+ int recipient_use = 0;
-+ int recipient_enforce = 0;
-+ int recipient_enforce_peername = 0;
-
- session = (SMTP_SESSION *) mymalloc(sizeof(*session));
- session->stream = stream;
-@@ -58,6 +85,61 @@
- session->addr = mystrdup(addr);
- session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
- session->best = 1;
-+ session->tls_use_tls = session->tls_enforce_tls = 0;
-+ session->tls_enforce_peername = 0;
-+#ifdef HAS_SSL
-+ lookup_key = lowercase(mystrdup(host));
-+ if (lookup = maps_find(tls_per_site, lookup_key, 0)) {
-+ if (!strcasecmp(lookup, "NONE"))
-+ host_dont_use = 1;
-+ else if (!strcasecmp(lookup, "MAY"))
-+ host_use = 1;
-+ else if (!strcasecmp(lookup, "MUST"))
-+ host_enforce = host_enforce_peername = 1;
-+ else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
-+ host_enforce = 1;
-+ else
-+ msg_warn("Unknown TLS state for receiving host %s: '%s', using default policy", session->host, lookup);
-+ }
-+ myfree(lookup_key);
-+ lookup_key = lowercase(mystrdup(dest));
-+ if (lookup = maps_find(tls_per_site, dest, 0)) {
-+ if (!strcasecmp(lookup, "NONE"))
-+ recipient_dont_use = 1;
-+ else if (!strcasecmp(lookup, "MAY"))
-+ recipient_use = 1;
-+ else if (!strcasecmp(lookup, "MUST"))
-+ recipient_enforce = recipient_enforce_peername = 1;
-+ else if (!strcasecmp(lookup, "MUST_NOPEERMATCH"))
-+ recipient_enforce = 1;
-+ else
-+ msg_warn("Unknown TLS state for recipient domain %s: '%s', using default policy", dest, lookup);
-+ }
-+ myfree(lookup_key);
-+
-+ if ((var_smtp_enforce_tls && !host_dont_use && !recipient_dont_use) || host_enforce ||
-+ recipient_enforce)
-+ session->tls_enforce_tls = session->tls_use_tls = 1;
-+
-+ /*
-+ * Set up peername checking. 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_enforce && host_enforce_peername)
-+ session->tls_enforce_peername = 1;
-+ else if (recipient_enforce && recipient_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_dont_use && !recipient_dont_use) || host_use || recipient_use)
-+ session->tls_use_tls = 1;
-+#endif
-+ session->tls_info = tls_info_zero;
- return (session);
- }
-
-@@ -65,6 +147,11 @@
-
- void smtp_session_free(SMTP_SESSION *session)
- {
-+#ifdef HAS_SSL
-+ vstream_fflush(session->stream);
-+ pfixtls_stop_clienttls(session->stream, var_smtp_starttls_tmout, 0,
-+ &(session->tls_info));
-+#endif
- vstream_fclose(session->stream);
- myfree(session->host);
- myfree(session->addr);
-diff -Pur postfix-1.1.11-20020613-orig/src/smtp/smtp_unalias.c postfix-1.1.11-20020613/src/smtp/smtp_unalias.c
---- postfix-1.1.11-20020613-orig/src/smtp/smtp_unalias.c Thu Sep 28 19:06:09 2000
-+++ postfix-1.1.11-20020613/src/smtp/smtp_unalias.c Wed Jun 26 15:26:48 2002
-@@ -86,7 +86,11 @@
- if ((result = htable_find(cache, name)) == 0) {
- fqdn = vstring_alloc(10);
- if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0,
-- fqdn, (VSTRING *) 0, T_MX, T_A, 0) != DNS_OK)
-+ fqdn, (VSTRING *) 0, T_MX, T_A,
-+#ifdef INET6
-+ T_AAAA,
-+#endif
-+ 0) != DNS_OK)
- vstring_strcpy(fqdn, name);
- htable_enter(cache, name, result = vstring_export(fqdn));
- }
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/Makefile.in postfix-1.1.11-20020613/src/smtpd/Makefile.in
---- postfix-1.1.11-20020613-orig/src/smtpd/Makefile.in Tue Jun 11 03:13:44 2002
-+++ postfix-1.1.11-20020613/src/smtpd/Makefile.in Wed Jun 26 15:26:48 2002
-@@ -134,6 +134,7 @@
- smtpd.o: ../../include/quote_flags.h
- smtpd.o: ../../include/lex_822.h
- smtpd.o: ../../include/mail_server.h
-+smtpd.o: ../../include/pfixtls.h
- smtpd.o: smtpd_token.h
- smtpd.o: smtpd.h
- smtpd.o: smtpd_check.h
-@@ -162,6 +163,7 @@
- smtpd_chat.o: ../../include/cleanup_user.h
- smtpd_chat.o: ../../include/mail_error.h
- smtpd_chat.o: ../../include/name_mask.h
-+smtpd_chat.o: ../../include/pfixtls.h
- smtpd_chat.o: smtpd.h
- smtpd_chat.o: ../../include/mail_stream.h
- smtpd_chat.o: smtpd_chat.h
-@@ -197,6 +199,7 @@
- smtpd_check.o: ../../include/mail_addr_find.h
- smtpd_check.o: ../../include/match_parent_style.h
- smtpd_check.o: ../../include/strip_addr.h
-+smtpd_check.o: ../../include/pfixtls.h
- smtpd_check.o: smtpd.h
- smtpd_check.o: ../../include/mail_stream.h
- smtpd_check.o: smtpd_sasl_glue.h
-@@ -213,6 +216,7 @@
- smtpd_peer.o: ../../include/vstream.h
- smtpd_peer.o: ../../include/argv.h
- smtpd_peer.o: ../../include/mail_stream.h
-+smtpd_peer.o: ../../include/pfixtls.h
- smtpd_sasl_glue.o: smtpd_sasl_glue.c
- smtpd_sasl_glue.o: ../../include/sys_defs.h
- smtpd_sasl_glue.o: ../../include/msg.h
-@@ -266,6 +270,7 @@
- smtpd_state.o: ../../include/vstring.h
- smtpd_state.o: ../../include/argv.h
- smtpd_state.o: ../../include/mail_stream.h
-+smtpd_state.o: ../../include/pfixtls.h
- smtpd_state.o: smtpd_chat.h
- smtpd_state.o: smtpd_sasl_glue.h
- smtpd_token.o: smtpd_token.c
-@@ -275,3 +280,4 @@
- smtpd_token.o: smtpd_token.h
- smtpd_token.o: ../../include/vstring.h
- smtpd_token.o: ../../include/vbuf.h
-+smtpd_token.o: ../../include/pfixtls.h
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd.c postfix-1.1.11-20020613/src/smtpd/smtpd.c
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd.c Tue May 28 19:08:56 2002
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd.c Wed Jun 26 15:26:48 2002
-@@ -314,6 +314,7 @@
- #include <string_list.h>
- #include <quote_822_local.h>
- #include <lex_822.h>
-+#include <pfixtls.h>
-
- /* Single-threaded server skeleton. */
-
-@@ -338,6 +339,7 @@
- */
- int var_smtpd_rcpt_limit;
- int var_smtpd_tmout;
-+char *var_relay_ccerts;
- int var_smtpd_soft_erlim;
- int var_smtpd_hard_erlim;
- int var_queue_minfree; /* XXX use off_t */
-@@ -385,6 +387,15 @@
- char *var_smtpd_noop_cmds;
- char *var_smtpd_null_key;
- int var_smtpd_hist_thrsh;
-+int var_smtpd_starttls_tmout;
-+int var_smtpd_tls_wrappermode;
-+int var_smtpd_use_tls;
-+int var_smtpd_enforce_tls;
-+int var_smtpd_tls_auth_only;
-+int var_smtpd_tls_ask_ccert;
-+int var_smtpd_tls_req_ccert;
-+int var_smtpd_tls_ccert_vd;
-+int var_smtpd_tls_received_header;
-
- /*
- * Silly little macros.
-@@ -489,11 +500,21 @@
- if (var_disable_vrfy_cmd == 0)
- smtpd_chat_reply(state, "250-VRFY");
- smtpd_chat_reply(state, "250-ETRN");
-+#ifdef HAS_SSL
-+ if ((state->tls_use_tls || state->tls_enforce_tls) && (!state->tls_active))
-+ smtpd_chat_reply(state, "250-STARTTLS");
-+#endif
- #ifdef USE_SASL_AUTH
- if (var_smtpd_sasl_enable) {
-+#ifdef HAS_SSL
-+ if (!state->tls_auth_only || state->tls_active) {
-+#endif
- smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list);
- if (var_broken_auth_clients)
- smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
-+#ifdef HAS_SSL
-+ }
-+#endif
- }
- #endif
- smtpd_chat_reply(state, "250-%s", VERP_CMD);
-@@ -918,11 +939,76 @@
- state->rcpt_count = 0;
- }
-
-+/* CN_sanitize - make sure, the CN-string is well behaved */
-+
-+static void CN_sanitize(char *CNstring)
-+{
-+ int i;
-+ int len;
-+ int parencount;
-+
-+ /*
-+ * The information included in the CN (CommonName) of the peer and its
-+ * issuer can be included into the Received: header line. The characters
-+ * allowed as well as comment nesting are limited by RFC822.
-+ */
-+
-+ len = strlen(CNstring);
-+ /*
-+ * The Received: header can only contain characters. Make sure that only
-+ * acceptable characters are printed. Maybe we could allow more, but
-+ * not everything makes sense inside a CommonName.
-+ */
-+ for (i = 0; i < len; i++)
-+ if (!((CNstring[i] >= 'A') && (CNstring[i] <='Z')) &&
-+ !((CNstring[i] >= 'a') && (CNstring[i] <='z')) &&
-+ !((CNstring[i] >= '0') && (CNstring[i] <='9')) &&
-+ (CNstring[i] != '(') && (CNstring[i] != ')') &&
-+ (CNstring[i] != '[') && (CNstring[i] != ']') &&
-+ (CNstring[i] != '{') && (CNstring[i] != '}') &&
-+ (CNstring[i] != '<') && (CNstring[i] != '>') &&
-+ (CNstring[i] != '?') && (CNstring[i] != '!') &&
-+ (CNstring[i] != ';') && (CNstring[i] != ':') &&
-+ (CNstring[i] != '"') && (CNstring[i] != '\'') &&
-+ (CNstring[i] != '/') && (CNstring[i] != '|') &&
-+ (CNstring[i] != '+') && (CNstring[i] != '&') &&
-+ (CNstring[i] != '~') && (CNstring[i] != '@') &&
-+ (CNstring[i] != '#') && (CNstring[i] != '$') &&
-+ (CNstring[i] != '%') && (CNstring[i] != '&') &&
-+ (CNstring[i] != '^') && (CNstring[i] != '*') &&
-+ (CNstring[i] != '_') && (CNstring[i] != '-') &&
-+ (CNstring[i] != '.') && (CNstring[i] != ' '))
-+ CNstring[i] = '?';
-+
-+ /*
-+ * This information will go into the Received: header inside a comment.
-+ * Since comments can be nested, parentheses '(' and ')' must match.
-+ */
-+ parencount = 0;
-+ for (i = 0; i < len; i++) {
-+ if (CNstring[i] == '(')
-+ parencount++;
-+ else if (CNstring[i] == ')')
-+ parencount--;
-+ }
-+ /*
-+ * The necessary condition is violated. Do YOU know, where to correct?
-+ * I don't know, so I will practically remove all parentheses.
-+ */
-+ if (parencount != 0) {
-+ for (i = 0; i < len; i++)
-+ if ((CNstring[i] == '(') || (CNstring[i] == ')'))
-+ CNstring[i] = '/';
-+ }
-+}
-+
- /* data_cmd - process DATA command */
-
- static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
- {
- char *start;
-+ char *peer_CN;
-+ char *issuer_CN;
- int len;
- int curr_rec_type;
- int prev_rec_type;
-@@ -961,6 +1047,35 @@
- "Received: from %s (%s [%s])",
- state->helo_name ? state->helo_name : state->name,
- state->name, state->addr);
-+ if (var_smtpd_tls_received_header && state->tls_active) {
-+ rec_fprintf(state->cleanup, 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);
-+ if (state->tls_info.peer_CN) {
-+ peer_CN = mystrdup(state->tls_info.peer_CN);
-+ CN_sanitize(peer_CN);
-+ issuer_CN = mystrdup(state->tls_info.issuer_CN);
-+ CN_sanitize(issuer_CN);
-+ if (state->tls_info.peer_verified)
-+ rec_fprintf(state->cleanup, REC_TYPE_NORM,
-+ "\t(Client CN \"%s\", Issuer \"%s\" (verified OK))",
-+ peer_CN, issuer_CN);
-+ else
-+ rec_fprintf(state->cleanup, REC_TYPE_NORM,
-+ "\t(Client CN \"%s\", Issuer \"%s\" (not verified))",
-+ peer_CN, issuer_CN);
-+ myfree(issuer_CN);
-+ myfree(peer_CN);
-+ }
-+ else if (var_smtpd_tls_ask_ccert)
-+ rec_fprintf(state->cleanup, REC_TYPE_NORM,
-+ "\t(Client did not present a certificate)");
-+ else
-+ rec_fprintf(state->cleanup, REC_TYPE_NORM,
-+ "\t(No client certificate requested)");
-+ }
- if (state->rcpt_count == 1 && state->recipient) {
- rec_fprintf(state->cleanup, REC_TYPE_NORM,
- "\tby %s (%s) with %s id %s",
-@@ -1310,6 +1425,77 @@
- }
- }
-
-+static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
-+{
-+ char *err;
-+
-+#ifdef HAS_SSL
-+ if (argc != 1) {
-+ state->error_mask |= MAIL_ERROR_PROTOCOL;
-+ smtpd_chat_reply(state, "501 Syntax: STARTTLS");
-+ return (-1);
-+ }
-+ if (state->tls_active != 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 (!pfixtls_serverengine) {
-+ smtpd_chat_reply(state, "454 TLS not available due to temporary reason");
-+ return (0);
-+ }
-+ smtpd_chat_reply(state, "220 Ready to start TLS");
-+ vstream_fflush(state->client);
-+ /*
-+ * When deciding about continuing the handshake, we will stop when a
-+ * client certificate was _required_ and none was presented or the
-+ * verification failed. This however does only make sense when TLS is
-+ * enforced. Otherwise we would happily perform perform the SMTP
-+ * transaction without any STARTTLS at all! So only have the handshake
-+ * fail when TLS is also enforced.
-+ */
-+ if (pfixtls_start_servertls(state->client, var_smtpd_starttls_tmout,
-+ state->name, state->addr, &(state->tls_info),
-+ (var_smtpd_tls_req_ccert && state->tls_enforce_tls))) {
-+ /*
-+ * Typically the connection is hanging at this point, so
-+ * we should try to shut it down by force! Unfortunately this
-+ * problem is not addressed in postfix!
-+ */
-+ return (-1);
-+ }
-+ state->tls_active = 1;
-+ helo_reset(state);
-+ mail_reset(state);
-+ rcpt_reset(state);
-+ return (0);
-+#else
-+ state->error_mask |= MAIL_ERROR_PROTOCOL;
-+ smtpd_chat_reply(state, "502 Error: command not implemented");
-+ return (-1);
-+#endif
-+}
-+
-+static void tls_reset(SMTPD_STATE *state)
-+{
-+ int failure = 0;
-+
-+ if (state->reason && state->where && strcmp(state->where, SMTPD_AFTER_DOT))
-+ failure = 1;
-+#ifdef HAS_SSL
-+ vstream_fflush(state->client);
-+ if (state->tls_active)
-+ pfixtls_stop_servertls(state->client, var_smtpd_starttls_tmout,
-+ failure, &(state->tls_info));
-+#endif
-+ state->tls_active = 0;
-+}
-+
- /*
- * 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
-@@ -1328,6 +1514,10 @@
- "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
- "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
-
-+#ifdef HAS_SSL
-+ "STARTTLS", starttls_cmd, 0,
-+#endif
-+
- #ifdef USE_SASL_AUTH
- "AUTH", smtpd_sasl_auth_cmd, 0,
- #endif
-@@ -1438,9 +1628,28 @@
- state->error_count++;
- continue;
- }
-+ if (state->tls_enforce_tls &&
-+ !state->tls_active &&
-+ cmdp->action != starttls_cmd &&
-+ cmdp->action != noop_cmd &&
-+ cmdp->action != ehlo_cmd &&
-+ cmdp->action != quit_cmd) {
-+ smtpd_chat_reply(state,
-+ "530 Must issue a STARTTLS command first");
-+ state->error_count++;
-+ continue;
-+ }
- state->where = cmdp->name;
-- if (cmdp->action(state, argc, argv) != 0)
-+ if (cmdp->action(state, argc, argv) != 0) {
- state->error_count++;
-+ /*
-+ * Die after TLS negotiation failure, as there is no
-+ * stable way to recover from a possible mixture of
-+ * TLS and SMTP protocol from the client.
-+ */
-+ if (cmdp->action == starttls_cmd)
-+ break;
-+ }
- if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT)
- && state->junk_cmds++ > var_smtpd_junk_cmd_limit)
- state->error_count++;
-@@ -1464,6 +1673,7 @@
- * Cleanup whatever information the client gave us during the SMTP
- * dialog.
- */
-+ tls_reset(state);
- helo_reset(state);
- #ifdef USE_SASL_AUTH
- if (var_smtpd_sasl_enable)
-@@ -1496,6 +1706,46 @@
- * machines.
- */
- smtpd_state_init(&state, stream);
-+#ifdef HAS_SSL
-+ if (SMTPD_STAND_ALONE((&state))) {
-+ state.tls_use_tls = 0;
-+ state.tls_enforce_tls = 0;
-+ state.tls_auth_only = 0;
-+ }
-+ 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_wrappermode) {
-+ /*
-+ * TLS has been set to wrapper mode, meaning that we run on a
-+ * seperate port and we must switch to TLS layer before actually
-+ * performing the SMTP protocol. This implies enforce-mode.
-+ */
-+ state.tls_use_tls = state.tls_enforce_tls = 1;
-+ if (pfixtls_start_servertls(state.client, var_smtpd_starttls_tmout,
-+ state.name, state.addr, &state.tls_info,
-+ var_smtpd_tls_req_ccert)) {
-+ /*
-+ * Typically the connection is hanging at this point, so
-+ * we should try to shut it down by force! Unfortunately this
-+ * problem is not addressed in postfix!
-+ */
-+ return;
-+ }
-+ state.tls_active = 1;
-+ }
-+ if (var_smtpd_tls_auth_only || state.tls_enforce_tls)
-+ state.tls_auth_only = 1;
-+ }
-+#else
-+ state.tls_use_tls = 0;
-+ state.tls_enforce_tls = 0;
-+ state.tls_auth_only = 0;
-+#endif
-+
-+ /*
-+ * Provide the SMTP service.
-+ */
-
- /*
- * See if we need to turn on verbose logging for this client.
-@@ -1513,10 +1763,6 @@
- smtpd_chat_reply(&state, "220 %s", var_smtpd_banner);
- msg_info("connect from %s[%s]", state.name, state.addr);
- }
--
-- /*
-- * Provide the SMTP service.
-- */
- smtpd_proto(&state);
-
- /*
-@@ -1542,7 +1788,6 @@
-
- static void pre_jail_init(char *unused_name, char **unused_argv)
- {
--
- /*
- * Initialize blacklist/etc. patterns before entering the chroot jail, in
- * case they specify a filename pattern.
-@@ -1558,6 +1803,12 @@
- msg_warn("%s is true, but SASL support is not compiled in",
- VAR_SMTPD_SASL_ENABLE);
- #endif
-+
-+#ifdef HAS_SSL
-+ if (var_smtpd_use_tls || var_smtpd_enforce_tls || var_smtpd_tls_wrappermode)
-+ pfixtls_init_serverengine(var_smtpd_tls_ccert_vd,
-+ var_smtpd_tls_ask_ccert);
-+#endif
- }
-
- /* main - the main program */
-@@ -1580,6 +1831,7 @@
- VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0,
- VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
- VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0,
-+ VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
- 0,
- };
- static CONFIG_TIME_TABLE time_table[] = {
-@@ -1595,6 +1847,13 @@
- VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
- VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable,
- VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients,
-+ VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode,
-+ 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_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,
- 0,
- };
- static CONFIG_STR_TABLE str_table[] = {
-@@ -1623,6 +1882,7 @@
- VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0,
- VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0,
- VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0,
-+ VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_relay_ccerts, 0, 0,
- 0,
- };
-
-@@ -1638,3 +1898,4 @@
- MAIL_SERVER_PRE_ACCEPT, pre_accept,
- 0);
- }
-+
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd.h postfix-1.1.11-20020613/src/smtpd/smtpd.h
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd.h Fri Mar 29 22:10:13 2002
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd.h Wed Jun 26 15:26:48 2002
-@@ -32,6 +32,7 @@
- * Global library.
- */
- #include <mail_stream.h>
-+#include <pfixtls.h>
-
- /*
- * Variables that keep track of conversation state. There is only one SMTP
-@@ -81,6 +82,11 @@
- VSTRING *sasl_decoded;
- #endif
- int warn_if_reject;
-+ int tls_active;
-+ int tls_use_tls;
-+ int tls_enforce_tls;
-+ int tls_auth_only;
-+ tls_info_t tls_info;
- } SMTPD_STATE;
-
- extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd_check.c postfix-1.1.11-20020613/src/smtpd/smtpd_check.c
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd_check.c Mon Jun 10 22:14:39 2002
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd_check.c Wed Jun 26 15:26:48 2002
-@@ -280,6 +280,7 @@
-
- #include <namadr_list.h>
- #include <domain_list.h>
-+#include <string_list.h>
- #include <mail_params.h>
- #include <canon_addr.h>
- #include <resolve_clnt.h>
-@@ -345,6 +346,9 @@
- static DOMAIN_LIST *relay_domains;
- static NAMADR_LIST *mynetworks;
- static NAMADR_LIST *perm_mx_networks;
-+#ifdef HAS_SSL
-+static MAPS *relay_ccerts;
-+#endif
-
- /*
- * How to do parent domain wildcard matching, if any.
-@@ -530,6 +534,10 @@
- perm_mx_networks =
- namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
- var_perm_mx_networks);
-+#ifdef HAS_SSL
-+ relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_relay_ccerts,
-+ DICT_FLAG_LOCK);
-+#endif
-
- /*
- * Pre-parse and pre-open the recipient maps.
-@@ -932,7 +940,11 @@
- msg_info("%s: %s", myname, name);
-
- dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-- (VSTRING *) 0, T_A, T_MX, 0);
-+ (VSTRING *) 0, T_A, T_MX,
-+#ifdef INET6
-+ T_AAAA,
-+#endif
-+ 0);
- if (dns_status != DNS_OK)
- return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- "%d <%s>: %s rejected: Host not found",
-@@ -954,7 +966,11 @@
- msg_info("%s: %s", myname, name);
-
- dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-- (VSTRING *) 0, T_A, T_MX, 0);
-+ (VSTRING *) 0, T_A, T_MX,
-+#ifdef INET6
-+ T_AAAA,
-+#endif
-+ 0);
- if (dns_status != DNS_OK)
- return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
- "%d <%s>: %s rejected: Domain not found",
-@@ -966,6 +982,36 @@
-
- static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
-
-+/* permit_tls_clientcerts - OK/DUNNO for message relaying */
-+
-+#ifdef HAS_SSL
-+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,
-@@ -1145,6 +1191,49 @@
-
- static int has_my_addr(const char *host)
- {
-+#ifdef INET6
-+ char *myname = "has_my_addr";
-+ struct addrinfo hints, *res, *res0;
-+ int error;
-+ char hbuf[NI_MAXHOST];
-+
-+ if (msg_verbose)
-+ msg_info("%s: host %s", myname, host);
-+
-+ /*
-+ * If we can't lookup the host, play safe and assume it is OK.
-+ */
-+#define YUP 1
-+#define NOPE 0
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ error = getaddrinfo(host, NULL, &hints, &res0);
-+ if (error) {
-+ if (msg_verbose)
-+ msg_info("%s: host %s: %s", myname, host, gai_strerror(error));
-+ return (YUP);
-+ }
-+ for (res = res0; res; res = res->ai_next) {
-+ if (msg_verbose) {
-+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST)) {
-+ strncpy(hbuf, "???", sizeof(hbuf));
-+ }
-+ msg_info("%s: addr %s", myname, hbuf);
-+ }
-+ if (own_inet_addr(res->ai_addr)) {
-+ freeaddrinfo(res0);
-+ return (YUP);
-+ }
-+ }
-+ freeaddrinfo(res0);
-+ if (msg_verbose)
-+ msg_info("%s: host %s: no match", myname, host);
-+
-+ return (NOPE);
-+#else
- char *myname = "has_my_addr";
- struct in_addr addr;
- char **cpp;
-@@ -1180,6 +1269,7 @@
- msg_info("%s: host %s: no match", myname, host);
-
- return (NOPE);
-+#endif
- }
-
- /* i_am_mx - is this machine listed as MX relay */
-@@ -1834,7 +1924,7 @@
- static int reject_maps_rbl(SMTPD_STATE *state)
- {
- char *myname = "reject_maps_rbl";
-- ARGV *octets = argv_split(state->addr, ".");
-+ ARGV *octets;
- VSTRING *query = vstring_alloc(100);
- char *saved_domains = mystrdup(var_maps_rbl_domains);
- char *bp = saved_domains;
-@@ -1846,17 +1936,29 @@
- int dns_status = DNS_FAIL;
- int i;
- int result;
-+ struct in_addr a;
- VSTRING *why;
-
- if (msg_verbose)
- msg_info("%s: %s", myname, state->addr);
-
-- /*
-- * IPv4 only for now
-- */
--#ifdef INET6
-+#ifndef INET6
-+ /* IPv4 only for now */
- if (inet_pton(AF_INET, state->addr, &a) != 1)
- return SMTPD_CHECK_DUNNO;
-+ octets = argv_split(state->addr, ".");
-+#else
-+ /* IPv4 and IPv6-mapped IPv4 only for now */
-+ if (inet_pton(AF_INET, state->addr, &a) == 1)
-+ octets = argv_split(state->addr, ".");
-+ else {
-+ struct in6_addr a6;
-+ if (inet_pton(AF_INET6, state->addr, &a6) != 1)
-+ return SMTPD_CHECK_DUNNO;
-+ if (!IN6_IS_ADDR_V4MAPPED(&a6) || (strrchr(state->addr,':') == NULL))
-+ return SMTPD_CHECK_DUNNO;
-+ octets = argv_split(strrchr(state->addr,':')+1, ".");
-+ }
- #endif
-
- /*
-@@ -2154,6 +2256,12 @@
- #else
- msg_warn("restriction `%s' ignored: no SASL support", name);
- #endif
-+#ifdef HAS_SSL
-+ } 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)
- status = reject_unknown_address(state, state->recipient,
-@@ -2588,6 +2696,7 @@
- char *var_rcpt_checks = "";
- char *var_etrn_checks = "";
- char *var_relay_domains = "";
-+char *var_relay_ccerts = "";
- char *var_mynetworks = "";
- char *var_notify_classes = "";
-
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd_peer.c postfix-1.1.11-20020613/src/smtpd/smtpd_peer.c
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd_peer.c Thu Jul 5 22:09:47 2001
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd_peer.c Wed Jun 26 15:26:48 2002
-@@ -63,6 +63,15 @@
- #include <netdb.h>
- #include <string.h>
-
-+/* Utility library. */
-+
-+#include <msg.h>
-+#include <mymalloc.h>
-+#include <valid_hostname.h>
-+#include <stringops.h>
-+
-+/* Global library. */
-+
- /*
- * Older systems don't have h_errno. Even modern systems don't have
- * hstrerror().
-@@ -84,16 +93,11 @@
- )
- #endif
-
--/* Utility library. */
--
--#include <msg.h>
--#include <mymalloc.h>
--#include <valid_hostname.h>
--#include <stringops.h>
--
--/* Global library. */
--
--
-+#ifdef INET6
-+#define GAI_STRERROR(error) \
-+ ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
-+#endif
-+
- /* Application-specific. */
-
- #include "smtpd.h"
-@@ -102,16 +106,23 @@
-
- void smtpd_peer_init(SMTPD_STATE *state)
- {
-- struct sockaddr_in sin;
-- SOCKADDR_SIZE len = sizeof(sin);
-+#ifdef INET6
-+ struct sockaddr_storage ss;
-+#else
-+ struct sockaddr ss;
-+ struct in_addr *in;
- struct hostent *hp;
-- int i;
-+#endif
-+ struct sockaddr *sa;
-+ SOCKADDR_SIZE len;
-+
-+ sa = (struct sockaddr *)&ss;
-+ len = sizeof(ss);
-
- /*
- * Look up the peer address information.
- */
-- if (getpeername(vstream_fileno(state->client),
-- (struct sockaddr *) & sin, &len) >= 0) {
-+ if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
- errno = 0;
- }
-
-@@ -127,18 +138,51 @@
- /*
- * Look up and "verify" the client hostname.
- */
-- else if (errno == 0 && sin.sin_family == AF_INET) {
-- state->addr = mystrdup(inet_ntoa(sin.sin_addr));
-- hp = gethostbyaddr((char *) &(sin.sin_addr),
-- sizeof(sin.sin_addr), AF_INET);
-- if (hp == 0) {
-+ else if (errno == 0 && (sa->sa_family == AF_INET
-+#ifdef INET6
-+ || sa->sa_family == AF_INET6
-+#endif
-+ )) {
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ char abuf[NI_MAXHOST];
-+ struct addrinfo hints, *rnull = NULL;
-+#else
-+ char abuf[sizeof("255.255.255.255") + 1];
-+ char *hbuf;
-+#endif
-+ int error = -1;
-+
-+#ifdef INET6
-+ (void)getnameinfo(sa, len, abuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
-+#else
-+ in = &((struct sockaddr_in *)sa)->sin_addr;
-+ inet_ntop(AF_INET, in, abuf, sizeof(hbuf));
-+#endif
-+ state->addr = mystrdup(abuf);
-+#ifdef INET6
-+ error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
-+#else
-+ hbuf = NULL;
-+ hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
-+ if (hp) {
-+ error = 0;
-+ hbuf = mystrdup(hp->h_name);
-+ } else
-+ error = 1;
-+#endif
-+ if (error) {
- state->name = mystrdup("unknown");
-+#ifdef INET6
-+ state->peer_code = (error == EAI_AGAIN ? 4 : 5);
-+#else
- state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
-- } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-+#endif
-+ } else if (!valid_hostname(hbuf, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- state->peer_code = 5;
- } else {
-- state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
-+ state->name = mystrdup(hbuf); /* hp->name is clobbered!! */
- state->peer_code = 2;
-
- /*
-@@ -150,16 +194,31 @@
- state->peer_code = code; \
- }
-
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = AF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ error = getaddrinfo(state->name, NULL, &hints, &rnull);
-+ if (error) {
-+ msg_warn("%s: hostname %s verification failed: %s",
-+ state->addr, state->name, GAI_STRERROR(error));
-+ REJECT_PEER_NAME(state, (error == EAI_AGAIN ? 4 : 5));
-+ }
-+ /* memcmp() isn't needed if we use getaddrinfo */
-+ if (rnull)
-+ freeaddrinfo(rnull);
-+#else
- hp = gethostbyname(state->name); /* clobbers hp->name!! */
- if (hp == 0) {
- msg_warn("%s: hostname %s verification failed: %s",
- state->addr, state->name, HSTRERROR(h_errno));
- REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
-- } else if (hp->h_length != sizeof(sin.sin_addr)) {
-+ } else if (hp->h_length != sizeof(*in)) {
- msg_warn("%s: hostname %s verification failed: bad address size %d",
- state->addr, state->name, hp->h_length);
- REJECT_PEER_NAME(state, 5);
- } else {
-+ int i;
- for (i = 0; /* void */ ; i++) {
- if (hp->h_addr_list[i] == 0) {
- msg_warn("%s: address not listed for hostname %s",
-@@ -167,12 +226,11 @@
- REJECT_PEER_NAME(state, 5);
- break;
- }
-- if (memcmp(hp->h_addr_list[i],
-- (char *) &sin.sin_addr,
-- sizeof(sin.sin_addr)) == 0)
-+ if (memcmp(hp->h_addr_list[i], (char *)in, sizeof(*in)) == 0)
- break; /* keep peer name */
- }
- }
-+#endif
- }
- }
-
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd_sasl_proto.c postfix-1.1.11-20020613/src/smtpd/smtpd_sasl_proto.c
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd_sasl_proto.c Tue Sep 12 00:45:40 2000
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd_sasl_proto.c Wed Jun 26 15:26:48 2002
-@@ -128,6 +128,13 @@
- smtpd_chat_reply(state, "503 Error: authentication not enabled");
- return (-1);
- }
-+#ifdef HAS_SSL
-+ if (state->tls_auth_only && !state->tls_active) {
-+ 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");
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpd/smtpd_state.c postfix-1.1.11-20020613/src/smtpd/smtpd_state.c
---- postfix-1.1.11-20020613-orig/src/smtpd/smtpd_state.c Tue Nov 6 18:35:40 2001
-+++ postfix-1.1.11-20020613/src/smtpd/smtpd_state.c Wed Jun 26 15:26:48 2002
-@@ -92,6 +92,11 @@
- state->msg_size = 0;
- state->junk_cmds = 0;
- state->warn_if_reject = 0;
-+ state->tls_active = 0;
-+ state->tls_use_tls = 0;
-+ state->tls_enforce_tls = 0;
-+ state->tls_info = tls_info_zero;
-+ state->tls_auth_only = 0;
-
- #ifdef USE_SASL_AUTH
- if (SMTPD_STAND_ALONE(state))
-diff -Pur postfix-1.1.11-20020613-orig/src/smtpstone/smtp-sink.c postfix-1.1.11-20020613/src/smtpstone/smtp-sink.c
---- postfix-1.1.11-20020613-orig/src/smtpstone/smtp-sink.c Sat Jun 8 20:21:41 2002
-+++ postfix-1.1.11-20020613/src/smtpstone/smtp-sink.c Wed Jun 26 15:26:48 2002
-@@ -518,7 +518,7 @@
- } else {
- if (strncmp(argv[optind], "inet:", 5) == 0)
- argv[optind] += 5;
-- sock = inet_listen(argv[optind], backlog, BLOCKING);
-+ sock = inet_listen(argv[optind], backlog, BLOCKING, 1);
- }
-
- /*
-diff -Pur postfix-1.1.11-20020613-orig/src/tlsmgr/Makefile.in postfix-1.1.11-20020613/src/tlsmgr/Makefile.in
---- postfix-1.1.11-20020613-orig/src/tlsmgr/Makefile.in Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/tlsmgr/Makefile.in Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,75 @@
-+SHELL = /bin/sh
-+SRCS = tlsmgr.c
-+OBJS = tlsmgr.o
-+HDRS =
-+TESTSRC =
-+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
-+ -Wunused
-+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
-+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
-+TESTPROG=
-+PROG = tlsmgr
-+INC_DIR = ../../include
-+LIBS = ../../lib/libmaster.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
-+ 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 | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
-+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
-+ done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
-+ @make -f Makefile.in Makefile
-+
-+# 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/vstream.h
-+tlsmgr.o: ../../include/vbuf.h
-+tlsmgr.o: ../../include/dict.h
-+tlsmgr.o: ../../include/argv.h
-+tlsmgr.o: ../../include/vstring.h
-+tlsmgr.o: ../../include/stringops.h
-+tlsmgr.o: ../../include/mymalloc.h
-+tlsmgr.o: ../../include/connect.h
-+tlsmgr.o: ../../include/myflock.h
-+tlsmgr.o: ../../include/mail_conf.h
-+tlsmgr.o: ../../include/mail_params.h
-+tlsmgr.o: ../../include/iostuff.h
-+tlsmgr.o: ../../include/master_proto.h
-+tlsmgr.o: ../../include/mail_server.h
-+tlsmgr.o: ../../include/pfixtls.h
-diff -Pur postfix-1.1.11-20020613-orig/src/tlsmgr/tlsmgr.c postfix-1.1.11-20020613/src/tlsmgr/tlsmgr.c
---- postfix-1.1.11-20020613-orig/src/tlsmgr/tlsmgr.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/tlsmgr/tlsmgr.c Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,598 @@
-+/*++
-+/* NAME
-+/* tlsmgr 8
-+/* SUMMARY
-+/* Postfix TLS session cache and PRNG handling manager
-+/* SYNOPSIS
-+/* \fBtlsmgr\fR [generic Postfix daemon options]
-+/* DESCRIPTION
-+/* The tlsmgr process does housekeeping on the session cache database
-+/* files. It runs through the databases and removes expired entries
-+/* and entries written by older (incompatible) versions.
-+/*
-+/* The tlsmgr is responsible for the PRNG handling. The used internal
-+/* OpenSSL PRNG has a pool size of 8192 bits (= 1024 bytes). The pool
-+/* is initially seeded at startup from an external source (EGD or
-+/* /dev/urandom) and additional seed is obtained later during program
-+/* run at a configurable period. The exact time of seed query is
-+/* using random information and is equally distributed in the range of
-+/* [0-\fBtls_random_reseed_period\fR] with a \fBtls_random_reseed_period\fR
-+/* having a default of 1 hour.
-+/*
-+/* Tlsmgr can be run chrooted and with dropped privileges, as it will
-+/* connect to the entropy source at startup.
-+/*
-+/* The PRNG is additionally seeded internally by the data found in the
-+/* session cache and timevalues.
-+/*
-+/* Tlsmgr reads the old value of the exchange file at startup to keep
-+/* entropy already collected during previous runs.
-+/*
-+/* From the PRNG random pool a cryptographically strong 1024 byte random
-+/* sequence is written into the PRNG exchange file. The file is updated
-+/* periodically with the time changing randomly from
-+/* [0-\fBtls_random_prng_update_period\fR].
-+/* STANDARDS
-+/* SECURITY
-+/* .ad
-+/* .fi
-+/* Tlsmgr is not security-sensitive. It only deals with external data
-+/* to be fed into the PRNG, the contents is never trusted. The session
-+/* cache housekeeping will only remove entries if expired and will never
-+/* touch the contents of the cached data.
-+/* DIAGNOSTICS
-+/* Problems and transactions are logged to the syslog daemon.
-+/* BUGS
-+/* There is no automatic means to limit the number of entries in the
-+/* session caches and/or the size of the session cache files.
-+/* CONFIGURATION PARAMETERS
-+/* .ad
-+/* .fi
-+/* The following \fBmain.cf\fR parameters are especially relevant to
-+/* this program. See the Postfix \fBmain.cf\fR file for syntax details
-+/* and for default values. Use the \fBpostfix reload\fR command after
-+/* a configuration change.
-+/* .SH Session Cache
-+/* .ad
-+/* .fi
-+/* .IP \fBsmtpd_tls_session_cache_database\fR
-+/* Name of the SDBM file (type sdbm:) containing the SMTP server session
-+/* cache. If the file does not exist, it is created.
-+/* .IP \fBsmtpd_tls_session_cache_timeout\fR
-+/* Expiry time of SMTP server session cache entries in seconds. Entries
-+/* older than this are removed from the session cache. A cleanup-run is
-+/* performed periodically every \fBsmtpd_tls_session_cache_timeout\fR
-+/* seconds. Default is 3600 (= 1 hour).
-+/* .IP \fBsmtp_tls_session_cache_database\fR
-+/* Name of the SDBM file (type sdbm:) containing the SMTP client session
-+/* cache. If the file does not exist, it is created.
-+/* .IP \fBsmtp_tls_session_cache_timeout\fR
-+/* Expiry time of SMTP client session cache entries in seconds. Entries
-+/* older than this are removed from the session cache. A cleanup-run is
-+/* performed periodically every \fBsmtp_tls_session_cache_timeout\fR
-+/* seconds. Default is 3600 (= 1 hour).
-+/* .SH Pseudo Random Number Generator
-+/* .ad
-+/* .fi
-+/* .IP \fBtls_random_source\fR
-+/* Name of the EGD socket or device or regular file to obtain entropy
-+/* from. The type of entropy source must be specified by preceding the
-+/* name with the appropriate type: egd:/path/to/egd_socket,
-+/* dev:/path/to/devicefile, or /path/to/regular/file.
-+/* tlsmgr opens \fBtls_random_source\fR and tries to read
-+/* \fBtls_random_bytes\fR from it.
-+/* .IP \fBtls_random_bytes\fR
-+/* Number of bytes to be read from \fBtls_random_source\fR.
-+/* Default value is 32 bytes. If using EGD, a maximum of 255 bytes is read.
-+/* .IP \fBtls_random_exchange_name\fR
-+/* Name of the file written by tlsmgr and read by smtp and smtpd at
-+/* startup. The length is 1024 bytes. Default value is
-+/* /etc/postfix/prng_exch.
-+/* .IP \fBtls_random_reseed_period\fR
-+/* Time in seconds until the next reseed from external sources is due.
-+/* This is the maximum value. The actual point in time is calculated
-+/* with a random factor equally distributed between 0 and this maximum
-+/* value. Default is 3600 (= 60 minutes).
-+/* .IP \fBtls_random_prng_update_period\fR
-+/* Time in seconds until the PRNG exchange file is updated with new
-+/* pseude random values. This is the maximum value. The actual point
-+/* in time is calculated with a random factor equally distributed
-+/* between 0 and this maximum value. Default is 60 (= 1 minute).
-+/* SEE ALSO
-+/* smtp(8) SMTP client
-+/* smtpd(8) SMTP server
-+/* LICENSE
-+/* .ad
-+/* .fi
-+/* The Secure Mailer license must be distributed with this software.
-+/* AUTHOR(S)
-+/*--*/
-+
-+/* System library. */
-+
-+#include <sys_defs.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <ctype.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <sys/time.h> /* gettimeofday, not POSIX */
-+
-+/* OpenSSL library. */
-+#ifdef HAS_SSL
-+#include <openssl/rand.h> /* For the PRNG */
-+#endif
-+
-+/* Utility library. */
-+
-+#include <msg.h>
-+#include <events.h>
-+#include <dict.h>
-+#include <stringops.h>
-+#include <mymalloc.h>
-+#include <connect.h>
-+#include <myflock.h>
-+
-+/* Global library. */
-+
-+#include <mail_conf.h>
-+#include <mail_params.h>
-+#include <pfixtls.h>
-+
-+/* Master process interface */
-+
-+#include <master_proto.h>
-+#include <mail_server.h>
-+
-+/* Application-specific. */
-+
-+ /*
-+ * Tunables.
-+ */
-+char *var_tls_rand_source;
-+int var_tls_rand_bytes;
-+int var_tls_reseed_period;
-+int var_tls_prng_upd_period;
-+
-+static int rand_exch_fd;
-+static int rand_source_dev_fd = -1;
-+static int rand_source_socket_fd = -1;
-+static int srvr_scache_db_active;
-+static int clnt_scache_db_active;
-+static DICT *srvr_scache_db = NULL;
-+static DICT *clnt_scache_db = NULL;
-+
-+static void tlsmgr_prng_upd_event(int unused_event, char *dummy)
-+{
-+ struct timeval tv;
-+ unsigned char buffer[1024];
-+ int next_period;
-+
-+#ifdef HAS_SSL
-+ /*
-+ * It is time to update the PRNG exchange file. Since other processes might
-+ * have added entropy, we do this in a read_stir-back_write cycle.
-+ */
-+ GETTIMEOFDAY(&tv);
-+ RAND_seed(&tv, sizeof(struct timeval));
-+
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) != 0)
-+ msg_fatal("Could not lock random exchange file: %s",
-+ strerror(errno));
-+
-+ lseek(rand_exch_fd, 0, SEEK_SET);
-+ if (read(rand_exch_fd, buffer, 1024) < 0)
-+ msg_fatal("reading exchange file failed");
-+ RAND_seed(buffer, 1024);
-+
-+ RAND_bytes(buffer, 1024);
-+ lseek(rand_exch_fd, 0, SEEK_SET);
-+ if (write(rand_exch_fd, buffer, 1024) != 1024)
-+ msg_fatal("Writing exchange file failed");
-+
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) != 0)
-+ msg_fatal("Could not unlock random exchange file: %s",
-+ strerror(errno));
-+
-+ /*
-+ * Make prediction difficult for outsiders and calculate the time for the
-+ * next execution randomly.
-+ */
-+ next_period = (var_tls_prng_upd_period * buffer[0]) / 255;
-+ event_request_timer(tlsmgr_prng_upd_event, dummy, next_period);
-+#endif
-+}
-+
-+
-+static void tlsmgr_reseed_event(int unused_event, char *dummy)
-+{
-+ int egd_success;
-+ int next_period;
-+ int rand_bytes;
-+ char buffer[255];
-+ struct timeval tv;
-+ unsigned char randbyte;
-+
-+#ifdef HAS_SSL
-+ /*
-+ * It is time to reseed the PRNG.
-+ */
-+
-+ GETTIMEOFDAY(&tv);
-+ RAND_seed(&tv, sizeof(struct timeval));
-+ if (rand_source_dev_fd != -1) {
-+ rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
-+ if (rand_bytes > 0)
-+ RAND_seed(buffer, rand_bytes);
-+ else if (rand_bytes < 0) {
-+ msg_fatal("Read from entropy device %s failed",
-+ var_tls_rand_source);
-+ }
-+ } else if (rand_source_socket_fd != -1) {
-+ egd_success = 0;
-+ buffer[0] = 1;
-+ buffer[1] = var_tls_rand_bytes;
-+ if (write(rand_source_socket_fd, buffer, 2) != 2)
-+ msg_info("Could not talk to %s", var_tls_rand_source);
-+ else if (read(rand_source_socket_fd, buffer, 1) != 1)
-+ msg_info("Could not read info from %s", var_tls_rand_source);
-+ else {
-+ rand_bytes = buffer[0];
-+ if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
-+ msg_info("Could not read data from %s", var_tls_rand_source);
-+ else {
-+ egd_success = 1;
-+ RAND_seed(buffer, rand_bytes);
-+ }
-+ }
-+ if (!egd_success) {
-+ msg_info("Lost connection to EGD-device, exiting to reconnect.");
-+ exit(0);
-+ }
-+ } else if (*var_tls_rand_source) {
-+ rand_bytes = RAND_load_file(var_tls_rand_source, var_tls_rand_bytes);
-+ }
-+
-+ /*
-+ * 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) / 255;
-+ event_request_timer(tlsmgr_reseed_event, dummy, next_period);
-+#endif
-+}
-+
-+
-+static int tlsmgr_do_scache_check(DICT *scache_db, int scache_timeout,
-+ int start)
-+{
-+#ifdef HAS_SSL
-+ int func;
-+ int len;
-+ int n;
-+ int delete = 0;
-+ int result;
-+ struct timeval tv;
-+ const char *member;
-+ const char *value;
-+ char *member_copy;
-+ unsigned char nibble, *data;
-+ pfixtls_scache_info_t scache_info;
-+
-+ GETTIMEOFDAY(&tv);
-+ RAND_seed(&tv, sizeof(struct timeval));
-+
-+ /*
-+ * Run through the given dictionary and check the stored sessions.
-+ * If "start" is set to 1, a new run is initiated, otherwise the next
-+ * item is accessed. The state is internally kept in the DICT.
-+ */
-+ if (start)
-+ func = DICT_SEQ_FUN_FIRST;
-+ else
-+ func = DICT_SEQ_FUN_NEXT;
-+ result = dict_seq(scache_db, func, &member, &value);
-+
-+ if (result > 0)
-+ return 0; /* End of list reached */
-+ else if (result < 0)
-+ msg_fatal("Database fault, should already be caught.");
-+ else {
-+ member_copy = mystrdup(member);
-+ len = strlen(value);
-+ RAND_seed(value, len); /* Use it to increase entropy */
-+ if (len < 2 * sizeof(pfixtls_scache_info_t))
-+ delete = 1; /* Messed up, delete */
-+ else if (len > 2 * sizeof(pfixtls_scache_info_t))
-+ len = 2 * sizeof(pfixtls_scache_info_t);
-+ if (!delete) {
-+ data = (unsigned char *)(&scache_info);
-+ memset(data, 0, len / 2);
-+ for (n = 0; n < len; n++) {
-+ if ((value[n] >= '0') && (value[n] <= '9'))
-+ nibble = value[n] - '0';
-+ else
-+ nibble = value[n] - 'A' + 10;
-+ if (n % 2)
-+ data[n / 2] |= nibble;
-+ else
-+ data[n / 2] |= (nibble << 4);
-+ }
-+
-+ if ((scache_info.scache_db_version != scache_db_version) ||
-+ (scache_info.openssl_version != openssl_version) ||
-+ (scache_info.timestamp + scache_timeout < time(NULL)))
-+ delete = 1;
-+ }
-+ if (delete)
-+ result = dict_del(scache_db, member_copy);
-+ myfree(member_copy);
-+ }
-+
-+ if (delete && result)
-+ msg_info("Could not delete %s", member);
-+ return 1;
-+
-+#else
-+ return 0;
-+#endif
-+}
-+
-+static void tlsmgr_clnt_cache_run_event(int unused_event, char *dummy)
-+{
-+
-+ /*
-+ * This routine runs when it is time for another tls session cache scan.
-+ * Make sure this routine gets called again in the future.
-+ */
-+ clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db,
-+ var_smtp_tls_scache_timeout, 1);
-+ event_request_timer(tlsmgr_clnt_cache_run_event, dummy,
-+ var_smtp_tls_scache_timeout);
-+}
-+
-+
-+static void tlsmgr_srvr_cache_run_event(int unused_event, char *dummy)
-+{
-+
-+ /*
-+ * This routine runs when it is time for another tls session cache scan.
-+ * Make sure this routine gets called again in the future.
-+ */
-+ srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
-+ var_smtpd_tls_scache_timeout, 1);
-+ event_request_timer(tlsmgr_srvr_cache_run_event, dummy,
-+ var_smtpd_tls_scache_timeout);
-+}
-+
-+
-+static DICT *tlsmgr_cache_open(const char *dbname)
-+{
-+ DICT *retval;
-+ char *dbpagname;
-+ char *dbdirname;
-+
-+ /*
-+ * First, try to find out the real name of the database file, so that
-+ * it can be removed.
-+ */
-+ if (!strncmp(dbname, "sdbm:", 5)) {
-+ dbpagname = concatenate(dbname + 5, ".pag", NULL);
-+ REMOVE(dbpagname);
-+ myfree(dbpagname);
-+ dbdirname = concatenate(dbname + 5, ".dir", NULL);
-+ REMOVE(dbdirname);
-+ myfree(dbdirname);
-+ }
-+ else {
-+ msg_warn("Only type sdbm: supported: %s", dbname);
-+ return NULL;
-+ }
-+
-+ /*
-+ * Now open the dictionary. Do it with O_EXCL, so that we only open a
-+ * fresh file. If we cannot open it with a fresh file, then we won't
-+ * touch it.
-+ */
-+ retval = dict_open(dbname, O_RDWR | O_CREAT | O_EXCL,
-+ DICT_FLAG_DUP_REPLACE | DICT_FLAG_LOCK | DICT_FLAG_SYNC_UPDATE);
-+ if (!retval)
-+ msg_warn("Could not create dictionary %s", dbname);
-+ return retval;
-+}
-+
-+/* tlsmgr_trigger_event - respond to external trigger(s) */
-+
-+static void tlsmgr_trigger_event(char *buf, int len,
-+ char *unused_service, char **argv)
-+{
-+ /*
-+ * Sanity check. This service takes no command-line arguments.
-+ */
-+ if (argv[0])
-+ msg_fatal("unexpected command-line argument: %s", argv[0]);
-+
-+}
-+
-+/* tlsmgr_loop - queue manager main loop */
-+
-+static int tlsmgr_loop(char *unused_name, char **unused_argv)
-+{
-+ /*
-+ * This routine runs as part of the event handling loop, after the event
-+ * manager has delivered a timer or I/O event (including the completion
-+ * of a connection to a delivery process), or after it has waited for a
-+ * specified amount of time. The result value of qmgr_loop() specifies
-+ * how long the event manager should wait for the next event.
-+ */
-+#define DONT_WAIT 0
-+#define WAIT_FOR_EVENT (-1)
-+
-+ if (clnt_scache_db_active)
-+ clnt_scache_db_active = tlsmgr_do_scache_check(clnt_scache_db,
-+ var_smtp_tls_scache_timeout, 0);
-+ if (srvr_scache_db_active)
-+ srvr_scache_db_active = tlsmgr_do_scache_check(srvr_scache_db,
-+ var_smtpd_tls_scache_timeout, 0);
-+ if (clnt_scache_db_active || srvr_scache_db_active)
-+ return (DONT_WAIT);
-+ return (WAIT_FOR_EVENT);
-+}
-+
-+/* pre_accept - see if tables have changed */
-+
-+static void pre_accept(char *unused_name, char **unused_argv)
-+{
-+ if (dict_changed()) {
-+ msg_info("table has changed -- exiting");
-+ exit(0);
-+ }
-+}
-+
-+/* tlsmgr_pre_init - pre-jail initialization */
-+
-+static void tlsmgr_pre_init(char *unused_name, char **unused_argv)
-+{
-+ int rand_bytes;
-+ unsigned char buffer[255];
-+
-+#ifdef HAS_SSL
-+ /*
-+ * Access the external sources for random seed. We may not be able to
-+ * access them again if we are sent to chroot jail, so we must leave
-+ * dev: and egd: type sources open.
-+ */
-+ if (*var_tls_rand_source) {
-+ if (!strncmp(var_tls_rand_source, "dev:", 4)) {
-+ /*
-+ * Source is a random device
-+ */
-+ rand_source_dev_fd = open(var_tls_rand_source + 4, 0, 0);
-+ if (rand_source_dev_fd == -1)
-+ msg_fatal("Could not open entropy device %s",
-+ var_tls_rand_source);
-+ if (var_tls_rand_bytes > 255)
-+ var_tls_rand_bytes = 255;
-+ rand_bytes = read(rand_source_dev_fd, buffer, var_tls_rand_bytes);
-+ RAND_seed(buffer, rand_bytes);
-+ } else if (!strncmp(var_tls_rand_source, "egd:", 4)) {
-+ /*
-+ * Source is a EGD compatible socket
-+ */
-+ rand_source_socket_fd = unix_connect(var_tls_rand_source +4,
-+ BLOCKING, 10);
-+ if (rand_source_socket_fd == -1)
-+ msg_fatal("Could not connect to %s", var_tls_rand_source);
-+ if (var_tls_rand_bytes > 255)
-+ var_tls_rand_bytes = 255;
-+ buffer[0] = 1;
-+ buffer[1] = var_tls_rand_bytes;
-+ if (write(rand_source_socket_fd, buffer, 2) != 2)
-+ msg_fatal("Could not talk to %s", var_tls_rand_source);
-+ if (read(rand_source_socket_fd, buffer, 1) != 1)
-+ msg_fatal("Could not read info from %s", var_tls_rand_source);
-+ rand_bytes = buffer[0];
-+ if (read(rand_source_socket_fd, buffer, rand_bytes) != rand_bytes)
-+ msg_fatal("Could not read data from %s", var_tls_rand_source);
-+ RAND_seed(buffer, rand_bytes);
-+ } else {
-+ rand_bytes = RAND_load_file(var_tls_rand_source,
-+ var_tls_rand_bytes);
-+ }
-+ }
-+#endif
-+
-+ /*
-+ * Now open the PRNG exchange file
-+ */
-+ if (*var_tls_rand_exch_name) {
-+ rand_exch_fd = open(var_tls_rand_exch_name, O_RDWR | O_CREAT, 0600);
-+ }
-+
-+ /*
-+ * Finally, open the session cache files. Remove old files, if still there.
-+ * If we could not remove the old files, something is pretty wrong and we
-+ * won't touch it!!
-+ */
-+ if (*var_smtp_tls_scache_db)
-+ clnt_scache_db = tlsmgr_cache_open(var_smtp_tls_scache_db);
-+ if (*var_smtpd_tls_scache_db)
-+ srvr_scache_db = tlsmgr_cache_open(var_smtpd_tls_scache_db);
-+}
-+
-+/* qmgr_post_init - post-jail initialization */
-+
-+static void tlsmgr_post_init(char *unused_name, char **unused_argv)
-+{
-+ unsigned char buffer[1024];
-+
-+ /*
-+ * This routine runs after the skeleton code has entered the chroot jail.
-+ * 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;
-+
-+#ifdef HAS_SSL
-+ /*
-+ * Complete thie initialization by reading the additional seed from the
-+ * PRNG exchange file. Don't care how many bytes were actually read, just
-+ * seed buffer into the PRNG, regardless of its contents.
-+ */
-+ if (rand_exch_fd >= 0) {
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) == -1)
-+ msg_fatal("Could not lock random exchange file: %s",
-+ strerror(errno));
-+ read(rand_exch_fd, buffer, 1024);
-+ if (myflock(rand_exch_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) == -1)
-+ msg_fatal("Could not unlock random exchange file: %s",
-+ strerror(errno));
-+ RAND_seed(buffer, 1024);
-+ tlsmgr_prng_upd_event(0, (char *) 0);
-+ tlsmgr_reseed_event(0, (char *) 0);
-+ }
-+#endif
-+
-+ clnt_scache_db_active = 0;
-+ srvr_scache_db_active = 0;
-+ if (clnt_scache_db)
-+ tlsmgr_clnt_cache_run_event(0, (char *) 0);
-+ if (srvr_scache_db)
-+ tlsmgr_srvr_cache_run_event(0, (char *) 0);
-+}
-+
-+/* 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, 0, 0,
-+ VAR_TLS_PRNG_UPD_PERIOD, DEF_TLS_PRNG_UPD_PERIOD, &var_tls_prng_upd_period, 0, 0,
-+ 0,
-+ };
-+ static CONFIG_INT_TABLE int_table[] = {
-+ VAR_TLS_RAND_BYTES, DEF_TLS_RAND_BYTES, &var_tls_rand_bytes, 0, 0,
-+ 0,
-+ };
-+
-+ /*
-+ * Use the trigger service skeleton, because no-one else should be
-+ * monitoring our service port while this process runs, and because we do
-+ * not talk back to the client.
-+ */
-+ trigger_server_main(argc, argv, tlsmgr_trigger_event,
-+ 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_LOOP, tlsmgr_loop,
-+ MAIL_SERVER_PRE_ACCEPT, pre_accept,
-+ 0);
-+}
-diff -Pur postfix-1.1.11-20020613-orig/src/util/Makefile.in postfix-1.1.11-20020613/src/util/Makefile.in
---- postfix-1.1.11-20020613-orig/src/util/Makefile.in Tue Jun 11 03:12:45 2002
-+++ postfix-1.1.11-20020613/src/util/Makefile.in Wed Jun 26 15:26:48 2002
-@@ -8,7 +8,7 @@
- dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \
- environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \
- file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \
-- get_hostname.c hex_quote.c htable.c inet_addr_host.c \
-+ get_hostname.c get_port.c hex_quote.c htable.c inet_addr_host.c \
- inet_addr_list.c inet_addr_local.c inet_connect.c inet_listen.c \
- inet_trigger.c inet_util.c intv.c line_wrap.c lowercase.c \
- lstat_as.c mac_expand.c mac_parse.c make_dirs.c match_list.c \
-@@ -26,7 +26,7 @@
- unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \
- valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \
- vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \
-- write_wait.c strcasecmp.c nvtable.c
-+ write_wait.c strcasecmp.c nvtable.c dict_sdbm.c sdbm.c
- OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
- attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
- chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
-@@ -36,7 +36,7 @@
- dict_tcp.o dict_unix.o dir_forest.o doze.o duplex_pipe.o \
- environ.o events.o exec_command.o fifo_listen.o fifo_trigger.o \
- file_limit.o find_inet.o fsspace.o fullname.o get_domainname.o \
-- get_hostname.o hex_quote.o htable.o inet_addr_host.o \
-+ get_hostname.o get_port.o hex_quote.o htable.o inet_addr_host.o \
- inet_addr_list.o inet_addr_local.o inet_connect.o inet_listen.o \
- inet_trigger.o inet_util.o intv.o line_wrap.o lowercase.o \
- lstat_as.o mac_expand.o mac_parse.o make_dirs.o match_list.o \
-@@ -54,13 +54,13 @@
- unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \
- valid_hostname.o vbuf.o vbuf_print.o vstream.o vstream_popen.o \
- vstring.o vstring_vstream.o watchdog.o writable.o write_buf.o \
-- write_wait.o nvtable.o $(STRCASE)
-+ write_wait.o nvtable.o $(STRCASE) dict_sdbm.o sdbm.o
- HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
- connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
- dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
- dict_nisplus.h dict_pcre.h dict_regexp.h dict_static.h dict_tcp.h \
- dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \
-- fsspace.h fullname.h get_domainname.h get_hostname.h hex_quote.h \
-+ fsspace.h fullname.h get_domainname.h get_hostname.h get_port.h hex_quote.h \
- htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \
- inet_util.h intv.h iostuff.h line_wrap.h listen.h lstat_as.h \
- mac_expand.h mac_parse.h make_dirs.h match_list.h match_ops.h \
-@@ -72,7 +72,7 @@
- split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \
- timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
- vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
-- nvtable.h
-+ nvtable.h dict_sdbm.h sdbm.h
- TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
- stream_test.c dup2_pass_on_exec.c
- WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-@@ -591,6 +591,7 @@
- dict_open.o: dict_unix.h
- dict_open.o: dict_tcp.h
- dict_open.o: dict_dbm.h
-+dict_open.o: dict_sdbm.h
- dict_open.o: dict_db.h
- dict_open.o: dict_nis.h
- dict_open.o: dict_nisplus.h
-@@ -725,6 +726,7 @@
- get_domainname.o: mymalloc.h
- get_domainname.o: get_hostname.h
- get_domainname.o: get_domainname.h
-+get_port.o: sys_defs.h
- get_hostname.o: get_hostname.c
- get_hostname.o: sys_defs.h
- get_hostname.o: mymalloc.h
-@@ -841,6 +843,7 @@
- match_list.o: stringops.h
- match_list.o: argv.h
- match_list.o: dict.h
-+match_list.o: inet_util.h
- match_list.o: match_ops.h
- match_list.o: match_list.h
- match_ops.o: match_ops.c
-@@ -1225,3 +1228,9 @@
- write_wait.o: sys_defs.h
- write_wait.o: msg.h
- write_wait.o: iostuff.h
-+sdbm.o: sdbm.c
-+sdbm.o: sdbm.h
-+dict_sdbm.o: sdbm.h
-+dict_sdbm.o: dict_sdbm.c
-+dict_sdbm.o: dict_sdbm.h
-+dict_sdbm.o: sys_defs.h
-diff -Pur postfix-1.1.11-20020613-orig/src/util/dict_open.c postfix-1.1.11-20020613/src/util/dict_open.c
---- postfix-1.1.11-20020613-orig/src/util/dict_open.c Fri Dec 21 23:18:07 2001
-+++ postfix-1.1.11-20020613/src/util/dict_open.c Wed Jun 26 15:26:48 2002
-@@ -159,6 +159,7 @@
- #include <dict_env.h>
- #include <dict_unix.h>
- #include <dict_tcp.h>
-+#include <dict_sdbm.h>
- #include <dict_dbm.h>
- #include <dict_db.h>
- #include <dict_nis.h>
-@@ -187,6 +188,7 @@
- #if 0
- DICT_TYPE_TCP, dict_tcp_open,
- #endif
-+ "sdbm", dict_sdbm_open,
- #ifdef HAS_DBM
- DICT_TYPE_DBM, dict_dbm_open,
- #endif
-diff -Pur postfix-1.1.11-20020613-orig/src/util/dict_sdbm.c postfix-1.1.11-20020613/src/util/dict_sdbm.c
---- postfix-1.1.11-20020613-orig/src/util/dict_sdbm.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/dict_sdbm.c Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,408 @@
-+/*++
-+/* NAME
-+/* dict_sdbm 3
-+/* SUMMARY
-+/* dictionary manager interface to SDBM files
-+/* SYNOPSIS
-+/* #include <dict_sdbm.h>
-+/*
-+/* DICT *dict_sdbm_open(path, open_flags, dict_flags)
-+/* const char *name;
-+/* const char *path;
-+/* int open_flags;
-+/* int dict_flags;
-+/* DESCRIPTION
-+/* dict_sdbm_open() opens the named SDBM database and makes it available
-+/* via the generic interface described in dict_open(3).
-+/* DIAGNOSTICS
-+/* Fatal errors: cannot open file, file write error, out of memory.
-+/* SEE ALSO
-+/* dict(3) generic dictionary manager
-+/* sdbm(3) data base subroutines
-+/* 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
-+/*--*/
-+
-+#include "sys_defs.h"
-+
-+/* System library. */
-+
-+#include <sys/stat.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+/* Utility library. */
-+
-+#include "msg.h"
-+#include "mymalloc.h"
-+#include "htable.h"
-+#include "iostuff.h"
-+#include "vstring.h"
-+#include "myflock.h"
-+#include "stringops.h"
-+#include "dict.h"
-+#include "dict_sdbm.h"
-+#include "sdbm.h"
-+
-+/* Application-specific. */
-+
-+typedef struct {
-+ DICT dict; /* generic members */
-+ SDBM *dbm; /* open database */
-+ char *path; /* pathname */
-+} DICT_SDBM;
-+
-+/* dict_sdbm_lookup - find database entry */
-+
-+static const char *dict_sdbm_lookup(DICT *dict, const char *name)
-+{
-+ DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
-+ datum dbm_key;
-+ datum dbm_value;
-+ static VSTRING *buf;
-+ const char *result = 0;
-+
-+ dict_errno = 0;
-+
-+ /*
-+ * Acquire an exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
-+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
-+
-+ /*
-+ * See if this DBM file was written with one null byte appended to key
-+ * and value.
-+ */
-+ if (dict->flags & DICT_FLAG_TRY1NULL) {
-+ dbm_key.dptr = (void *) name;
-+ dbm_key.dsize = strlen(name) + 1;
-+ dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
-+ if (dbm_value.dptr != 0) {
-+ dict->flags &= ~DICT_FLAG_TRY0NULL;
-+ result = dbm_value.dptr;
-+ }
-+ }
-+
-+ /*
-+ * See if this DBM file was written with no null byte appended to key and
-+ * value.
-+ */
-+ if (result == 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
-+ dbm_key.dptr = (void *) name;
-+ dbm_key.dsize = strlen(name);
-+ dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
-+ if (dbm_value.dptr != 0) {
-+ if (buf == 0)
-+ buf = vstring_alloc(10);
-+ vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
-+ dict->flags &= ~DICT_FLAG_TRY1NULL;
-+ result = vstring_str(buf);
-+ }
-+ }
-+
-+ /*
-+ * Release the exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
-+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
-+
-+ return (result);
-+}
-+
-+/* dict_sdbm_update - add or update database entry */
-+
-+static void dict_sdbm_update(DICT *dict, const char *name, const char *value)
-+{
-+ DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
-+ datum dbm_key;
-+ datum dbm_value;
-+ int status;
-+
-+ dbm_key.dptr = (void *) name;
-+ dbm_value.dptr = (void *) value;
-+ dbm_key.dsize = strlen(name);
-+ dbm_value.dsize = strlen(value);
-+
-+ /*
-+ * If undecided about appending a null byte to key and value, choose a
-+ * default depending on the platform.
-+ */
-+ if ((dict->flags & DICT_FLAG_TRY1NULL)
-+ && (dict->flags & DICT_FLAG_TRY0NULL)) {
-+#ifdef DBM_NO_TRAILING_NULL
-+ dict->flags &= ~DICT_FLAG_TRY1NULL;
-+#else
-+ dict->flags &= ~DICT_FLAG_TRY0NULL;
-+#endif
-+ }
-+
-+ /*
-+ * Optionally append a null byte to key and value.
-+ */
-+ if (dict->flags & DICT_FLAG_TRY1NULL) {
-+ dbm_key.dsize++;
-+ dbm_value.dsize++;
-+ }
-+
-+ /*
-+ * Acquire an exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
-+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
-+
-+ /*
-+ * Do the update.
-+ */
-+ if ((status = sdbm_store(dict_sdbm->dbm, dbm_key, dbm_value,
-+ (dict->flags & DICT_FLAG_DUP_REPLACE) ? DBM_REPLACE : DBM_INSERT)) < 0)
-+ msg_fatal("error writing SDBM database %s: %m", dict_sdbm->path);
-+ if (status) {
-+ if (dict->flags & DICT_FLAG_DUP_IGNORE)
-+ /* void */ ;
-+ else if (dict->flags & DICT_FLAG_DUP_WARN)
-+ msg_warn("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
-+ else
-+ msg_fatal("%s: duplicate entry: \"%s\"", dict_sdbm->path, name);
-+ }
-+
-+ /*
-+ * Release the exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
-+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
-+}
-+
-+
-+/* dict_sdbm_delete - delete one entry from the dictionary */
-+
-+static int dict_sdbm_delete(DICT *dict, const char *name)
-+{
-+ DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
-+ datum dbm_key;
-+ int status = 1;
-+ int flags = 0;
-+
-+ /*
-+ * Acquire an exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
-+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
-+
-+ /*
-+ * See if this DBM file was written with one null byte appended to key
-+ * and value.
-+ */
-+ if (dict->flags & DICT_FLAG_TRY1NULL) {
-+ dbm_key.dptr = (void *) name;
-+ dbm_key.dsize = strlen(name) + 1;
-+ sdbm_clearerr(dict_sdbm->dbm);
-+ if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
-+ if (sdbm_error(dict_sdbm->dbm) != 0) /* fatal error */
-+ msg_fatal("error deleting from %s: %m", dict_sdbm->path);
-+ status = 1; /* not found */
-+ } else {
-+ dict->flags &= ~DICT_FLAG_TRY0NULL; /* found */
-+ }
-+ }
-+
-+ /*
-+ * See if this DBM file was written with no null byte appended to key and
-+ * value.
-+ */
-+ if (status > 0 && (dict->flags & DICT_FLAG_TRY0NULL)) {
-+ dbm_key.dptr = (void *) name;
-+ dbm_key.dsize = strlen(name);
-+ sdbm_clearerr(dict_sdbm->dbm);
-+ if ((status = sdbm_delete(dict_sdbm->dbm, dbm_key)) < 0) {
-+ if (sdbm_error(dict_sdbm->dbm) != 0) /* fatal error */
-+ msg_fatal("error deleting from %s: %m", dict_sdbm->path);
-+ status = 1; /* not found */
-+ } else {
-+ dict->flags &= ~DICT_FLAG_TRY1NULL; /* found */
-+ }
-+ }
-+
-+ /*
-+ * Release the exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
-+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
-+
-+ return (status);
-+}
-+
-+/* traverse the dictionary */
-+
-+static int dict_sdbm_sequence(DICT *dict, const int function,
-+ const char **key, const char **value)
-+{
-+ char *myname = "dict_sdbm_sequence";
-+ DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
-+ datum dbm_key;
-+ datum dbm_value;
-+ int status = 0;
-+ static VSTRING *key_buf;
-+ static VSTRING *value_buf;
-+
-+ /*
-+ * Acquire an exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
-+ msg_fatal("%s: lock dictionary: %m", dict_sdbm->path);
-+
-+ /*
-+ * Determine and execute the seek function. It returns the key.
-+ */
-+ switch (function) {
-+ case DICT_SEQ_FUN_FIRST:
-+ dbm_key = sdbm_firstkey(dict_sdbm->dbm);
-+ break;
-+ case DICT_SEQ_FUN_NEXT:
-+ dbm_key = sdbm_nextkey(dict_sdbm->dbm);
-+ break;
-+ default:
-+ msg_panic("%s: invalid function: %d", myname, function);
-+ }
-+
-+ /*
-+ * Release the exclusive lock.
-+ */
-+ if ((dict->flags & DICT_FLAG_LOCK)
-+ && myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
-+ msg_fatal("%s: unlock dictionary: %m", dict_sdbm->path);
-+
-+ if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
-+
-+ /*
-+ * See if this DB file was written with one null byte appended to key
-+ * an d value or not. If necessary, copy the key.
-+ */
-+ if (((char *) dbm_key.dptr)[dbm_key.dsize - 1] == 0) {
-+ *key = dbm_key.dptr;
-+ } else {
-+ if (key_buf == 0)
-+ key_buf = vstring_alloc(10);
-+ vstring_strncpy(key_buf, dbm_key.dptr, dbm_key.dsize);
-+ *key = vstring_str(key_buf);
-+ }
-+
-+ /*
-+ * Fetch the corresponding value.
-+ */
-+ dbm_value = sdbm_fetch(dict_sdbm->dbm, dbm_key);
-+
-+ if (dbm_value.dptr != 0 && dbm_value.dsize > 0) {
-+
-+ /*
-+ * See if this DB file was written with one null byte appended to
-+ * key and value or not. If necessary, copy the key.
-+ */
-+ if (((char *) dbm_value.dptr)[dbm_value.dsize - 1] == 0) {
-+ *value = dbm_value.dptr;
-+ } else {
-+ if (value_buf == 0)
-+ value_buf = vstring_alloc(10);
-+ vstring_strncpy(value_buf, dbm_value.dptr, dbm_value.dsize);
-+ *value = vstring_str(value_buf);
-+ }
-+ } else {
-+
-+ /*
-+ * Determine if we have hit the last record or an error
-+ * condition.
-+ */
-+ if (sdbm_error(dict_sdbm->dbm))
-+ msg_fatal("error seeking %s: %m", dict_sdbm->path);
-+ return (1); /* no error: eof/not found
-+ * (should not happen!) */
-+ }
-+ } else {
-+
-+ /*
-+ * Determine if we have hit the last record or an error condition.
-+ */
-+ if (sdbm_error(dict_sdbm->dbm))
-+ msg_fatal("error seeking %s: %m", dict_sdbm->path);
-+ return (1); /* no error: eof/not found */
-+ }
-+ return (0);
-+}
-+
-+/* dict_sdbm_close - disassociate from data base */
-+
-+static void dict_sdbm_close(DICT *dict)
-+{
-+ DICT_SDBM *dict_sdbm = (DICT_SDBM *) dict;
-+
-+ sdbm_close(dict_sdbm->dbm);
-+ myfree(dict_sdbm->path);
-+ myfree((char *) dict_sdbm);
-+}
-+
-+/* dict_sdbm_open - open SDBM data base */
-+
-+DICT *dict_sdbm_open(const char *path, int open_flags, int dict_flags)
-+{
-+ DICT_SDBM *dict_sdbm;
-+ struct stat st;
-+ SDBM *dbm;
-+ char *dbm_path;
-+ int lock_fd;
-+
-+ if (dict_flags & DICT_FLAG_LOCK) {
-+ dbm_path = concatenate(path, ".pag", (char *) 0);
-+ if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
-+ msg_fatal("open database %s: %m", dbm_path);
-+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
-+ msg_fatal("shared-lock database %s for open: %m", dbm_path);
-+ }
-+
-+ /*
-+ * XXX SunOS 5.x has no const in dbm_open() prototype.
-+ */
-+ if ((dbm = sdbm_open((char *) path, open_flags, 0644)) == 0)
-+ msg_fatal("open database %s.{dir,pag}: %m", path);
-+
-+ if (dict_flags & DICT_FLAG_LOCK) {
-+ if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
-+ msg_fatal("unlock database %s for open: %m", dbm_path);
-+ if (close(lock_fd) < 0)
-+ msg_fatal("close database %s: %m", dbm_path);
-+ myfree(dbm_path);
-+ }
-+ dict_sdbm = (DICT_SDBM *) mymalloc(sizeof(*dict_sdbm));
-+ dict_sdbm->dict.lookup = dict_sdbm_lookup;
-+ dict_sdbm->dict.update = dict_sdbm_update;
-+ dict_sdbm->dict.delete = dict_sdbm_delete;
-+ dict_sdbm->dict.sequence = dict_sdbm_sequence;
-+ dict_sdbm->dict.close = dict_sdbm_close;
-+ dict_sdbm->dict.lock_fd = sdbm_dirfno(dbm);
-+ dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
-+ if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
-+ msg_fatal("dict_sdbm_open: fstat: %m");
-+ dict_sdbm->dict.mtime = st.st_mtime;
-+ close_on_exec(sdbm_pagfno(dbm), CLOSE_ON_EXEC);
-+ close_on_exec(sdbm_dirfno(dbm), CLOSE_ON_EXEC);
-+ dict_sdbm->dict.flags = dict_flags | DICT_FLAG_FIXED;
-+ if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
-+ dict_sdbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
-+ dict_sdbm->dbm = dbm;
-+ dict_sdbm->path = mystrdup(path);
-+
-+ return (&dict_sdbm->dict);
-+}
-diff -Pur postfix-1.1.11-20020613-orig/src/util/dict_sdbm.h postfix-1.1.11-20020613/src/util/dict_sdbm.h
---- postfix-1.1.11-20020613-orig/src/util/dict_sdbm.h Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/dict_sdbm.h Wed Jun 26 15:26:48 2002
-@@ -0,0 +1,35 @@
-+#ifndef _DICT_SDBM_H_INCLUDED_
-+#define _DICT_SDBM_H_INCLUDED_
-+
-+/*++
-+/* NAME
-+/* dict_dbm 3h
-+/* SUMMARY
-+/* dictionary manager interface to DBM files
-+/* SYNOPSIS
-+/* #include <dict_dbm.h>
-+/* DESCRIPTION
-+/* .nf
-+
-+ /*
-+ * Utility library.
-+ */
-+#include <dict.h>
-+
-+ /*
-+ * External interface.
-+ */
-+extern DICT *dict_sdbm_open(const char *, int, int);
-+
-+/* 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 -Pur postfix-1.1.11-20020613-orig/src/util/get_port.c postfix-1.1.11-20020613/src/util/get_port.c
---- postfix-1.1.11-20020613-orig/src/util/get_port.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/get_port.c Wed Jun 26 15:26:49 2002
-@@ -0,0 +1,65 @@
-+/*++
-+/* NAME
-+/* get_port 3
-+/* SUMMARY
-+/* trivial host and port extracter
-+/* SYNOPSIS
-+/* #include <get_port.h>
-+/*
-+/* char *get_port(data)
-+/* char *data;
-+/*
-+/* DESCRIPTION
-+/* get_port() extract host name or ip address from
-+/* strings such as [3ffe:902:12::10]:25, [::1]
-+/* or 192.168.0.1:25, and null-terminates the
-+/* \fIdata\fR at the first occurrence of port separator.
-+/* DIAGNOSTICS
-+/* If port not found return null pointer.
-+/* LICENSE
-+/* .ad
-+/* .fi
-+/* BSD Style (or BSD like) license.
-+/* AUTHOR(S)
-+/* Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
-+/* Wroclaw, POLAND
-+/*--*/
-+
-+/* System libraries */
-+
-+#include <sys_defs.h>
-+#include <string.h>
-+
-+/* Utility library. */
-+
-+#include "get_port.h"
-+
-+/* get_port - extract port number from string */
-+
-+char *get_port(char *data)
-+{
-+ const char *escl=strchr(data,'[');
-+ const char *sepl=strchr(data,':');
-+ char *escr=strrchr(data,']');
-+ char *sepr=strrchr(data,':');
-+
-+ /* extract from "[address]:port" or "[address]"*/
-+ if (escl && escr)
-+ {
-+ memmove(data, data + 1, strlen(data) - strlen(escr));
-+ data[strlen(data) - strlen(escr) - 1] = 0;
-+ *escr++ = 0;
-+ if (*escr == ':')
-+ escr++;
-+ return (*escr ? escr : NULL);
-+ }
-+ /* extract from "address:port" or "address" */
-+ if ((sepl == sepr) && sepr && sepl)
-+ {
-+ *sepr++ = 0;
-+ return sepr;
-+ }
-+
-+ /* return empty string */
-+ return NULL;
-+}
-diff -Pur postfix-1.1.11-20020613-orig/src/util/get_port.h postfix-1.1.11-20020613/src/util/get_port.h
---- postfix-1.1.11-20020613-orig/src/util/get_port.h Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/get_port.h Wed Jun 26 15:26:49 2002
-@@ -0,0 +1,28 @@
-+#ifndef _GET_PORT_H_INCLUDED_
-+#define _GET_PORT_H_INCLUDED_
-+
-+/*++
-+/* NAME
-+/* get_port 3h
-+/* SUMMARY
-+/* trivial host and port extracter
-+/* SYNOPSIS
-+/* #include <get_port.h>
-+/* DESCRIPTION
-+/* .nf
-+
-+ /* External interface. */
-+
-+extern char *get_port(char *);
-+
-+
-+/* LICENSE
-+/* .ad
-+/* .fi
-+/* BSD Style (or BSD like) license.
-+/* AUTHOR(S)
-+/* Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
-+/* Wroclaw, POLAND
-+/*--*/
-+
-+#endif
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_addr_host.c postfix-1.1.11-20020613/src/util/inet_addr_host.c
---- postfix-1.1.11-20020613-orig/src/util/inet_addr_host.c Fri Dec 11 19:55:35 1998
-+++ postfix-1.1.11-20020613/src/util/inet_addr_host.c Wed Jun 26 15:26:49 2002
-@@ -38,7 +38,10 @@
- #include <sys_defs.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-+#include <sys/socket.h>
- #include <netdb.h>
-+#include <stdlib.h>
-+#include <string.h>
-
- #ifndef INADDR_NONE
- #define INADDR_NONE 0xffffffff
-@@ -48,15 +51,47 @@
-
- #include <inet_addr_list.h>
- #include <inet_addr_host.h>
-+#ifdef TEST
-+#include <msg.h>
-+#endif
-
- /* inet_addr_host - look up address list for host */
-
- int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
- {
-+#ifdef INET6
-+ int s;
-+ struct addrinfo hints, *res0, *res;
-+#ifdef TEST
-+ char buforhosta[1024];
-+#endif
-+ int error;
-+#else
- struct hostent *hp;
- struct in_addr addr;
-+#endif
- int initial_count = addr_list->used;
-
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ error = getaddrinfo(hostname, NULL, &hints, &res0);
-+ if (error == 0) {
-+ for (res = res0; res; res = res->ai_next) {
-+ if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
-+ continue;
-+ /* filter out address families that are not supported */
-+ s = socket(res->ai_family, SOCK_DGRAM, 0);
-+ if (s < 0)
-+ continue;
-+ close(s);
-+
-+ inet_addr_list_append(addr_list, res->ai_addr);
-+ }
-+ freeaddrinfo(res0);
-+ }
-+#else
- if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
- inet_addr_list_append(addr_list, &addr);
- } else {
-@@ -65,9 +100,12 @@
- inet_addr_list_append(addr_list,
- (struct in_addr *) * hp->h_addr_list++);
- }
-+#endif
-+
- return (addr_list->used - initial_count);
- }
-
-+
- #ifdef TEST
-
- #include <msg.h>
-@@ -78,6 +116,8 @@
- {
- INET_ADDR_LIST addr_list;
- int i;
-+ struct sockaddr *sa;
-+ char hbuf[NI_MAXHOST];
-
- msg_vstream_init(argv[0], VSTREAM_ERR);
-
-@@ -89,8 +129,12 @@
- if (inet_addr_host(&addr_list, *argv) == 0)
- msg_fatal("not found: %s", *argv);
-
-- for (i = 0; i < addr_list.used; i++)
-- vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i]));
-+ for (i = 0; i < addr_list.used; i++) {
-+ sa = (struct sockaddr *)&addr_list.addrs[i];
-+ getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
-+ NI_NUMERICHOST);
-+ vstream_printf("%s\n", hbuf);
-+ }
- vstream_fflush(VSTREAM_OUT);
- }
- inet_addr_list_free(&addr_list);
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_addr_list.c postfix-1.1.11-20020613/src/util/inet_addr_list.c
---- postfix-1.1.11-20020613-orig/src/util/inet_addr_list.c Tue Jul 31 20:13:41 2001
-+++ postfix-1.1.11-20020613/src/util/inet_addr_list.c Wed Jun 26 15:26:49 2002
-@@ -51,6 +51,13 @@
- #include <arpa/inet.h>
- #include <stdlib.h>
-
-+#include <netdb.h>
-+
-+#ifdef INET6
-+#include <string.h>
-+#include <sys/socket.h>
-+#endif
-+
- /* Utility library. */
-
- #include <msg.h>
-@@ -63,12 +70,39 @@
- {
- list->used = 0;
- list->size = 2;
-+#ifdef INET6
-+ list->addrs = (struct sockaddr_storage *)
-+#else
- list->addrs = (struct in_addr *)
-+#endif
- mymalloc(sizeof(*list->addrs) * list->size);
- }
-
- /* inet_addr_list_append - append address to internet address list */
-
-+#ifdef INET6
-+void inet_addr_list_append(INET_ADDR_LIST *list,
-+ struct sockaddr * addr)
-+{
-+ char *myname = "inet_addr_list_append";
-+ char hbuf[NI_MAXHOST];
-+
-+ if (msg_verbose > 1) {
-+ if (getnameinfo(addr, SA_LEN(addr), hbuf, sizeof(hbuf), NULL, 0,
-+ NI_NUMERICHOST)) {
-+ strncpy(hbuf, "??????", sizeof(hbuf));
-+ }
-+ msg_info("%s: %s", myname, hbuf);
-+ }
-+
-+ if (list->used >= list->size)
-+ list->size *= 2;
-+ list->addrs = (struct sockaddr_storage *)
-+ myrealloc((char *) list->addrs,
-+ sizeof(*list->addrs) * list->size);
-+ memcpy(&list->addrs[list->used++], addr, SA_LEN(addr));
-+}
-+#else
- void inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
- {
- char *myname = "inet_addr_list_append";
-@@ -83,15 +117,22 @@
- sizeof(*list->addrs) * list->size);
- list->addrs[list->used++] = *addr;
- }
-+#endif
-
- /* inet_addr_list_comp - compare addresses */
-
- static int inet_addr_list_comp(const void *a, const void *b)
- {
-+#ifdef INET6
-+ if(((struct sockaddr*)a)->sa_family != ((struct sockaddr*)b)->sa_family)
-+ return ( ((struct sockaddr*)a)->sa_family - ((struct sockaddr*)b)->sa_family );
-+ return memcmp(a,b,SA_LEN((struct sockaddr*)a));
-+#else
- const struct in_addr *a_addr = (const struct in_addr *) a;
- const struct in_addr *b_addr = (const struct in_addr *) b;
-
- return (a_addr->s_addr - b_addr->s_addr);
-+#endif
- }
-
- /* inet_addr_list_uniq - weed out duplicates */
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_addr_list.h postfix-1.1.11-20020613/src/util/inet_addr_list.h
---- postfix-1.1.11-20020613-orig/src/util/inet_addr_list.h Tue Jul 31 19:56:47 2001
-+++ postfix-1.1.11-20020613/src/util/inet_addr_list.h Wed Jun 26 15:26:49 2002
-@@ -16,19 +16,42 @@
- */
- #include <netinet/in.h>
-
-+#ifndef SA_LEN
-+# ifndef HAS_SA_LEN
-+# define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-+# define SS_LEN(x) (((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-+# else
-+# define SA_LEN(x) ((x)->sa_len)
-+# define SS_LEN(x) ((x).ss_len)
-+# endif
-+#else
-+# ifndef SS_LEN
-+# define SS_LEN(x) (((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
-+# endif
-+#endif
-+
- /*
- * External interface.
- */
- typedef struct INET_ADDR_LIST {
- int used; /* nr of elements in use */
- int size; /* actual list size */
-+#ifdef INET6
-+ struct sockaddr_storage *addrs; /* payload */
-+#else
- struct in_addr *addrs; /* payload */
-+#endif
- } INET_ADDR_LIST;
-
- extern void inet_addr_list_init(INET_ADDR_LIST *);
- extern void inet_addr_list_free(INET_ADDR_LIST *);
- extern void inet_addr_list_uniq(INET_ADDR_LIST *);
-+#ifdef INET6
-+struct sockaddr;
-+extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);
-+#else
- extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
-+#endif
-
- /* LICENSE
- /* .ad
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_addr_local.c postfix-1.1.11-20020613/src/util/inet_addr_local.c
---- postfix-1.1.11-20020613-orig/src/util/inet_addr_local.c Sun Feb 25 19:20:19 2001
-+++ postfix-1.1.11-20020613/src/util/inet_addr_local.c Wed Jun 26 15:26:49 2002
-@@ -47,6 +47,13 @@
- #endif
- #include <errno.h>
- #include <string.h>
-+#if defined(INET6) && (defined (LINUX) || defined (LINUX2))
-+#include <netdb.h>
-+#include <stdio.h>
-+#endif
-+#ifdef HAVE_GETIFADDRS
-+#include <ifaddrs.h>
-+#endif
-
- /* Utility library. */
-
-@@ -78,18 +85,104 @@
-
- int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
- {
-+#ifdef HAVE_GETIFADDRS
-+ char *myname = "inet_addr_local";
-+ struct ifaddrs *ifap, *ifa;
-+ int initial_count = addr_list->used;
-+ struct sockaddr *sa, *sam;
-+#ifdef INET6
-+#ifdef __KAME__
-+ struct sockaddr_in6 addr6;
-+#endif
-+#else
-+ void *addr,*addrm;
-+#endif
-+
-+ if (getifaddrs(&ifap) < 0)
-+ msg_fatal("%s: getifaddrs: %m", myname);
-+
-+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
-+ if (! (ifa->ifa_flags & IFF_RUNNING) || ifa->ifa_addr==NULL)
-+ continue;
-+ sa = ifa->ifa_addr;
-+ sam = ifa->ifa_netmask;
-+ switch (ifa->ifa_addr->sa_family) {
-+ case AF_INET:
-+#ifndef INET6
-+ addr = (void *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
-+ addrm = (void *)&((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
-+#endif
-+ break;
-+#ifdef INET6
-+ case AF_INET6:
-+#ifdef __KAME__
-+ memcpy(&addr6, ifa->ifa_addr, ifa->ifa_addr->sa_len);
-+ /* decode scoped address notation */
-+ if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
-+ IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
-+ addr6.sin6_scope_id == 0) {
-+ addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
-+ (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
-+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
-+ sa = (struct sockaddr *)&addr6;
-+ }
-+#endif
-+ break;
-+#endif
-+ default:
-+ continue;
-+ }
-+
-+#ifdef INET6
-+ inet_addr_list_append(addr_list, sa);
-+ if (mask_list != NULL)
-+ inet_addr_list_append(mask_list, sam);
-+#else
-+ inet_addr_list_append(addr_list, (struct in_addr *)addr);
-+ if (mask_list != NULL)
-+ inet_addr_list_append(mask_list, (struct in_addr *)addrm);
-+#endif
-+ }
-+
-+ freeifaddrs(ifap);
-+ return (addr_list->used - initial_count);
-+#else
- char *myname = "inet_addr_local";
- struct ifconf ifc;
- struct ifreq *ifr;
- struct ifreq *the_end;
- int sock;
-- VSTRING *buf = vstring_alloc(1024);
-+ VSTRING *buf;
- int initial_count = addr_list->used;
- struct in_addr addr;
- struct ifreq *ifr_mask;
-+ int af = AF_INET;
-+#ifdef INET6
-+#if defined (LINUX) || defined (LINUX2)
-+#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
-+ FILE *f;
-+ char addr6p[8][5], addr6res[40], devname[20];
-+ int plen, scope, dad_status, if_idx, gaierror;
-+ struct addrinfo hints, *res, *res0;
-+#endif
-+ struct sockaddr_in6 addr6;
-
-- if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
-+other_socket_type:
-+#endif
-+ buf = vstring_alloc(1024);
-+
-+ if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
-+#ifdef INET6
-+ if (af == AF_INET6)
-+ {
-+ if (msg_verbose)
-+ msg_warn("%s: socket: %m", myname);
-+ goto end;
-+ }
-+ else
-+#endif
- msg_fatal("%s: socket: %m", myname);
-+ }
-
- /*
- * Get the network interface list. XXX The socket API appears to have no
-@@ -126,10 +219,15 @@
- */
- the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
- for (ifr = ifc.ifc_req; ifr < the_end;) {
-- if (ifr->ifr_addr.sa_family == AF_INET) { /* IP interface */
-+ if ((ifr->ifr_addr.sa_family == AF_INET) &&
-+ (ifr->ifr_addr.sa_family == af)) { /* IP interface */
- addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
- if (addr.s_addr != INADDR_ANY) { /* has IP address */
-+#ifdef INET6
-+ inet_addr_list_append(addr_list, &ifr->ifr_addr);
-+#else
- inet_addr_list_append(addr_list, &addr);
-+#endif
- if (mask_list) {
- ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
- memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
-@@ -141,11 +239,61 @@
- }
- }
- }
-+#ifdef INET6
-+ else if ((ifr->ifr_addr.sa_family == AF_INET6) &&
-+ (ifr->ifr_addr.sa_family == af)) { /* IPv6 interface */
-+ addr6 = *((struct sockaddr_in6 *) & ifr->ifr_addr);
-+#ifdef __KAME__
-+ /* decode scoped address notation */
-+ if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
-+ IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
-+ addr6.sin6_scope_id == 0) {
-+ addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
-+ (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
-+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
-+ }
-+#endif
-+ if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr)))
-+ inet_addr_list_append(addr_list, (struct sockaddr *)&addr6);
-+ }
-+#endif
- ifr = NEXT_INTERFACE(ifr);
- }
- vstring_free(buf);
- (void) close(sock);
-+#ifdef INET6
-+end:
-+ if (af != AF_INET6) {
-+ af = AF_INET6;
-+ goto other_socket_type;
-+ }
-+#if defined (LINUX) || defined (LINUX2)
-+ if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
-+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
-+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
-+ addr6p[5], addr6p[6], addr6p[7],
-+ &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
-+ sprintf(addr6res, "%s:%s:%s:%s:%s:%s:%s:%s",
-+ addr6p[0], addr6p[1], addr6p[2], addr6p[3],
-+ addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
-+ addr6res[sizeof(addr6res) - 1] = 0;
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_flags = AI_NUMERICHOST;
-+ hints.ai_family = AF_UNSPEC;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ gaierror = getaddrinfo(addr6res, NULL, &hints, &res0);
-+ if (!gaierror) {
-+ for (res = res0; res; res = res->ai_next) {
-+ inet_addr_list_append(addr_list, res->ai_addr);
-+ }
-+ freeaddrinfo(res0);
-+ }
-+ }
-+ }
-+#endif /* linux */
-+#endif
- return (addr_list->used - initial_count);
-+#endif
- }
-
- #ifdef TEST
-@@ -158,6 +306,8 @@
- INET_ADDR_LIST addr_list;
- INET_ADDR_LIST mask_list;
- int i;
-+ char abuf[NI_MAXHOST], mbuf[NI_MAXHOST];
-+ struct sockaddr *sa;
-
- msg_vstream_init(argv[0], VSTREAM_ERR);
-
-@@ -172,8 +322,17 @@
- msg_warn("found only one active network interface");
-
- for (i = 0; i < addr_list.used; i++) {
-- vstream_printf("%s/", inet_ntoa(addr_list.addrs[i]));
-- vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i]));
-+ sa = (struct sockaddr *)&addr_list.addrs[i];
-+ if (getnameinfo(sa, SA_LEN(sa), abuf, sizeof(abuf), NULL, 0,
-+ NI_NUMERICHOST)) {
-+ strncpy(abuf, "???", sizeof(abuf));
-+ }
-+ sa = (struct sockaddr *)&mask_list.addrs[i];
-+ if (getnameinfo(sa, SA_LEN(sa), mbuf, sizeof(mbuf), NULL, 0,
-+ NI_NUMERICHOST)) {
-+ strncpy(mbuf, "???", sizeof(mbuf));
-+ }
-+ vstream_printf("%s/%s\n", abuf, mbuf);
- }
- vstream_fflush(VSTREAM_OUT);
- inet_addr_list_free(&addr_list);
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_connect.c postfix-1.1.11-20020613/src/util/inet_connect.c
---- postfix-1.1.11-20020613-orig/src/util/inet_connect.c Mon Nov 20 19:06:31 2000
-+++ postfix-1.1.11-20020613/src/util/inet_connect.c Wed Jun 26 15:26:49 2002
-@@ -55,6 +55,9 @@
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
-+#ifdef INET6
-+#include <netdb.h>
-+#endif
-
- /* Utility library. */
-
-@@ -73,7 +76,12 @@
- char *buf;
- char *host;
- char *port;
-+#ifdef INET6
-+ struct addrinfo hints, *res, *res0;
-+ int error;
-+#else
- struct sockaddr_in sin;
-+#endif
- int sock;
-
- /*
-@@ -81,14 +89,58 @@
- * the local host.
- */
- buf = inet_parse(addr, &host, &port);
-+#ifdef INET6
-+ if (*host == 0)
-+ host = NULL;
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_NUMERICHOST; /* find_inet_addr is numeric only */
-+ if (getaddrinfo(host, port, &hints, &res0))
-+ msg_fatal("host not found: %s", host);
-+#else
- if (*host == 0)
- host = "localhost";
- memset((char *) &sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = find_inet_addr(host);
- sin.sin_port = find_inet_port(port, "tcp");
-+#endif
- myfree(buf);
-
-+#ifdef INET6
-+ sock = -1;
-+ for (res = res0; res; res = res->ai_next) {
-+ if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
-+ continue;
-+
-+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-+ if (sock < 0)
-+ continue;
-+ if (timeout > 0) {
-+ non_blocking(sock, NON_BLOCKING);
-+ if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
-+ close(sock);
-+ sock = -1;
-+ continue;
-+ }
-+ if (block_mode != NON_BLOCKING)
-+ non_blocking(sock, block_mode);
-+ break;
-+ } else {
-+ non_blocking(sock, block_mode);
-+ if (connect(sock, res->ai_addr, res->ai_addrlen) < 0
-+ && errno != EINPROGRESS) {
-+ close(sock);
-+ sock = -1;
-+ continue;
-+ }
-+ break;
-+ }
-+ }
-+ freeaddrinfo(res0);
-+ return sock;
-+#else
- /*
- * Create a client socket.
- */
-@@ -121,4 +173,5 @@
- }
- return (sock);
- }
-+#endif
- }
-diff -Pur postfix-1.1.11-20020613-orig/src/util/inet_listen.c postfix-1.1.11-20020613/src/util/inet_listen.c
---- postfix-1.1.11-20020613-orig/src/util/inet_listen.c Mon Nov 20 19:06:32 2000
-+++ postfix-1.1.11-20020613/src/util/inet_listen.c Wed Jun 26 15:26:49 2002
-@@ -6,7 +6,7 @@
- /* SYNOPSIS
- /* #include <listen.h>
- /*
--/* int inet_listen(addr, backlog, block_mode)
-+/* int inet_listen(addr, backlog, block_mode, addinuse_fatal)
- /* const char *addr;
- /* int backlog;
- /* int block_mode;
-@@ -51,11 +51,17 @@
- #include <sys_defs.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-+#ifdef INET6
-+#if (! __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 )
-+#include <netinet6/in6.h>
-+#endif
-+#endif
- #include <arpa/inet.h>
- #include <netdb.h>
- #ifndef MAXHOSTNAMELEN
- #include <sys/param.h>
- #endif
-+#include <errno.h>
- #include <string.h>
- #include <unistd.h>
-
-@@ -77,35 +83,116 @@
-
- /* inet_listen - create inet-domain listener */
-
--int inet_listen(const char *addr, int backlog, int block_mode)
-+int inet_listen(const char *addr, int backlog, int block_mode, int addrinuse_fatal)
- {
-+#ifdef INET6
-+ struct addrinfo *res, *res0, hints;
-+ int error;
-+#else
-+ struct ai {
-+ int ai_family;
-+ int ai_socktype;
-+ int ai_protocol;
-+ struct sockaddr *ai_addr;
-+ SOCKADDR_SIZE ai_addrlen;
-+ struct ai *ai_next;
-+ } *res, *res0, resbody;
- struct sockaddr_in sin;
-+#endif
- int sock;
- int t = 1;
-+ int addrinuse = 0;
- char *buf;
- char *host;
- char *port;
-+#ifdef INET6
-+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
-+#else
-+ char hbuf[sizeof("255.255.255.255") + 1];
-+ char pbuf[sizeof("255.255.255.255") + 1];
-+#endif
-+ char *cause = "unknown";
-
- /*
- * Translate address information to internal form.
- */
- buf = inet_parse(addr, &host, &port);
-- memset((char *) &sin, 0, sizeof(sin));
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_flags = AI_PASSIVE;
-+ hints.ai_family = AF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ error = getaddrinfo(*host ? host : NULL, *port ? port : "0", &hints, &res0);
-+ if (error) {
-+ msg_fatal("getaddrinfo: %s", gai_strerror(error));
-+ }
-+ myfree(buf);
-+#else
-+ memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
-+#ifdef HAS_SA_LEN
-+ sin.sin_len = sizeof(sin);
-+#endif
- sin.sin_port = find_inet_port(port, "tcp");
- sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
-- myfree(buf);
-
-- /*
-- * Create a listener socket.
-- */
-- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-- msg_fatal("socket: %m");
-- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0)
-- msg_fatal("setsockopt: %m");
-- if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
-- msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ?
-- "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-+ memset(&resbody, 0, sizeof(resbody));
-+ resbody.ai_socktype = SOCK_STREAM;
-+ resbody.ai_family = AF_INET;
-+ resbody.ai_addr = (struct sockaddr *)&sin;
-+ resbody.ai_addrlen = sizeof(sin);
-+
-+ res0 = &resbody;
-+#endif
-+
-+ sock = -1;
-+ for (res = res0; res; res = res->ai_next) {
-+ if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
-+ continue;
-+
-+ /*
-+ * Create a listener socket.
-+ */
-+ if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0) {
-+ cause = "socket";
-+ continue;
-+ }
-+#ifdef IPV6_V6ONLY
-+ if (res->ai_family == AF_INET6 &&
-+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &t, sizeof(t)) < 0) {
-+ /* if kernel/libc don't support this simple ignore it
-+ cause = "setsockopt(IPV6_V6ONLY)";
-+ close(sock);
-+ sock = -1;
-+ continue;
-+ */
-+ ;
-+ }
-+#endif
-+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) {
-+ cause = "setsockopt(SO_REUSEADDR)";
-+ close(sock);
-+ sock = -1;
-+ continue;
-+ }
-+
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
-+ cause = "bind";
-+ if (errno == EADDRINUSE)
-+ addrinuse = 1;
-+ close(sock);
-+ sock = -1;
-+ continue;
-+ }
-+ break;
-+ }
-+ if (sock < 0 && (addrinuse_fatal || !addrinuse))
-+ msg_fatal("%s: %m", cause);
-+#ifdef INET6
-+ freeaddrinfo(res0);
-+#endif
-+ if (sock < 0)
-+ return -1;
- non_blocking(sock, block_mode);
- if (listen(sock, backlog) < 0)
- msg_fatal("listen: %m");
-diff -Pur postfix-1.1.11-20020613-orig/src/util/listen.h postfix-1.1.11-20020613/src/util/listen.h
---- postfix-1.1.11-20020613-orig/src/util/listen.h Mon Mar 22 02:57:11 1999
-+++ postfix-1.1.11-20020613/src/util/listen.h Wed Jun 26 15:26:49 2002
-@@ -20,7 +20,7 @@
- * Listener external interface.
- */
- extern int unix_listen(const char *, int, int);
--extern int inet_listen(const char *, int, int);
-+extern int inet_listen(const char *, int, int, int);
- extern int fifo_listen(const char *, int, int);
- extern int stream_listen(const char *, int, int);
-
-diff -Pur postfix-1.1.11-20020613-orig/src/util/match_list.c postfix-1.1.11-20020613/src/util/match_list.c
---- postfix-1.1.11-20020613-orig/src/util/match_list.c Tue Nov 20 21:07:15 2001
-+++ postfix-1.1.11-20020613/src/util/match_list.c Wed Jun 26 15:26:49 2002
-@@ -118,7 +118,7 @@
- list = match_list_parse(list, vstring_str(buf));
- if (vstream_fclose(fp))
- msg_fatal("%s: read file %s: %m", myname, pattern);
-- } else if (strchr(pattern, ':') != 0) { /* type:table */
-+ } else if ((strchr(pattern, ']') == 0) && (strchr(pattern, ':') != 0)) { /* type:table */
- for (cp = pattern; *cp == '!'; cp++)
- /* void */ ;
- if (dict_handle(pattern) == 0)
-diff -Pur postfix-1.1.11-20020613-orig/src/util/match_ops.c postfix-1.1.11-20020613/src/util/match_ops.c
---- postfix-1.1.11-20020613-orig/src/util/match_ops.c Tue Nov 20 21:16:10 2001
-+++ postfix-1.1.11-20020613/src/util/match_ops.c Wed Jun 26 15:26:49 2002
-@@ -81,6 +81,307 @@
- #include <match_ops.h>
- #include <stringops.h>
-
-+#ifdef INET6
-+/*
-+ * $Id: tls+ipv6.diff,v 1.1 2002/07/22 23:09:48 raker Exp $
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ *
-+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
-+ *
-+ * Modifications:
-+ * Artur Frysiak <wiget@pld.org.pl>
-+ * Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <syslog.h>
-+#include <fcntl.h>
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <string.h>
-+#include <netdb.h>
-+#include <arpa/inet.h>
-+#include <resolv.h>
-+
-+#ifndef AF_DECnet
-+#define AF_DECnet 12
-+#endif
-+
-+#ifndef PF_PACKET
-+#define PF_PACKET 17
-+#endif
-+
-+typedef struct
-+{
-+ unsigned char family;
-+ unsigned char bytelen;
-+ signed short bitlen;
-+ unsigned int data[4];
-+} inet_prefix;
-+
-+/* prototypes */
-+int masked_match(char *, char *, char *);
-+int get_integer(int *, char *, int);
-+int get_addr_1(inet_prefix *, char *, int);
-+int get_prefix_1(inet_prefix *, char *, int);
-+int get_addr(inet_prefix *, char *, int);
-+int get_prefix(inet_prefix *, char *, int);
-+unsigned int get_addr32(char *);
-+int matches(char *, char *);
-+int inet_addr_match(inet_prefix *, inet_prefix *, int);
-+int mask_match(char *, char *, char *);
-+
-+int get_integer(int *val, char *arg, int base)
-+{
-+ long res;
-+ char *ptr;
-+
-+ if (!arg || !*arg)
-+ return -1;
-+ res = strtol(arg, &ptr, base);
-+ if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
-+ return -1;
-+ *val = res;
-+ return 0;
-+}
-+
-+int get_addr_1(inet_prefix *addr, char *name, int family)
-+{
-+ char *cp;
-+ unsigned char *ap = (unsigned char*)addr->data;
-+ int i;
-+
-+ memset(addr, 0, sizeof(*addr));
-+
-+ if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) {
-+ if (family == AF_DECnet)
-+ return -1;
-+ addr->family = family;
-+ addr->bytelen = (family == AF_INET6 ? 16 : 4);
-+ addr->bitlen = -1;
-+ return 0;
-+ }
-+
-+ if (strchr(name, ':')) {
-+ addr->family = AF_INET6;
-+ if (family != AF_UNSPEC && family != AF_INET6)
-+ return -1;
-+ if (inet_pton(AF_INET6, name, addr->data) <= 0)
-+ return -1;
-+ addr->bytelen = 16;
-+ addr->bitlen = -1;
-+ return 0;
-+ }
-+ addr->family = AF_INET;
-+ if (family != AF_UNSPEC && family != AF_INET)
-+ return -1;
-+ addr->bytelen = 4;
-+ addr->bitlen = -1;
-+ for (cp = name, i = 0; *cp; cp++) {
-+ if (*cp <= '9' && *cp >= '0') {
-+ ap[i] = 10*ap[i] + (*cp-'0');
-+ continue;
-+ }
-+ if (*cp == '.' && ++i <= 3)
-+ continue;
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+int get_prefix_1(inet_prefix *dst, char *arg, int family)
-+{
-+ int err;
-+ unsigned plen;
-+ char *slash;
-+
-+ memset(dst, 0, sizeof(*dst));
-+
-+ if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
-+ if (family == AF_DECnet)
-+ return -1;
-+ dst->family = family;
-+ dst->bytelen = 0;
-+ dst->bitlen = 0;
-+ return 0;
-+ }
-+
-+ slash = strchr(arg, '/');
-+ if (slash)
-+ *slash = 0;
-+ err = get_addr_1(dst, arg, family);
-+ if (err == 0) {
-+ switch(dst->family) {
-+ case AF_INET6:
-+ dst->bitlen = 128;
-+ break;
-+ case AF_DECnet:
-+ dst->bitlen = 16;
-+ break;
-+ default:
-+ case AF_INET:
-+ dst->bitlen = 32;
-+ }
-+ if (slash) {
-+ if (get_integer(&plen, slash+1, 0) || plen > dst->bitlen) {
-+ err = -1;
-+ goto done;
-+ }
-+ dst->bitlen = plen;
-+ }
-+ }
-+done:
-+ if (slash)
-+ *slash = '/';
-+ return err;
-+}
-+
-+int get_addr(inet_prefix *dst, char *arg, int family)
-+{
-+#ifdef AF_PACKET
-+ if (family == AF_PACKET)
-+ return -1;
-+#endif
-+ if (get_addr_1(dst, arg, family))
-+ return -1;
-+ return 0;
-+}
-+
-+int get_prefix(inet_prefix *dst, char *arg, int family)
-+{
-+#ifdef AF_PACKET
-+ if (family == AF_PACKET)
-+ return -1;
-+#endif
-+ if (get_prefix_1(dst, arg, family))
-+ return -1;
-+ return 0;
-+}
-+
-+unsigned int get_addr32(char *name)
-+{
-+ inet_prefix addr;
-+ if (get_addr_1(&addr, name, AF_INET))
-+ return -1;
-+ return addr.data[0];
-+}
-+
-+int matches(char *cmd, char *pattern)
-+{
-+ int len = strlen(cmd);
-+ if (len > strlen(pattern))
-+ return -1;
-+ return memcmp(pattern, cmd, len);
-+}
-+
-+int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
-+{
-+ unsigned int *a1 = a->data;
-+ unsigned int *a2 = b->data;
-+ int words = bits >> 0x05;
-+
-+ bits &= 0x1f;
-+
-+ if (words)
-+ if (memcmp(a1, a2, words << 2))
-+ return -1;
-+
-+ if (bits) {
-+ unsigned int w1, w2;
-+ unsigned int mask;
-+
-+ w1 = a1[words];
-+ w2 = a2[words];
-+
-+ mask = htonl((0xffffffff) << (0x20 - bits));
-+
-+ if ((w1 ^ w2) & mask)
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* zero if matches */
-+int mask_match(char *network, char *cprefix, char *address)
-+{
-+ inet_prefix *inetwork;
-+ inet_prefix *iaddress;
-+ int ret, prefix;
-+
-+ if (!(network && address && cprefix))
-+ return -1;
-+ prefix = strtol(cprefix, (char **)NULL, 10);
-+ if ((prefix < 0) || (prefix > 128))
-+ return -1;
-+ if ((strlen(network) == 0) || (strlen(address) == 0))
-+ return -1;
-+
-+ inetwork = malloc(sizeof(inet_prefix));
-+ iaddress = malloc(sizeof(inet_prefix));
-+
-+ if ((get_addr(iaddress, address, AF_UNSPEC) >= 0)
-+ && (get_addr(inetwork, network, AF_UNSPEC) >= 0))
-+ ret = inet_addr_match(inetwork, iaddress, prefix);
-+ else
-+ ret = -1;
-+ free(inetwork);
-+ free(iaddress);
-+
-+ /* 1 if matches */
-+ /* return (!ret); */
-+ /* 0 if matches */
-+ return ret;
-+}
-+
-+/*
-+ * masked_match() - universal for IPv4 and IPv6 - 1 if matches
-+ */
-+int masked_match(net_tok, mask_tok, string)
-+char *net_tok;
-+char *mask_tok;
-+char *string;
-+{
-+#ifdef INET6
-+ struct in6_addr in6[2];
-+ char v4addr[2][INET_ADDRSTRLEN];
-+ char newmask[6];
-+ int plen;
-+#endif
-+
-+ /* Check for NULL */
-+ if (!(net_tok && mask_tok && string))
-+ return 0; /* doesn't match!!! */
-+
-+ /* If IPv6 mapped convert to native-IPv4 */
-+#ifdef INET6
-+ if (inet_pton(AF_INET6, net_tok, &in6[0]) == 1 &&
-+ inet_pton(AF_INET6, string, &in6[1]) == 1 &&
-+ IN6_IS_ADDR_V4MAPPED(&in6[0]) && IN6_IS_ADDR_V4MAPPED(&in6[1])) {
-+ plen = atoi(mask_tok);
-+ if (32 < plen && plen < 129) {
-+ sprintf(newmask, "%d", plen - 96);
-+ mask_tok = newmask;
-+ }
-+
-+ (void)inet_ntop(AF_INET, &in6[0].s6_addr[12], v4addr[0],
-+ sizeof(v4addr[0]));
-+ net_tok = v4addr[0];
-+ (void)inet_ntop(AF_INET, &in6[1].s6_addr[12], v4addr[1],
-+ sizeof(v4addr[1]));
-+ string = v4addr[1];
-+ }
-+#endif
-+ return (!mask_match(net_tok, mask_tok, string));
-+}
-+#endif
-+
- /* match_string - match a string literal */
-
- int match_string(int unused_flags, const char *string, const char *pattern)
-@@ -177,6 +478,7 @@
- return (0);
- }
-
-+#ifndef INET6
- /* match_parse_mask - parse net/mask pattern */
-
- static int match_parse_mask(const char *pattern, unsigned long *net_bits,
-@@ -198,27 +500,55 @@
- return (mask != 0);
- }
-
-+#endif
-+
- /* match_hostaddr - match host by address */
-
- int match_hostaddr(int unused_flags, const char *addr, const char *pattern)
- {
- char *myname = "match_hostaddr";
-+#ifdef INET6
-+ char *network, *mask, *escl, *escr, *patternx;
-+ struct in6_addr in6;
-+ char v4addr[INET_ADDRSTRLEN];
-+#else
- int mask_shift;
- unsigned long mask_bits;
- unsigned long net_bits;
- unsigned long addr_bits;
-+#endif
-
- if (msg_verbose)
- msg_info("%s: %s ~? %s", myname, addr, pattern);
-
-+#ifdef INET6
-+ if (addr[strspn(addr, "01234567890./:abcdef")] != 0)
-+#else
- if (addr[strspn(addr, "01234567890./:")] != 0)
-+#endif
- return (0);
-
-+#ifdef INET6
-+ patternx = mystrdup(pattern);
-+ escl = strchr(patternx,'[');
-+ escr = strrchr(patternx,']');
-+ if (escl && escr) {
-+ *escr = 0;
-+ sprintf(patternx, "%s%s", escl + 1, escr + 1);
-+ pattern = patternx;
-+ }
-+#endif
-+
- /*
- * Try dictionary lookup. This can be case insensitive. XXX Probably
- * should also try again after stripping least significant octets.
- */
-- if (strchr(pattern, ':') != 0) {
-+#ifdef INET6
-+ if (!(escl && escr) && strchr(pattern, ':') != 0)
-+#else
-+ if (strchr(pattern, ':') != 0)
-+#endif
-+ {
- if (dict_lookup(pattern, addr) != 0)
- return (1);
- if (dict_errno != 0)
-@@ -229,6 +559,12 @@
- /*
- * Try an exact match with the host address.
- */
-+#ifdef INET6
-+ if (inet_pton(AF_INET6, addr, &in6) == 1 && IN6_IS_ADDR_V4MAPPED(&in6)) {
-+ (void)inet_ntop(AF_INET, &in6.s6_addr[12], v4addr, sizeof(v4addr));
-+ addr = v4addr;
-+ }
-+#endif
- if (strcasecmp(addr, pattern) == 0) {
- return (1);
- }
-@@ -237,6 +573,20 @@
- * In a net/mask pattern, the mask is specified as the number of bits of
- * the network part.
- */
-+#ifdef INET6
-+ network = mystrdup(patternx);
-+ mask = split_at(network, '/');
-+
-+ if (masked_match(network, mask, (char *)addr)) {
-+ myfree(network);
-+ myfree(patternx);
-+ return (1);
-+ } else {
-+ myfree(network);
-+ myfree(patternx);
-+ }
-+#else
-+
- if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
- addr_bits = inet_addr(addr);
- if (addr_bits == INADDR_NONE)
-@@ -244,5 +594,6 @@
- mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
- return ((addr_bits & mask_bits) == (net_bits & mask_bits));
- }
-+#endif
- return (0);
- }
-diff -Pur postfix-1.1.11-20020613-orig/src/util/sdbm.c postfix-1.1.11-20020613/src/util/sdbm.c
---- postfix-1.1.11-20020613-orig/src/util/sdbm.c Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/sdbm.c Wed Jun 26 15:26:49 2002
-@@ -0,0 +1,971 @@
-+/*++
-+/* NAME
-+/* sdbm 3h
-+/* SUMMARY
-+/* SDBM Simple DBM: ndbm work-alike hashed database library
-+/* SYNOPSIS
-+/* include "sdbm.h"
-+/* DESCRIPTION
-+/* This file includes the public domain SDBM (ndbm work-alike hashed
-+/* database library), based on Per-Aake Larson's Dynamic Hashing
-+/* algorithms. BIT 18 (1978).
-+/* author: oz@nexus.yorku.ca
-+/* status: public domain
-+/* The file has been patched following the advice of Uwe Ohse
-+/* <uwe@ohse.de>:
-+/* --------------------------------------------------------------
-+/* this patch fixes a problem with sdbms .dir file, which arrises when
-+/* a second .dir block is needed for the first time. read() returns 0
-+/* in that case, and the library forgot to initialize that new block.
-+/*
-+/* A related problem is that the calculation of db->maxbno is wrong.
-+/* It just appends 4096*BYTESIZ bits, which is not enough except for
-+/* small databases (.dir basically doubles everytime it's too small).
-+/* --------------------------------------------------------------
-+/* According to Uwe Ohse, the patch has also been submitted to the
-+/* author of SDBM. (The 4096*BYTESIZ bits comment may apply with a
-+/* different size for Postfix/TLS, as the patch was sent against the
-+/* original SDBM distributiona and for Postfix/TLS I have changed the
-+/* default sizes.
-+/* .nf
-+/*--*/
-+
-+/*
-+ * sdbm - ndbm work-alike hashed database library
-+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
-+ * author: oz@nexus.yorku.ca
-+ * status: public domain.
-+ *
-+ * core routines
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#ifdef WIN32
-+#include <io.h>
-+#include <errno.h>
-+#else
-+#include <unistd.h>
-+#endif
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <errno.h>
-+#include <string.h>
-+#ifdef __STDC__
-+#include <stddef.h>
-+#endif
-+
-+#include <sdbm.h>
-+
-+/*
-+ * useful macros
-+ */
-+#define bad(x) ((x).dptr == NULL || (x).dsize <= 0)
-+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
-+#define ioerr(db) ((db)->flags |= DBM_IOERR)
-+
-+#define OFF_PAG(off) (long) (off) * PBLKSIZ
-+#define OFF_DIR(off) (long) (off) * DBLKSIZ
-+
-+static long masks[] =
-+{
-+ 000000000000, 000000000001, 000000000003, 000000000007,
-+ 000000000017, 000000000037, 000000000077, 000000000177,
-+ 000000000377, 000000000777, 000000001777, 000000003777,
-+ 000000007777, 000000017777, 000000037777, 000000077777,
-+ 000000177777, 000000377777, 000000777777, 000001777777,
-+ 000003777777, 000007777777, 000017777777, 000037777777,
-+ 000077777777, 000177777777, 000377777777, 000777777777,
-+ 001777777777, 003777777777, 007777777777, 017777777777
-+};
-+
-+datum nullitem =
-+{NULL, 0};
-+
-+typedef struct
-+{
-+ int dirf; /* directory file descriptor */
-+ int pagf; /* page file descriptor */
-+ int flags; /* status/error flags, see below */
-+ long maxbno; /* size of dirfile in bits */
-+ long curbit; /* current bit number */
-+ long hmask; /* current hash mask */
-+ long blkptr; /* current block for nextkey */
-+ int keyptr; /* current key for nextkey */
-+ long blkno; /* current page to read/write */
-+ long pagbno; /* current page in pagbuf */
-+ char *pagbuf; /* page file block buffer */
-+ long dirbno; /* current block in dirbuf */
-+ char *dirbuf; /* directory file block buffer */
-+} DBM;
-+
-+
-+/* ************************* */
-+
-+/*
-+ * sdbm - ndbm work-alike hashed database library
-+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
-+ * author: oz@nexus.yorku.ca
-+ * status: public domain. keep it that way.
-+ *
-+ * hashing routine
-+ */
-+
-+/*
-+ * polynomial conversion ignoring overflows
-+ * [this seems to work remarkably well, in fact better
-+ * then the ndbm hash function. Replace at your own risk]
-+ * use: 65599 nice.
-+ * 65587 even better.
-+ */
-+static long sdbm_hash (char *str, int len)
-+{
-+ unsigned long n = 0;
-+
-+#ifdef DUFF
-+#define HASHC n = *str++ + 65599 * n
-+ if (len > 0)
-+ {
-+ int loop = (len + 8 - 1) >> 3;
-+
-+ switch (len & (8 - 1))
-+ {
-+ case 0:
-+ do
-+ {
-+ HASHC;
-+ case 7:
-+ HASHC;
-+ case 6:
-+ HASHC;
-+ case 5:
-+ HASHC;
-+ case 4:
-+ HASHC;
-+ case 3:
-+ HASHC;
-+ case 2:
-+ HASHC;
-+ case 1:
-+ HASHC;
-+ }
-+ while (--loop);
-+ }
-+
-+ }
-+#else
-+ while (len--)
-+ n = *str++ + 65599 * n;
-+#endif
-+ return n;
-+}
-+
-+/*
-+ * check page sanity:
-+ * number of entries should be something
-+ * reasonable, and all offsets in the index should be in order.
-+ * this could be made more rigorous.
-+ */
-+static int chkpage (char *pag)
-+{
-+ int n;
-+ int off;
-+ short *ino = (short *) pag;
-+
-+ if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof (short))
-+ return 0;
-+
-+ if (n > 0)
-+ {
-+ off = PBLKSIZ;
-+ for (ino++; n > 0; ino += 2)
-+ {
-+ if (ino[0] > off || ino[1] > off ||
-+ ino[1] > ino[0])
-+ return 0;
-+ off = ino[1];
-+ n -= 2;
-+ }
-+ }
-+ return 1;
-+}
-+
-+/*
-+ * search for the key in the page.
-+ * return offset index in the range 0 < i < n.
-+ * return 0 if not found.
-+ */
-+static int seepair (char *pag, int n, char *key, int siz)
-+{
-+ int i;
-+ int off = PBLKSIZ;
-+ short *ino = (short *) pag;
-+
-+ for (i = 1; i < n; i += 2)
-+ {
-+ if (siz == off - ino[i] &&
-+ memcmp (key, pag + ino[i], siz) == 0)
-+ return i;
-+ off = ino[i + 1];
-+ }
-+ return 0;
-+}
-+
-+#ifdef SEEDUPS
-+static int duppair (char *pag, datum key)
-+{
-+ short *ino = (short *) pag;
-+
-+ return ino[0] > 0 && seepair (pag, ino[0], key.dptr, key.dsize) > 0;
-+}
-+
-+#endif
-+
-+/* ************************* */
-+
-+/*
-+ * sdbm - ndbm work-alike hashed database library
-+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
-+ * author: oz@nexus.yorku.ca
-+ * status: public domain.
-+ *
-+ * page-level routines
-+ */
-+
-+/*
-+ * page format:
-+ * +------------------------------+
-+ * ino | n | keyoff | datoff | keyoff |
-+ * +------------+--------+--------+
-+ * | datoff | - - - ----> |
-+ * +--------+---------------------+
-+ * | F R E E A R E A |
-+ * +--------------+---------------+
-+ * | <---- - - - | data |
-+ * +--------+-----+----+----------+
-+ * | key | data | key |
-+ * +--------+----------+----------+
-+ *
-+ * calculating the offsets for free area: if the number
-+ * of entries (ino[0]) is zero, the offset to the END of
-+ * the free area is the block size. Otherwise, it is the
-+ * nth (ino[ino[0]]) entry's offset.
-+ */
-+
-+static int fitpair (char *pag, int need)
-+{
-+ int n;
-+ int off;
-+ int avail;
-+ short *ino = (short *) pag;
-+
-+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
-+ avail = off - (n + 1) * sizeof (short);
-+ need += 2 * sizeof (short);
-+
-+ return need <= avail;
-+}
-+
-+static void putpair (char *pag, datum key, datum val)
-+{
-+ int n;
-+ int off;
-+ short *ino = (short *) pag;
-+
-+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
-+/*
-+ * enter the key first
-+ */
-+ off -= key.dsize;
-+ (void) memcpy (pag + off, key.dptr, key.dsize);
-+ ino[n + 1] = off;
-+/*
-+ * now the data
-+ */
-+ off -= val.dsize;
-+ (void) memcpy (pag + off, val.dptr, val.dsize);
-+ ino[n + 2] = off;
-+/*
-+ * adjust item count
-+ */
-+ ino[0] += 2;
-+}
-+
-+static datum getpair (char *pag, datum key)
-+{
-+ int i;
-+ int n;
-+ datum val;
-+ short *ino = (short *) pag;
-+
-+ if ((n = ino[0]) == 0)
-+ return nullitem;
-+
-+ if ((i = seepair (pag, n, key.dptr, key.dsize)) == 0)
-+ return nullitem;
-+
-+ val.dptr = pag + ino[i + 1];
-+ val.dsize = ino[i] - ino[i + 1];
-+ return val;
-+}
-+
-+static datum getnkey (char *pag, int num)
-+{
-+ datum key;
-+ int off;
-+ short *ino = (short *) pag;
-+
-+ num = num * 2 - 1;
-+ if (ino[0] == 0 || num > ino[0])
-+ return nullitem;
-+
-+ off = (num > 1) ? ino[num - 1] : PBLKSIZ;
-+
-+ key.dptr = pag + ino[num];
-+ key.dsize = off - ino[num];
-+
-+ return key;
-+}
-+
-+static int delpair (char *pag, datum key)
-+{
-+ int n;
-+ int i;
-+ short *ino = (short *) pag;
-+
-+ if ((n = ino[0]) == 0)
-+ return 0;
-+
-+ if ((i = seepair (pag, n, key.dptr, key.dsize)) == 0)
-+ return 0;
-+/*
-+ * found the key. if it is the last entry
-+ * [i.e. i == n - 1] we just adjust the entry count.
-+ * hard case: move all data down onto the deleted pair,
-+ * shift offsets onto deleted offsets, and adjust them.
-+ * [note: 0 < i < n]
-+ */
-+ if (i < n - 1)
-+ {
-+ int m;
-+ char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
-+ char *src = pag + ino[i + 1];
-+ int zoo = dst - src;
-+
-+/*
-+ * shift data/keys down
-+ */
-+ m = ino[i + 1] - ino[n];
-+#ifdef DUFF
-+#define MOVB *--dst = *--src
-+ if (m > 0)
-+ {
-+ int loop = (m + 8 - 1) >> 3;
-+
-+ switch (m & (8 - 1))
-+ {
-+ case 0:
-+ do
-+ {
-+ MOVB;
-+ case 7:
-+ MOVB;
-+ case 6:
-+ MOVB;
-+ case 5:
-+ MOVB;
-+ case 4:
-+ MOVB;
-+ case 3:
-+ MOVB;
-+ case 2:
-+ MOVB;
-+ case 1:
-+ MOVB;
-+ }
-+ while (--loop);
-+ }
-+ }
-+#else
-+ dst -= m;
-+ src -= m;
-+ memmove (dst, src, m);
-+#endif
-+/*
-+ * adjust offset index up
-+ */
-+ while (i < n - 1)
-+ {
-+ ino[i] = ino[i + 2] + zoo;
-+ i++;
-+ }
-+ }
-+ ino[0] -= 2;
-+ return 1;
-+}
-+
-+static void splpage (char *pag, char *new, long sbit)
-+{
-+ datum key;
-+ datum val;
-+
-+ int n;
-+ int off = PBLKSIZ;
-+ char cur[PBLKSIZ];
-+ short *ino = (short *) cur;
-+
-+ (void) memcpy (cur, pag, PBLKSIZ);
-+ (void) memset (pag, 0, PBLKSIZ);
-+ (void) memset (new, 0, PBLKSIZ);
-+
-+ n = ino[0];
-+ for (ino++; n > 0; ino += 2)
-+ {
-+ key.dptr = cur + ino[0];
-+ key.dsize = off - ino[0];
-+ val.dptr = cur + ino[1];
-+ val.dsize = ino[0] - ino[1];
-+/*
-+ * select the page pointer (by looking at sbit) and insert
-+ */
-+ (void) putpair ((exhash (key) & sbit) ? new : pag, key, val);
-+
-+ off = ino[1];
-+ n -= 2;
-+ }
-+}
-+
-+static int getdbit (DBM * db, long dbit)
-+{
-+ long c;
-+ long dirb;
-+
-+ c = dbit / BYTESIZ;
-+ dirb = c / DBLKSIZ;
-+
-+ if (dirb != db->dirbno)
-+ {
-+ int got;
-+ if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
-+ || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0)
-+ return 0;
-+ if (got==0)
-+ memset(db->dirbuf,0,DBLKSIZ);
-+ db->dirbno = dirb;
-+ }
-+
-+ return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
-+}
-+
-+static int setdbit (DBM * db, long dbit)
-+{
-+ long c;
-+ long dirb;
-+
-+ c = dbit / BYTESIZ;
-+ dirb = c / DBLKSIZ;
-+
-+ if (dirb != db->dirbno)
-+ {
-+ int got;
-+ if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
-+ || (got = read(db->dirf, db->dirbuf, DBLKSIZ)) < 0)
-+ return 0;
-+ if (got==0)
-+ memset(db->dirbuf,0,DBLKSIZ);
-+ db->dirbno = dirb;
-+ }
-+
-+ db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
-+
-+#if 0
-+ if (dbit >= db->maxbno)
-+ db->maxbno += DBLKSIZ * BYTESIZ;
-+#else
-+ if (OFF_DIR((dirb+1))*BYTESIZ > db->maxbno)
-+ db->maxbno=OFF_DIR((dirb+1))*BYTESIZ;
-+#endif
-+
-+ if (lseek (db->dirf, OFF_DIR (dirb), SEEK_SET) < 0
-+ || write (db->dirf, db->dirbuf, DBLKSIZ) < 0)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/*
-+ * getnext - get the next key in the page, and if done with
-+ * the page, try the next page in sequence
-+ */
-+static datum getnext (DBM * db)
-+{
-+ datum key;
-+
-+ for (;;)
-+ {
-+ db->keyptr++;
-+ key = getnkey (db->pagbuf, db->keyptr);
-+ if (key.dptr != NULL)
-+ return key;
-+/*
-+ * we either run out, or there is nothing on this page..
-+ * try the next one... If we lost our position on the
-+ * file, we will have to seek.
-+ */
-+ db->keyptr = 0;
-+ if (db->pagbno != db->blkptr++)
-+ if (lseek (db->pagf, OFF_PAG (db->blkptr), SEEK_SET) < 0)
-+ break;
-+ db->pagbno = db->blkptr;
-+ if (read (db->pagf, db->pagbuf, PBLKSIZ) <= 0)
-+ break;
-+ if (!chkpage (db->pagbuf))
-+ break;
-+ }
-+
-+ return ioerr (db), nullitem;
-+}
-+
-+/*
-+ * all important binary trie traversal
-+ */
-+static int getpage (DBM * db, long hash)
-+{
-+ int hbit;
-+ long dbit;
-+ long pagb;
-+
-+ dbit = 0;
-+ hbit = 0;
-+ while (dbit < db->maxbno && getdbit (db, dbit))
-+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
-+
-+ db->curbit = dbit;
-+ db->hmask = masks[hbit];
-+
-+ pagb = hash & db->hmask;
-+/*
-+ * see if the block we need is already in memory.
-+ * note: this lookaside cache has about 10% hit rate.
-+ */
-+ if (pagb != db->pagbno)
-+ {
-+/*
-+ * note: here, we assume a "hole" is read as 0s.
-+ * if not, must zero pagbuf first.
-+ */
-+ if (lseek (db->pagf, OFF_PAG (pagb), SEEK_SET) < 0
-+ || read (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ return 0;
-+ if (!chkpage (db->pagbuf))
-+ return 0;
-+ db->pagbno = pagb;
-+ }
-+ return 1;
-+}
-+
-+/*
-+ * makroom - make room by splitting the overfull page
-+ * this routine will attempt to make room for SPLTMAX times before
-+ * giving up.
-+ */
-+static int makroom (DBM * db, long hash, int need)
-+{
-+ long newp;
-+ char twin[PBLKSIZ];
-+ char *pag = db->pagbuf;
-+ char *new = twin;
-+ int smax = SPLTMAX;
-+
-+ do
-+ {
-+/*
-+ * split the current page
-+ */
-+ (void) splpage (pag, new, db->hmask + 1);
-+/*
-+ * address of the new page
-+ */
-+ newp = (hash & db->hmask) | (db->hmask + 1);
-+
-+/*
-+ * write delay, read avoidence/cache shuffle:
-+ * select the page for incoming pair: if key is to go to the new page,
-+ * write out the previous one, and copy the new one over, thus making
-+ * it the current page. If not, simply write the new page, and we are
-+ * still looking at the page of interest. current page is not updated
-+ * here, as sdbm_store will do so, after it inserts the incoming pair.
-+ */
-+ if (hash & (db->hmask + 1))
-+ {
-+ if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
-+ || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ return 0;
-+ db->pagbno = newp;
-+ (void) memcpy (pag, new, PBLKSIZ);
-+ }
-+ else if (lseek (db->pagf, OFF_PAG (newp), SEEK_SET) < 0
-+ || write (db->pagf, new, PBLKSIZ) < 0)
-+ return 0;
-+
-+ if (!setdbit (db, db->curbit))
-+ return 0;
-+/*
-+ * see if we have enough room now
-+ */
-+ if (fitpair (pag, need))
-+ return 1;
-+/*
-+ * try again... update curbit and hmask as getpage would have
-+ * done. because of our update of the current page, we do not
-+ * need to read in anything. BUT we have to write the current
-+ * [deferred] page out, as the window of failure is too great.
-+ */
-+ db->curbit = 2 * db->curbit +
-+ ((hash & (db->hmask + 1)) ? 2 : 1);
-+ db->hmask |= db->hmask + 1;
-+
-+ if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
-+ || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ return 0;
-+
-+ }
-+ while (--smax);
-+/*
-+ * if we are here, this is real bad news. After SPLTMAX splits,
-+ * we still cannot fit the key. say goodnight.
-+ */
-+#ifdef BADMESS
-+ (void) write (2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
-+#endif
-+ return 0;
-+
-+}
-+
-+static SDBM *sdbm_prep (char *dirname, char *pagname, int flags, int mode)
-+{
-+ SDBM *db;
-+ struct stat dstat;
-+
-+ if ((db = (SDBM *) mymalloc (sizeof (SDBM))) == NULL)
-+ return errno = ENOMEM, (SDBM *) NULL;
-+
-+ db->flags = 0;
-+ db->blkptr = 0;
-+ db->keyptr = 0;
-+/*
-+ * adjust user flags so that WRONLY becomes RDWR,
-+ * as required by this package. Also set our internal
-+ * flag for RDONLY if needed.
-+ */
-+ if (flags & O_WRONLY)
-+ flags = (flags & ~O_WRONLY) | O_RDWR;
-+ else if ((flags & 03) == O_RDONLY)
-+ db->flags = DBM_RDONLY;
-+#if defined(OS2) || defined(MSDOS) || defined(WIN32)
-+ flags |= O_BINARY;
-+#endif
-+
-+/*
-+ * Make sure to ignore the O_EXCL option, as the file might exist due
-+ * to the locking.
-+ */
-+ flags &= ~O_EXCL;
-+
-+/*
-+ * open the files in sequence, and stat the dirfile.
-+ * If we fail anywhere, undo everything, return NULL.
-+ */
-+
-+ if ((db->pagf = open (pagname, flags, mode)) > -1)
-+ {
-+ if ((db->dirf = open (dirname, flags, mode)) > -1)
-+ {
-+/*
-+ * need the dirfile size to establish max bit number.
-+ */
-+ if (fstat (db->dirf, &dstat) == 0)
-+ {
-+ /*
-+ * success
-+ */
-+ return db;
-+ }
-+ msg_info ("closing dirf");
-+ (void) close (db->dirf);
-+ }
-+ msg_info ("closing pagf");
-+ (void) close (db->pagf);
-+ }
-+ myfree ((char *) db);
-+ return (SDBM *) NULL;
-+}
-+
-+static DBM *sdbm_internal_open (SDBM * sdbm)
-+{
-+ DBM *db;
-+ struct stat dstat;
-+
-+ if ((db = (DBM *) mymalloc (sizeof (DBM))) == NULL)
-+ return errno = ENOMEM, (DBM *) NULL;
-+
-+ db->flags = sdbm->flags;
-+ db->hmask = 0;
-+ db->blkptr = sdbm->blkptr;
-+ db->keyptr = sdbm->keyptr;
-+ db->pagf = sdbm->pagf;
-+ db->dirf = sdbm->dirf;
-+ db->pagbuf = sdbm->pagbuf;
-+ db->dirbuf = sdbm->dirbuf;
-+
-+/*
-+ * need the dirfile size to establish max bit number.
-+ */
-+ if (fstat (db->dirf, &dstat) == 0)
-+ {
-+/*
-+ * zero size: either a fresh database, or one with a single,
-+ * unsplit data page: dirpage is all zeros.
-+ */
-+ db->dirbno = (!dstat.st_size) ? 0 : -1;
-+ db->pagbno = -1;
-+ db->maxbno = dstat.st_size * BYTESIZ;
-+
-+ (void) memset (db->pagbuf, 0, PBLKSIZ);
-+ (void) memset (db->dirbuf, 0, DBLKSIZ);
-+ return db;
-+ }
-+ myfree ((char *) db);
-+ return (DBM *) NULL;
-+}
-+
-+static void sdbm_internal_close (DBM * db)
-+{
-+ if (db == NULL)
-+ errno = EINVAL;
-+ else
-+ {
-+ myfree ((char *) db);
-+ }
-+}
-+
-+datum sdbm_fetch (SDBM * sdb, datum key)
-+{
-+ datum retval;
-+ DBM *db;
-+
-+ if (sdb == NULL || bad (key))
-+ return errno = EINVAL, nullitem;
-+
-+ if (!(db = sdbm_internal_open (sdb)))
-+ return errno = EINVAL, nullitem;
-+
-+ if (getpage (db, exhash (key)))
-+ {
-+ retval = getpair (db->pagbuf, key);
-+ sdbm_internal_close (db);
-+ return retval;
-+ }
-+
-+ sdbm_internal_close (db);
-+
-+ return ioerr (sdb), nullitem;
-+}
-+
-+int sdbm_delete (SDBM * sdb, datum key)
-+{
-+ int retval;
-+ DBM *db;
-+
-+ if (sdb == NULL || bad (key))
-+ return errno = EINVAL, -1;
-+ if (sdbm_rdonly (sdb))
-+ return errno = EPERM, -1;
-+
-+ if (!(db = sdbm_internal_open (sdb)))
-+ return errno = EINVAL, -1;
-+
-+ if (getpage (db, exhash (key)))
-+ {
-+ if (!delpair (db->pagbuf, key))
-+ retval = -1;
-+/*
-+ * update the page file
-+ */
-+ else if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
-+ || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ retval = ioerr (sdb), -1;
-+ else
-+ retval = 0;
-+ }
-+ else
-+ retval = ioerr (sdb), -1;
-+
-+ sdbm_internal_close (db);
-+
-+ return retval;
-+}
-+
-+int sdbm_store (SDBM * sdb, datum key, datum val, int flags)
-+{
-+ int need;
-+ int retval;
-+ long hash;
-+ DBM *db;
-+
-+ if (sdb == NULL || bad (key))
-+ return errno = EINVAL, -1;
-+ if (sdbm_rdonly (sdb))
-+ return errno = EPERM, -1;
-+
-+ need = key.dsize + val.dsize;
-+/*
-+ * is the pair too big (or too small) for this database ??
-+ */
-+ if (need < 0 || need > PAIRMAX)
-+ return errno = EINVAL, -1;
-+
-+ if (!(db = sdbm_internal_open (sdb)))
-+ return errno = EINVAL, -1;
-+
-+ if (getpage (db, (hash = exhash (key))))
-+ {
-+/*
-+ * if we need to replace, delete the key/data pair
-+ * first. If it is not there, ignore.
-+ */
-+ if (flags == DBM_REPLACE)
-+ (void) delpair (db->pagbuf, key);
-+#ifdef SEEDUPS
-+ else if (duppair (db->pagbuf, key))
-+ {
-+ sdbm_internal_close (db);
-+ return 1;
-+ }
-+#endif
-+/*
-+ * if we do not have enough room, we have to split.
-+ */
-+ if (!fitpair (db->pagbuf, need))
-+ if (!makroom (db, hash, need))
-+ {
-+ sdbm_internal_close (db);
-+ return ioerr (db), -1;
-+ }
-+/*
-+ * we have enough room or split is successful. insert the key,
-+ * and update the page file.
-+ */
-+ (void) putpair (db->pagbuf, key, val);
-+
-+ if (lseek (db->pagf, OFF_PAG (db->pagbno), SEEK_SET) < 0
-+ || write (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ {
-+ sdbm_internal_close (db);
-+ return ioerr (db), -1;
-+ }
-+ /*
-+ * success
-+ */
-+ sdbm_internal_close (db);
-+ return 0;
-+ }
-+
-+ sdbm_internal_close (db);
-+ return ioerr (sdb), -1;
-+}
-+
-+/*
-+ * the following two routines will break if
-+ * deletions aren't taken into account. (ndbm bug)
-+ */
-+datum sdbm_firstkey (SDBM * sdb)
-+{
-+ datum retval;
-+ DBM *db;
-+
-+ if (sdb == NULL)
-+ return errno = EINVAL, nullitem;
-+
-+ if (!(db = sdbm_internal_open (sdb)))
-+ return errno = EINVAL, nullitem;
-+
-+/*
-+ * start at page 0
-+ */
-+ if (lseek (db->pagf, OFF_PAG (0), SEEK_SET) < 0
-+ || read (db->pagf, db->pagbuf, PBLKSIZ) < 0)
-+ {
-+ sdbm_internal_close (db);
-+ return ioerr (sdb), nullitem;
-+ }
-+ db->pagbno = 0;
-+ db->blkptr = 0;
-+ db->keyptr = 0;
-+
-+ retval = getnext (db);
-+ sdb->blkptr = db->blkptr;
-+ sdb->keyptr = db->keyptr;
-+ sdbm_internal_close (db);
-+ return retval;
-+}
-+
-+datum sdbm_nextkey (SDBM * sdb)
-+{
-+ datum retval;
-+ DBM *db;
-+
-+ if (sdb == NULL)
-+ return errno = EINVAL, nullitem;
-+
-+ if (!(db = sdbm_internal_open (sdb)))
-+ return errno = EINVAL, nullitem;
-+
-+ retval = getnext (db);
-+ sdb->blkptr = db->blkptr;
-+ sdb->keyptr = db->keyptr;
-+ sdbm_internal_close (db);
-+ return retval;
-+}
-+
-+void sdbm_close (SDBM * db)
-+{
-+ if (db == NULL)
-+ errno = EINVAL;
-+ else
-+ {
-+ (void) close (db->dirf);
-+ (void) close (db->pagf);
-+ myfree ((char *) db);
-+ }
-+}
-+
-+SDBM *sdbm_open (char *file, int flags, int mode)
-+{
-+ SDBM *db;
-+ char *dirname;
-+ char *pagname;
-+ int n;
-+
-+ if (file == NULL || !*file)
-+ return errno = EINVAL, (SDBM *) NULL;
-+/*
-+ * need space for two seperate filenames
-+ */
-+ n = strlen (file) * 2 + strlen (DIRFEXT) + strlen (PAGFEXT) + 2;
-+
-+ if ((dirname = (char *) mymalloc ((unsigned) n)) == NULL)
-+ return errno = ENOMEM, (SDBM *) NULL;
-+/*
-+ * build the file names
-+ */
-+ dirname = strcat (strcpy (dirname, file), DIRFEXT);
-+ pagname = strcpy (dirname + strlen (dirname) + 1, file);
-+ pagname = strcat (pagname, PAGFEXT);
-+
-+ db = sdbm_prep (dirname, pagname, flags, mode);
-+ myfree ((char *) dirname);
-+ return db;
-+}
-+
-diff -Pur postfix-1.1.11-20020613-orig/src/util/sdbm.h postfix-1.1.11-20020613/src/util/sdbm.h
---- postfix-1.1.11-20020613-orig/src/util/sdbm.h Thu Jan 1 01:00:00 1970
-+++ postfix-1.1.11-20020613/src/util/sdbm.h Wed Jun 26 15:26:49 2002
-@@ -0,0 +1,97 @@
-+/*++
-+/* NAME
-+/* sdbm 3h
-+/* SUMMARY
-+/* SDBM Simple DBM: ndbm work-alike hashed database library
-+/* SYNOPSIS
-+/* include "sdbm.h"
-+/* DESCRIPTION
-+/* .nf
-+/*--*/
-+
-+#ifndef UTIL_SDBM_H
-+#define UTIL_SDBM_H
-+
-+/*
-+ * sdbm - ndbm work-alike hashed database library
-+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
-+ * author: oz@nexus.yorku.ca
-+ * status: public domain.
-+ */
-+
-+#define DUFF /* go ahead and use the loop-unrolled version */
-+
-+#include <stdio.h>
-+
-+#define DBLKSIZ 16384 /* SSL cert chains require more */
-+#define PBLKSIZ 8192 /* SSL cert chains require more */
-+#define PAIRMAX 8008 /* arbitrary on PBLKSIZ-N */
-+#define SPLTMAX 10 /* maximum allowed splits */
-+ /* for a single insertion */
-+#define DIRFEXT ".dir"
-+#define PAGFEXT ".pag"
-+
-+typedef struct {
-+ int dirf; /* directory file descriptor */
-+ int pagf; /* page file descriptor */
-+ int flags; /* status/error flags, see below */
-+ long blkptr; /* current block for nextkey */
-+ int keyptr; /* current key for nextkey */
-+ char pagbuf[PBLKSIZ]; /* page file block buffer */
-+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
-+} SDBM;
-+
-+#define DBM_RDONLY 0x1 /* data base open read-only */
-+#define DBM_IOERR 0x2 /* data base I/O error */
-+
-+/*
-+ * utility macros
-+ */
-+#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
-+#define sdbm_error(db) ((db)->flags & DBM_IOERR)
-+
-+#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
-+
-+#define sdbm_dirfno(db) ((db)->dirf)
-+#define sdbm_pagfno(db) ((db)->pagf)
-+
-+typedef struct {
-+ char *dptr;
-+ int dsize;
-+} datum;
-+
-+extern datum nullitem;
-+
-+/*
-+ * flags to sdbm_store
-+ */
-+#define DBM_INSERT 0
-+#define DBM_REPLACE 1
-+
-+/*
-+ * ndbm interface
-+ */
-+extern SDBM *sdbm_open(char *, int, int);
-+extern void sdbm_close(SDBM *);
-+extern datum sdbm_fetch(SDBM *, datum);
-+extern int sdbm_delete(SDBM *, datum);
-+extern int sdbm_store(SDBM *, datum, datum, int);
-+extern datum sdbm_firstkey(SDBM *);
-+extern datum sdbm_nextkey(SDBM *);
-+
-+/*
-+ * sdbm - ndbm work-alike hashed database library
-+ * tuning and portability constructs [not nearly enough]
-+ * author: oz@nexus.yorku.ca
-+ */
-+
-+#define BYTESIZ 8
-+
-+/*
-+ * important tuning parms (hah)
-+ */
-+
-+#define SEEDUPS /* always detect duplicates */
-+#define BADMESS /* generate a message for worst case:
-+ cannot make room after SPLTMAX splits */
-+#endif /* UTIL_SDBM_H */
-diff -Pur postfix-1.1.11-20020613-orig/src/util/sys_defs.h postfix-1.1.11-20020613/src/util/sys_defs.h
---- postfix-1.1.11-20020613-orig/src/util/sys_defs.h Mon Apr 15 23:56:08 2002
-+++ postfix-1.1.11-20020613/src/util/sys_defs.h Wed Jun 26 15:26:49 2002
-@@ -73,6 +73,10 @@
- #define DEF_MAILBOX_LOCK "flock, dotlock"
- #endif
-
-+#if ((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) || defined(USAGI_LIBINET6))
-+#define HAVE_GETIFADDRS
-+#endif
-+
- /*
- * UNIX on MAC.
- */
-diff -Pur postfix-1.1.11-20020613-orig/src/util/valid_hostname.c postfix-1.1.11-20020613/src/util/valid_hostname.c
---- postfix-1.1.11-20020613-orig/src/util/valid_hostname.c Sun Jan 28 15:10:18 2001
-+++ postfix-1.1.11-20020613/src/util/valid_hostname.c Wed Jun 26 15:26:49 2002
-@@ -47,6 +47,13 @@
- #include <string.h>
- #include <ctype.h>
-
-+#ifdef INET6
-+#include <netinet/in.h>
-+#include <sys/socket.h>
-+#include <arpa/inet.h>
-+#include <netdb.h>
-+#endif
-+
- /* Utility library. */
-
- #include "msg.h"
-@@ -103,7 +110,23 @@
- msg_warn("%s: misplaced hyphen: %.100s", myname, name);
- return (0);
- }
-- } else {
-+ }
-+#ifdef INET6
-+ else if (ch == ':') {
-+ struct addrinfo hints, *res;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = AF_INET6;
-+ hints.ai_socktype = SOCK_STREAM; /*dummy*/
-+ hints.ai_flags = AI_NUMERICHOST;
-+ if (getaddrinfo(name, "0", &hints, &res) == 0) {
-+ freeaddrinfo(res);
-+ return 1;
-+ } else
-+ return 0;
-+ }
-+#endif
-+ else {
- if (gripe)
- msg_warn("%s: invalid character %d(decimal): %.100s",
- myname, ch, name);
-@@ -135,6 +158,9 @@
- int byte_count = 0;
- int byte_val = 0;
- int ch;
-+#ifdef INET6
-+ struct addrinfo hints, *res;
-+#endif
-
- #define BYTES_NEEDED 4
-
-@@ -146,6 +172,17 @@
- msg_warn("%s: empty address", myname);
- return (0);
- }
-+
-+#ifdef INET6
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = AF_INET6;
-+ hints.ai_socktype = SOCK_STREAM; /*dummy*/
-+ hints.ai_flags = AI_NUMERICHOST;
-+ if (getaddrinfo(addr, "0", &hints, &res) == 0) {
-+ freeaddrinfo(res);
-+ return 1;
-+ }
-+#endif
-
- /*
- * Scary code to avoid sscanf() overflow nasties.
diff --git a/net-mail/postfix/postfix-1.1.11-r4.ebuild b/net-mail/postfix/postfix-1.1.11-r4.ebuild
deleted file mode 100644
index fcf0b1b9e37e..000000000000
--- a/net-mail/postfix/postfix-1.1.11-r4.ebuild
+++ /dev/null
@@ -1,185 +0,0 @@
-# Copyright 1999-2002 Gentoo Technologies, Inc.
-# Distributed under the terms of the GNU General Public License, v2 or later
-# $Header: /var/cvsroot/gentoo-x86/net-mail/postfix/postfix-1.1.11-r4.ebuild,v 1.3 2002/08/14 12:05:25 murphy Exp $
-
-DESCRIPTION="A fast and secure drop-in replacement for sendmail"
-HOMEPAGE="http://www.postfix.org/"
-LICENSE="IPL-1"
-SLOT="0"
-KEYWORDS="x86 sparc sparc64"
-
-POSTFIX_TLS_VER="0.8.11a-${PV}-0.9.6d"
-
-S=${WORKDIR}/${P}
-SRC_URI="ftp://ftp.porcupine.org/mirrors/postfix-release/official/${P}.tar.gz
- ssl? ( ftp://ftp.aet.tu-cottbus.de/pub/postfix_tls/pfixtls-${POSTFIX_TLS_VER}.tar.gz )"
-
-PROVIDE="virtual/mta"
-DEPEND=">=sys-libs/db-3.2
- >=dev-libs/libpcre-3.4
- sasl? ( >=dev-libs/cyrus-sasl-1.5.27 )
- ldap? ( >=net-nds/openldap-1.2 )
- mysql? ( >=dev-db/mysql-3.23.28 )
- ssl? ( >=dev-libs/openssl-0.9.6d )"
-RDEPEND="${DEPEND}
- >=net-mail/mailbase-0.00
- !virtual/mta"
-
-postfix_installed=no
-
-pkg_setup() {
- if ! grep -q ^postdrop: /etc/group ; then
- groupadd postdrop || die "problem adding group postdrop"
- fi
-
- # is there an existing postfix installation?
- if [ -d /etc/postfix ] ; then
- postfix_installed=yes
- fi
-}
-
-src_unpack() {
- unpack ${A}
-
- use ssl && ( \
- cd ${S}
- patch -p1 < ${WORKDIR}/pfixtls-${POSTFIX_TLS_VER}/pfixtls.diff || die
- )
-
- if [ "`use sasl`" ]
- then
- if [ ! -e /usr/include/sasl.h ]
- then
- # saslv2
- cd ${S}
- patch -p1 < ${FILESDIR}/postfix-1.1.11-saslv2.diff || die
- fi
- fi
- cd ${S}/conf
- cp main.cf main.cf.orig
- sed -e "s:/usr/libexec/postfix:/usr/lib/postfix:" main.cf.orig > main.cf
-
- cd ${S}/src/global
- cp mail_params.h mail_params.h.orig
- sed -e "s:/usr/libexec/postfix:/usr/lib/postfix:" mail_params.h.orig > mail_params.h
-
- use mysql \
- && CCARGS="${CCARGS} -DHAS_MYSQL -I/usr/include/mysql" \
- && AUXLIBS="${AUXLIBS} -lmysqlclient -lm"
-
- use ldap \
- && CCARGS="${CCARGS} -DHAS_LDAP" \
- && AUXLIBS="${AUXLIBS} -lldap -llber"
-
- use ssl \
- && CCARGS="${CCARGS} -DHAS_SSL" \
- && AUXLIBS="${AUXLIBS} -lssl"
-
- # note: if sasl is built w/ pam, then postfix _MUST_ be built w/ pam
- use pam && AUXLIBS="${AUXLIBS} -lpam"
-
- # stuff we always want...
- CCARGS="${CCARGS} -I/usr/include -DHAS_PCRE"
- AUXLIBS="${AUXLIBS} -L/usr/lib -lpcre -ldl -lcrypt"
- if [ "`use sasl`" ]
- then
- if [ -e /usr/include/sasl.h ]
- then
- # saslv1 seems to be installed. To not break existing installations,
- # we use this
- AUXLIBS="${AUXLIBS} -lsasl"
- CCARGS="${CCARGS} -DUSE_SASL_AUTH"
- else
- # Seems to be saslv2
- AUXLIBS="${AUXLIBS} -lsasl2"
- CCARGS="${CCARGS} -I/usr/include/sasl -DUSE_SASL_AUTH"
- fi
- fi
- DEBUG=""
-
- cd ${S}
- make tidy || die
- make makefiles CC="cc" OPT="${CFLAGS}" DEBUG="${DEBUG}" \
- CCARGS="${CCARGS}" AUXLIBS="${AUXLIBS}" || die
-}
-
-src_compile() {
- emake || die "compile problem"
-}
-
-src_install () {
- dodir /usr/bin /usr/sbin /usr/lib/postfix /etc/postfix/sample
-
- cd ${S}/bin
- dosbin post* sendmail
- chown root.postdrop ${D}/usr/sbin/{postdrop,postqueue}
- chmod 2755 ${D}/usr/sbin/{postdrop,postqueue}
-
- dosym /usr/sbin/sendmail /usr/bin/mailq
- dosym /usr/sbin/sendmail /usr/bin/newaliases
- dosym /usr/sbin/sendmail /usr/lib/sendmail
-
- cd ${S}/libexec
- exeinto /usr/lib/postfix
- doexe *
-
- cd ${S}/man
- doman man*/*
-
- cd ${S}
- dodoc *README COMPATIBILITY HISTORY LICENSE PORTING RELEASE_NOTES INSTALL
- dohtml html/*
-
- cd ${S}/conf
- insinto /etc/postfix/sample
- doins access aliases canonical relocated transport \
- pcre_table regexp_table postfix-script* *.cf
-
- exeinto /etc/postfix
- doexe postfix-script post-install postfix-files || die
-
- insinto /etc/postfix
- doins ${FILESDIR}/main.cf ${FILESDIR}/master.cf ${FILESDIR}/saslpass || die
-
- exeinto /etc/init.d ; newexe ${FILESDIR}/postfix.rc6 postfix
- insinto /etc/pam.d ; newins ${FILESDIR}/smtp.pam smtp
-
- if [ "`use sasl`" ]
- then
- if [ -e /usr/include/sasl.h ]
- then
- # saslv1 seems to be installed.
- insinto /etc/sasl ; doins ${FILESDIR}/smtpd.conf
- fi
- if [ -e /usr/include/sasl/sasl.h ]
- then
- # saslv2 seems to be installed.
- insinto /usr/lib/sasl2 ; newins ${FILESDIR}/smtpd2.conf smtpd.conf
- fi
- fi
-}
-
-pkg_postinst() {
- install -d 0755 ${ROOT}/var/spool/postfix
-
- if [ "${postfix_installed}" = "yes" ] ; then
- ewarn "If you've upgraded from <postfix-1.1.8, you must update"
- ewarn "/etc/postfix/master.cf to the latest version"
- ewarn "(/etc/postfix/._cfg*_master.cf). Otherwise Postfix will"
- ewarn "not work correctly."
- fi
-
- if [ ! -e /etc/mail/aliases.db ] ; then
- echo
- ewarn "You must edit /etc/mail/aliases to suit your needs"
- ewarn "and then run /usr/bin/newaliases. Postfix will not"
- ewarn "work correctly without it."
- fi
-
- if [ "`use sasl`" -a -e /usr/include/sasl.h ] ; then
- echo
- einfo "sasl v1 and sasl v2 seem to be installed. Because we don't"
- einfo "want to break existing installations, we use sasl v1."
- einfo "If you don't want this, unmerge sasl v1 and remerge postfix."
- fi
-}
diff --git a/net-mail/postfix/postfix-1.1.11.20020822.ebuild b/net-mail/postfix/postfix-1.1.11.20020917.ebuild
index 1485fbb19e88..790388b6e004 100644
--- a/net-mail/postfix/postfix-1.1.11.20020822.ebuild
+++ b/net-mail/postfix/postfix-1.1.11.20020917.ebuild
@@ -1,8 +1,8 @@
# Copyright 1999-2002 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License, v2 or later
-# $Header: /var/cvsroot/gentoo-x86/net-mail/postfix/postfix-1.1.11.20020822.ebuild,v 1.5 2002/09/17 21:28:32 raker Exp $
+# $Header: /var/cvsroot/gentoo-x86/net-mail/postfix/postfix-1.1.11.20020917.ebuild,v 1.1 2002/09/19 19:09:22 raker Exp $
-PF_PV=1.1.11-20020822
+PF_PV=1.1.11-20020917
PF_P=postfix-${PF_PV}
S=${WORKDIR}/${PF_P}
TLS_P=pfixtls-0.8.11a-${PF_PV}-0.9.6g
diff --git a/net-mail/postfix/postfix-1.1.8-r1.ebuild b/net-mail/postfix/postfix-1.1.8-r1.ebuild
deleted file mode 100644
index 85bf2b2058fd..000000000000
--- a/net-mail/postfix/postfix-1.1.8-r1.ebuild
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 1999-2002 Gentoo Technologies, Inc.
-# Distributed under the terms of the GNU General Public License, v2 or later
-# /space/gentoo/cvsroot/gentoo-x86/net-mail/postfix/postfix-1.1.8.ebuild,v 1.1 2002/05/14 03:49:25 woodchip Exp
-
-DESCRIPTION="A fast and secure drop-in replacement for sendmail"
-HOMEPAGE="http://www.postfix.org/"
-
-POSTFIX_TLS_VER="0.8.8-${PV}-0.9.6d"
-
-S=${WORKDIR}/${P}
-SRC_URI="ftp://ftp.porcupine.org/mirrors/postfix-release/official/${P}.tar.gz
- ssl? ( ftp://ftp.aet.tu-cottbus.de/pub/postfix_tls/pfixtls-${POSTFIX_TLS_VER}.tar.gz )"
-
-PROVIDE="virtual/mta"
-DEPEND=">=sys-libs/db-3.2
- >=dev-libs/libpcre-3.4
- sasl? ( >=dev-libs/cyrus-sasl-1.5.27 )
- ldap? ( >=net-nds/openldap-1.2 )
- mysql? ( >=dev-db/mysql-3.23.28 )
- ssl? ( >=dev-libs/openssl-0.9.6d )
- pam? ( sys-libs/pam )"
-RDEPEND="${DEPEND}
- >=net-mail/mailbase-0.00
- !virtual/mta"
-
-SLOT="0"
-LICENSE="IPL-1"
-KEYWORDS="x86 sparc sparc64"
-
-pkg_setup() {
- if ! grep -q ^postdrop: /etc/group ; then
- groupadd postdrop || die "problem adding group postdrop"
- fi
-}
-
-src_unpack() {
- unpack ${A}
-
- use ssl && ( \
- cd ${S}
- patch -p1 < ${WORKDIR}/pfixtls-${POSTFIX_TLS_VER}/pfixtls.diff || die
- )
-
- cd ${S}/conf
- cp main.cf main.cf.orig
- sed -e "s:/usr/libexec/postfix:/usr/lib/postfix:" main.cf.orig > main.cf
-
- cd ${S}/src/global
- cp mail_params.h mail_params.h.orig
- sed -e "s:/usr/libexec/postfix:/usr/lib/postfix:" mail_params.h.orig > mail_params.h
-
- use mysql \
- && CCARGS="${CCARGS} -DHAS_MYSQL -I/usr/include/mysql" \
- && AUXLIBS="${AUXLIBS} -lmysqlclient -lm"
-
- use ldap \
- && CCARGS="${CCARGS} -DHAS_LDAP" \
- && AUXLIBS="${AUXLIBS} -lldap -llber"
-
- use ssl \
- && CCARGS="${CCARGS} -DHAS_SSL" \
- && AUXLIBS="${AUXLIBS} -lssl"
-
- # note: if sasl is built w/ pam, then postfix _MUST_ be built w/ pam
- use pam && AUXLIBS="${AUXLIBS} -lpam"
-
- # stuff we always want...
- CCARGS="${CCARGS} -I/usr/include -DHAS_PCRE"
- AUXLIBS="${AUXLIBS} -L/usr/lib -lpcre -ldl -lcrypt"
- if [ "`use sasl`" ]
- then
- AUXLIBS="${AUXLIBS} -lsasl"
- CCARGS="${CCARGS} -DUSE_SASL_AUTH"
- fi
- DEBUG=""
-
- cd ${S}
- make tidy || die
- make makefiles CC="cc" OPT="${CFLAGS}" DEBUG="${DEBUG}" \
- CCARGS="${CCARGS}" AUXLIBS="${AUXLIBS}" || die
-}
-
-src_compile() {
- emake || die "compile problem"
-}
-
-src_install () {
- dodir /usr/bin /usr/sbin /usr/lib/postfix /etc/postfix/sample
-
- cd ${S}/bin
- dosbin post* sendmail
- chown root.postdrop ${D}/usr/sbin/{postdrop,postqueue}
- chmod 2755 ${D}/usr/sbin/{postdrop,postqueue}
-
- dosym /usr/sbin/sendmail /usr/bin/mailq
- dosym /usr/sbin/sendmail /usr/bin/newaliases
- dosym /usr/sbin/sendmail /usr/lib/sendmail
-
- cd ${S}/libexec
- exeinto /usr/lib/postfix
- doexe *
-
- cd ${S}/man
- doman man*/*
-
- cd ${S}
- dodoc *README COMPATIBILITY HISTORY LICENSE PORTING RELEASE_NOTES INSTALL
- dohtml html/*
-
- cd ${S}/conf
- insinto /etc/postfix/sample
- doins access aliases canonical relocated transport \
- pcre_table regexp_table postfix-script* *.cf
-
- exeinto /etc/postfix
- doexe postfix-script post-install postfix-files || die
-
- insinto /etc/postfix
- doins ${FILESDIR}/main.cf master.cf || die
-
- exeinto /etc/init.d ; newexe ${FILESDIR}/postfix.rc6 postfix
- insinto /etc/pam.d ; newins ${FILESDIR}/smtp.pam smtp
- insinto /etc/sasl ; doins ${FILESDIR}/smtpd.conf
-}
-
-pkg_postinst() {
- install -d 0755 ${ROOT}/var/spool/postfix
-
- einfo "***************************************************************"
- einfo "* NOTE: If config file protection is enabled and you upgraded *"
- einfo "* from an earlier version of postfix you must update *"
- einfo "* /etc/postfix/master.cf to the latest version *"
- einfo "* (/etc/postfix/._cfg????_master.cf). Otherwise postfix *"
- einfo "* will not work correctly. *"
- einfo "***************************************************************"
-}