diff options
-rw-r--r-- | net-mail/postfix/ChangeLog | 13 | ||||
-rw-r--r-- | net-mail/postfix/files/digest-postfix-1.1.11-r4 | 2 | ||||
-rw-r--r-- | net-mail/postfix/files/digest-postfix-1.1.11.20020822 | 2 | ||||
-rw-r--r-- | net-mail/postfix/files/digest-postfix-1.1.11.20020917 | 2 | ||||
-rw-r--r-- | net-mail/postfix/files/digest-postfix-1.1.8-r1 | 2 | ||||
-rw-r--r-- | net-mail/postfix/files/saslv2.diff | 42 | ||||
-rw-r--r-- | net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2 | bin | 72042 -> 0 bytes | |||
-rw-r--r-- | net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2 | bin | 0 -> 72150 bytes | |||
-rw-r--r-- | net-mail/postfix/files/tls+ipv6.diff | 10732 | ||||
-rw-r--r-- | net-mail/postfix/postfix-1.1.11-r4.ebuild | 185 | ||||
-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.ebuild | 136 |
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 Binary files differdeleted file mode 100644 index ff87843c55cf..000000000000 --- a/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020822.patch.bz2 +++ /dev/null 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 Binary files differnew file mode 100644 index 000000000000..fdf1837fa63d --- /dev/null +++ b/net-mail/postfix/files/tls+ipv6-1.4-pf-1.1.11-20020917.patch.bz2 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 "***************************************************************" -} |