+++ /dev/null
-diff -Pcr postfix-2.0.16/IPv6-ChangeLog postfix-2.0.16-ti1.20/IPv6-ChangeLog
-*** postfix-2.0.16/IPv6-ChangeLog Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/IPv6-ChangeLog Mon Jan 5 19:44:36 2004
-***************
-*** 0 ****
---- 1,397 ----
-+ ChangeLog for Dean Strik's IPv6 patch for Postfix. The patch is based on
-+ PLD's patch, which in turn seems to be based on KAME's. For more information:
-+
-+ http://www.ipnet6.org/postfix/
-+
-+ ---------------------------------------------------------------------
-+
-+ Version 1.20 Postfix release 2.0.16
-+ Postfix snapshot 2.0.16-20031207
-+
-+ Bugfix: The SMTP client would abort when binding to specific
-+ IPv6 addresses.
-+ File: smtp/smtp_connect.c
-+
-+ Synchronisation/bugfix: LMTP source address binding is identical
-+ to the SMTP source binding setup, avoiding the need for
-+ lmtp_bind_address(6) if inet_interfaces is set to a single
-+ host for an address family.
-+ File: lmtp/lmtp_connect.c
-+
-+ Version 1.19 Postfix release 2.0.16
-+ Postfix snapshot 2.0.16-20031207
-+
-+ Bugfix: Synchronisation of TLS patches in snapshots of 1.18[ab]
-+ was not complete, causing a crash of smtpd if used with the new
-+ proxy agent.
-+ File: smtpd/smtpd.c
-+
-+ Bugfix: SMTP source address binding based on a single hostname
-+ in inet_interfaces did not work since the code counted IPv4 and
-+ IPv6 addresses instead of only the used address family. Fixed,
-+ thereby no longer requiring exact specification of
-+ smtp_bind_address(6) in this case.
-+ File: smtp/smtp_connect.c
-+
-+ Bugfix: The QMQP sink server did not compile correctly. This
-+ program, part of smtpstone tools, is not compiled or installed
-+ by default.
-+ File: smtpstone/qmqp-sink.c
-+
-+ Bugfix: NI_WITHSCOPEID was not correctly defined everywhere,
-+ which could result in EAI_BADFLAGS. Changed location of
-+ definition to correct it.
-+ Files: util/sys_defs.h, util/inet_addr_list.h
-+
-+ Version 1.18b Postfix snapshot 2.0.16-20030921
-+
-+ IPv6 support: Added IPv6-enabled code to the new snapshot
-+ check_*_{ns,mx}_access restrictions.
-+ File: smtpd/smtpd_check.c
-+
-+ Version 1.18a Postfix release 2.0.16
-+
-+ Update (TLS patches): Updated Lutz Jaenicke's TLS patch to
-+ version 0.8.16. See pfixtls/ChangeLog for details.
-+ Diff contributed by Tuomo Soini.
-+
-+ The TLS+IPv6 patch now contains the original TLS patch
-+ documentation from Lutz Jaenicke.
-+
-+ Version 1.18 Postfix releases 2.0.14 - 2.0.15
-+ Postfix snapshot 2.0.14-20030812
-+
-+ Bugfix: Perform actual hostname verification in the SMTP
-+ and QMTP servers. This was never supported in the IPv6
-+ patch. Reported by Wolfgang S. Rupprecht.
-+ Files: smtpd/smtpd_peer.c, qmqpd/qmqpd_peer.c
-+
-+ IPv6 address ranges using address/prefixlength (e.g. in
-+ mynetworks and access maps) should be written as
-+ [ipv6:addr:ess]/plen (e.g. [fec0:10:20::]/48). The old
-+ supported syntax, [ipv6:addr:ess/plen] is deprecated and
-+ support will be removed in a later version.
-+ Thanks to Dr. Peter Bieringer and Pekka Savola for discussion.
-+ Files: util/match_ops.c, global/mynetworks.c
-+
-+ Explicitly prefer IPv6 over IPv4 addresses when delivering
-+ to a host when MX lookups are disabled when SMTP address
-+ randomization is on (default).
-+ File: smtp/smtp_addr.c
-+
-+ Compliance: write IPv6 address literals in mail headers
-+ as [IPv6:addr] instead of [addr] as per RFC 2821:4.1.3
-+ tagging requirement, for example [IPv6:fec0:10:20::1].
-+ Pointed out by Dr. Peter Bieringer.
-+ Files: smtpd/smtpd{,_peer,_state}.c, smtpd/smtpd.h
-+
-+ Version 1.17 Postfix release 2.0.13, 2.0.14
-+ Postfix snapshot 2.0.13-20030706, 2.0.14-20030812
-+
-+ Bugfix: Two memory allocation/deallocation bugs were
-+ introduced in patch 1.16. The impact of these bugs could
-+ be 'arbitrary' memory corruption.
-+ File: util/match_ops.c
-+
-+ Version 1.16 Postfix release 2.0.13
-+ Postfix snapshot 2.0.13-20030706
-+
-+ Cleanup: rewrote match_ops.c. This rewrite is partly based on
-+ patch by Takahiro Igarashi. The rewrite enables some better
-+ handling of scoped addresses, and drops all GPL code from the
-+ patch, easying license considerations. Also, allowed for
-+ use of this code by the CIDR maps.
-+ Files: util/match_ops.[ch]
-+
-+ Bugfix: correctly relay for scoped unicast addresses when
-+ applicable. Until now, while Postfix was able to recognize
-+ scoped addresses, it was not able to see e.g. fe80::10%fxp0
-+ as local in mynetworks validation. KAME-only code.
-+ (I've never heard of people using scoped addresses (think
-+ link-local addresses) for mail relaying though...)
-+ Files: util/inet_addr_list.[ch]
-+
-+ Feature (snapshot only): rewrote CIDR maps code to support
-+ IPv6 addresses, using new match_ops code. Allow the use
-+ of [::/0] since it allows one to easily disable further
-+ checks for IPv6 addresses.
-+ File: util/dict_cidr.c
-+
-+ Consistency: require IPv6 addresses in inet_interfaces to
-+ be enclosed in square brackets.
-+ File: util/inet_addr_host.c
-+
-+ Bugfix: (Linux2-only) A #define was misspelled. This could
-+ lead to Postfix being unable to read the system's local IPv6
-+ addresses (e.g. when using inet_interfaces).
-+ Spotted by Jochen Friedrich.
-+ File: util/sys_defs.h
-+
-+ Cleanup: require non-null host portion in CIDR /
-+ prefixlength notations for IPv6 (was IPv4-only).
-+
-+ Version 1.15a Postfix release 2.0.13
-+
-+ Update (TLS patches): Updated Lutz Jaenicke's TLS patch
-+ to version 0.8.15. This version introduces new options
-+ for managing SASL mechanisms. More information at:
-+ http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/
-+ Diff contributed by Tuomo Soini.
-+
-+ Version 1.15 Postfix release 2.0.12, 2.0.13
-+ Postfix snapshot 2.0.12-20030621
-+
-+ Bugfix (TLS-snapshots only): a change in Postfix snapshot
-+ 2.0.11-20030609 broke initialisation of TLS in smtpd,
-+ causing TLS to both be unadvertised and unaccepted.
-+ This was fixed again by reordering initialisation.
-+ File: smtpd/smtpd.c
-+
-+ Update (TLS patches): Updated Lutz Jaenicke's TLS patch
-+ to version 0.8.14. This version introduces a few fixes and
-+ uses USE_SSL instead of HAS_SSL. More information at:
-+ http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/
-+ Diff contributed by Tuomo Soini.
-+
-+ Bugfix (Postfix releases only - this was already added to
-+ the snapshots in patch 1.14). KAME derived systems only.
-+ Correctly decode scoped addresses, including network
-+ interface specifiers.
-+ File: util/inet_addr_local.c
-+
-+ Version 1.14 Postfix releases 2.0.9, 2.0.10, 2.0.11, 2.0.12
-+ Postfix snapshots 2.0.9-20030424, 2.0.10-20030521,
-+ 2.0.11-20030609, 2.0.12-20030611
-+
-+ Patch change: made the patch available as an IPv6-only
-+ patch (i.e., without the TLS code). This on popular
-+ request by users and packagers.
-+ A TLS+IPv6 version is still available of course.
-+
-+ Bugfix: correctly decode scoped addresses from now on
-+ (KAME derived systems only). I think the original code
-+ was written by Itojun, so I'm rather puzzled that it
-+ didn't work...
-+ File: util/inet_addr_local.c
-+
-+ Bugfix/portability: Recent KAME snapshots return both
-+ TCP and SCTP address information on getaddrinfo() if
-+ no protocol was specified. This causes the socket counts
-+ to be wrong, confusing child processes.
-+ Merged patch by JINMEI Tatuya of KAME to fix this.
-+ Files: master/master.h, master/master_{ent,conf}.[ch],
-+ util/inet_listen.c
-+
-+ Documentation: added an IPV6_README file to the patch.
-+ This file contains the primary documentation. Also,
-+ added a sample-ipv6.cf to describe the (currently few)
-+ IPv6 related main.cf parameters.
-+
-+ Bugfix: the netmask structures for the *unsupported*
-+ platforms (boldly assume /64) were added to the wrong
-+ list (addresses instead of masks). This bug did not affect
-+ any supported platform though.
-+ File: util/inet_addr_local.c
-+
-+ Portability: added support for HP/Compaq Tru64Unix V5.1
-+ and later. (compiled with CompaqCC only).
-+ Thanks to Sten Spans for providing root access to an
-+ IPv6-connected Tru64 testing machine.
-+
-+ Version 1.13 Postfix releases 2.0.4 - 2.0.9
-+ Postfix snapshots 2.0.3-20030126 - 2.0.7-20030319
-+
-+ Bugfix: Due to a missing storage pointer, DNS lookup
-+ results in the permit_mx_backups code were not processed,
-+ and smtpd would likely crash.
-+ Thanks to Wouter de Jong for reporting the crashes.
-+ File: smtpd/smtpd_check.c
-+
-+ Incompatible change: The addresses given to the parameters
-+ smtp_bind_address6 and lmtp_bind_address6 now need to be
-+ enclosed in square brackets for consistency.
-+ Files: [ls]mtp/[ls]mtp_connect.c
-+
-+ Version 1.12 Postfix releases 2.0.2, 2.0.3
-+ Postfix snapshots 2.0.2-20030115, 2.0.3-20030126
-+
-+ Bugfix/workaround (Solaris): A simplified comparison
-+ function for Solaris' qsort() function, would result
-+ in corruption of network addresses in the SMTP client.
-+ Fixed. Reported with possible fix by Edvard Tuinder.
-+ File: smtp/smtp_addr.c
-+
-+ Version 1.11 Postfix releases 2.0.0.x, 2.0.1, 2.0.2
-+ Postfix snapshots 2.0.0-20030105, 2.0.1-20030112
-+ 2.0.2-20030115
-+
-+ Bugfix (Solaris): Properly initialize lifconf structure
-+ when requesting host interface addresses. If you get
-+ warnings about SIOCGLIFCONF with earlier versions,
-+ please upgrade.
-+ File: util/inet_addr_local.c
-+
-+ Patch fix: fixed compilation errors in case the patch is
-+ applied but built without IPv6 support (i.e., on unsupported
-+ platforms).
-+
-+ Version 1.10 Postfix snapshots 1.1.12-200212{19,21}
-+ Postfix releases 2.0.0, 2.0.0.{1,2}
-+ Postfix snapshots 2.0.0-20021223 - 2.0.0-20030101
-+
-+ 'Bugfix': don't show spurious warnings on Linux systems
-+ about missing /proc/net/if_inet6 unless verbose mode
-+ is enabled.
-+ File: util/inet_addr_local.c
-+
-+ Bugfix: If unable to create a socket for a specific adress
-+ in the SMTP client (e.g., when trying to create an IPv6
-+ connection while the local host has no configured IPv6
-+ addresses), then stop the attempt.
-+ File: smtp/smtp_connect.c
-+
-+ Small bugfix: never query DNS for <localpart@[domain.tld]>.
-+ This syntax now correctly generates an error immediately.
-+ File: global/resolve_local.c
-+
-+ Updated TLS patch to 0.8.12-1.1.12-20021219-0.9.6h, fixing
-+ a bug with "sendmail -bs".
-+
-+ Version 1.9 Postfix version 1.1.11-20021115
-+ Postfix version 1.1.12-2002{1124,1209-1213}
-+
-+ Bugfix: with getifaddrs() code (*BSD, linux-USAGI), IPv4
-+ netmasks were set to /32 effectively. Work around broken
-+ netmask data structures (*BSD only perhaps).
-+
-+ Bugfix: same data corruption in another place created
-+ entirely wrong IPv4 netmasks. Work around broken
-+ SIOCGIFNETMASK structure.
-+
-+ New code was added for correct IPv6 netmasks. The original
-+ code did not contain IPv6 netmask support at all!
-+ For Solaris, use SIOCGLIF*; Linux: /proc/net/if_inet6.
-+ Getifaddrs() support is used otherwise. This should cover
-+ all supported systems. Other systems also work, prefix
-+ length is always set to /64 then.
-+
-+ Since there are no classes (context: Class A, class B etc
-+ networks) with IPv6, default to IPv6 subnet style if the
-+ mynetworks style is 'class'. I recommend against this style
-+ anyway.
-+
-+ Added support to display IPv6 nets mynetworks output.
-+
-+ Version 1.8 Postfix version 1.1.11-200211{01,15}
-+
-+ An earlier author of the patch made a typo in the GAI_STRERROR()
-+ macro, resulting in bogus error messages when checking for
-+ PTR records. Fixed.
-+
-+ IPv4-mapped addresses in the smtpd are converted to true IPv4
-+ addresses just after the connection has been made. This means
-+ that all IPv4-mapped addresses are now logged as true IPv4
-+ addresses. Hence beside RBL checks, also access maps now treat
-+ IPv4-mapped addresses as native IPv4. Note that ::ffff:...
-+ entries in your access tables will no longer work.
-+
-+ You can now specify IPv6 'parent' networks in your access maps,
-+ e.g. to reject all mail from 3ffe:200:... nodes, add the line
-+ 3ffe:200 REJECT
-+ Use of trailing colons is discouraged because postmap will
-+ warn about it possibly being an alias...
-+ NOTE: I'll soon obsolete this again in favor of the more
-+ common address/len notation. This was just so trivial to add
-+ that it didn't hurt and I needed it :)
-+
-+ For easy reference, the version of the TLS/IPv6 patch can be
-+ dynamically queried using the tls_ipv6_version variable.
-+ This gives the short version (like, "1.8").
-+
-+ The service bind address for 'inet' sockets in master.cf (e.g.,
-+ smtpd), must be enclosed in square brackets '[..]' for IPv6
-+ addresses. The old style (without brackets) still works but is
-+ unsupported and may be removed in the future. Example
-+ [::1]:smtp inet n - n - - smtpd
-+
-+ Version 1.7 Postfix version 1.1.11-20021029 - 1.1.11-20021101
-+
-+ Postfix' SMTP client performs randomization of MX addresses
-+ when sending mail. This however could result in A records
-+ being used before AAAA records. This has been corrected.
-+
-+ Note that from Postfix version 1.1.11-20021029 on, there is
-+ a proxy_interfaces parameter. This has of course not been
-+ ported to IPv6 addresses...
-+
-+ Version 1.6 Postfix version 1.1.11-20020928
-+
-+ Added IPv6 support for backup_mx_networks feature; also the
-+ behaviour when DNS lookups fail when checking whether the
-+ local host is an MX for a domain conforms to the IPv4 case:
-+ defer rather than allow.
-+
-+ Version 1.5 Postfix version 1.1.11-20020917
-+
-+ I introduced two bugs when I rewrote my older LMTP IPv6 patch.
-+ These bugs effectively rendered LMTP useless. Now fixed.
-+ Bugs spotted by Kaj Niemi.
-+
-+ Now supports Solaris 8 and 9. Due to lack of testing equipment,
-+ this has been only tested in production on Solaris 9, both
-+ with gcc and the Sun Workshop Compiler.
-+
-+ Version 1.4 Postfix version 1.1.11-20020822 - 1.1.11-20020917
-+
-+ OpenBSD (>=200003) and FreeBSD release 4 and up now use
-+ getifaddrs(). This makes for cleaner code. The old code
-+ seems to be bug-ridden anyway.
-+
-+ Got rid of some compiler warnings. Should be cleaner on
-+ Alpha as well now. Thanks to Sten Spans for providing me
-+ access to an Alpha running FreeBSD4.
-+
-+ Fixed an old bug in smtpd memory alloation if you compiled
-+ without IPv6 support (the wrong buffer size was used. This
-+ was harmless for IPv6-enabled compiles since the sizes were
-+ equal then).
-+
-+ Added ChangeLog to the patch (as IPv6-ChangeLog) (this
-+ was absent in 1.3 contrary to docs).
-+
-+ Version 1.3 Postfix version 1.1.11-20020613 - 1.1.11-20020718
-+
-+ FYI: In postfix version 1.1.11-20020718, DNS lookups for
-+ AAAA can be done natively. The code matches the code in
-+ the patch (though the #ifdef changed from INET6 to T_AAAA).
-+ This change causes the patch for 1.1.11-20020718 to be a
-+ bit smaller.
-+
-+ Version 1.2 Postfix version 1.1.11-20020613
-+
-+ Added IPv6 support for the LMTP client.
-+
-+ Added lmtp_bind_address and lmtp_bind_address6 parameters,
-+ similar to those for smtp.
-+
-+ Added IPv6 support for the QMQP server.
-+
-+ Version 1.1 Postfix version 1.1.11-20020602 - 1.1.11-20020613
-+
-+ Added parameter smtp_bind_address6. By using this parameter,
-+ it is possible to bind to an IPv6 address, independently of
-+ IPv4 address binding.
-+
-+ Lutz fixed a bug in his TLS patch regarding SASL. Incorporated.
-+
-+ Version 1.0.x Postfix version 1.1.8-20020505 - 1.1.11-20020602
-+
-+ Patch derived from PLD's IPv6 patch for Postfix, revision 1.10
-+ which applied to early Postfix snapshots 1.1.x. Updated this
-+ patch to apply to 1.1.8-20020505.
-+
-+ Added compile-time checks for SS_LEN. Some Linux installations,
-+ and maybe other systems, do define SA_LEN, but not SS_LEN.
-+
-+ Several updates of postfix snapshots.
-+
-diff -Pcr postfix-2.0.16/Makefile.in postfix-2.0.16-ti1.20/Makefile.in
-*** postfix-2.0.16/Makefile.in Sun Jan 12 17:23:26 2003
---- postfix-2.0.16-ti1.20/Makefile.in Mon Jan 5 16:58:03 2004
-***************
-*** 7,13 ****
- 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/proxymap
- MANDIRS = proto man html
-
- default: update
---- 7,13 ----
- 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/proxymap src/tlsmgr
- MANDIRS = proto man html
-
- default: update
-diff -Pcr postfix-2.0.16/README_FILES/IPV6_README postfix-2.0.16-ti1.20/README_FILES/IPV6_README
-*** postfix-2.0.16/README_FILES/IPV6_README Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/README_FILES/IPV6_README Mon Jan 5 16:59:53 2004
-***************
-*** 0 ****
---- 1,154 ----
-+ Postfix IPv6 / IPv6+TLS patch
-+ Maintained by Dean C. Strik <dean@ipnet6.org>
-+
-+ These patches add IPv6 support to Postfix. A combo TLS+IPv6 patch is
-+ available as a replacement for Lutz Jaenicke's TLS patch.
-+
-+ More information about these IPv6 patches can be found on Dean Strik's
-+ postfix website at
-+ http://www.ipnet6.org/postfix/
-+
-+ CONTENTS
-+ ---------
-+ - Supported platforms
-+ - Downloads
-+ - Installation
-+ - Configuration
-+ - Mailing list
-+ - Known issues
-+ - Reporting bugs
-+
-+ SUPPORTED PLATFORMS
-+ --------------------
-+
-+ Currently, the following platforms are supported:
-+ - FreeBSD 4.x/5.x
-+ - OpenBSD 2.x/3.x
-+ - NetBSD 1.5+
-+ - Solaris 8/9
-+ - Linux 2.x
-+ - Tru64Unix V5.1+
-+ Postfix may work on other versions of these operating systems or
-+ other operating systems entirely. If you find a problem on one
-+ of the above platforms, please contact me at <dean@ipnet6.org>.
-+
-+ DOWNLOADS
-+ ----------
-+
-+ The official download site is
-+
-+ http://www.ipnet6.org/postfix/
-+
-+ Patches are offered as HTTP and FTP downloads here. To directly
-+ access the files on the FTP server, use the following address:
-+
-+ ftp://ftp.stack.nl/pub/postfix/tls+ipv6/
-+
-+ The patches are in gzipped context diff format.
-+
-+ INSTALLATION
-+ -------------
-+
-+ The patch is distributed as a gzipped context diff. This used to
-+ be unified diff (more readable), but it was changed because to
-+ avoid unidiff limitations.
-+
-+ We assume postfix is already extracted, to the directory
-+ postfix-2.0.16
-+
-+ 1. Decompress the patch:
-+ e.g. $ gunzip tls+ipv6-1.20-pf-2.0.16.patch.gz
-+ 2. Change directory to the postfix source directory
-+ e.g. $ cd postfix-2.0.16
-+ 3. Apply the patch
-+ e.g. $ patch -s -p 1 < ../tls+ipv6-1.20-pf-2.0.16.patch
-+ 4. Build postfix. The IPv6 patch does not require additional environment
-+ variables or arguments to 'make'.
-+
-+ CONFIGURATION
-+ --------------
-+
-+ In theory, no post-installation configuration of postfix is
-+ required, although you may want to extend the value of the
-+ 'mynetworks' parameter to include the IPv6 networks the system is
-+ in.
-+
-+ The main.cf parameters regarding IPv6 are documented in the file
-+ 'sample-ipv6.cf' in the samples/ directory.
-+
-+ MAILING LISTS
-+ --------------
-+
-+ I've created two mailing lists about using IPv6 with Postfix.
-+ There's a general list (postfix-ipv6) that can be used for discussion.
-+ Also, there's an announcement-only list (postfix-ipv6-announce)
-+ for people who only want to get the announcements.
-+ All announcements are cross-posted to postfix-ipv6 though.
-+
-+ List name: postfix-ipv6
-+ List type: Discussion / general (incl. announcements)
-+ List info: http://lists.stack.nl/mailman/listinfo/postfix-ipv6
-+ List archive: http://lists.stack.nl/pipermail/postfix-ipv6
-+ List admin: Dean Strik <dean@ipnet6.org>
-+
-+ List name: postfix-ipv6-announce
-+ List type: Announcements only, moderated
-+ List info: http://lists.stack.nl/mailman/listinfo/postfix-ipv6-announce
-+ List archive: http://lists.stack.nl/pipermail/postfix-ipv6-announce
-+ List admin: Dean Strik <dean@ipnet6.org>
-+
-+ KNOWN ISSUES
-+ -------------
-+
-+ The patch comes with an IPv6-ChangeLog file. Please always validate
-+ whether you have the latest version. You can always download the
-+ latest ChangeLog at
-+
-+ ftp://ftp.stack.nl/postfix/tls+ipv6/ChangeLog
-+
-+ The following 'issues' and todo items are known (none critical):
-+
-+ - It is not currently supported to use Postfix network daemons
-+ (such as smtp and smtpd) chrooted on Linux systems without
-+ mounting the proc filesystem under /var/spool/postfix/proc
-+ This is because the proc filesystem is required on Linux to
-+ obtain the system's IPv6 address information.
-+
-+ - The 'smtp_host_lookup' parameter is not effective with IPv6.
-+ This is because a different lookup mechanism is used that
-+ cannot easily disable the 'local' (i.e., non-DNS) lookups.
-+ Whether local files or the DNS are used first, is determined
-+ by your operating system, e.g. in /etc/nsswitch.conf or
-+ /etc/host.conf.
-+
-+ - The order of IPv6/IPv4 outgoing connection attempts is not
-+ yet configurable. This will be configurable in a later,
-+ soon to be released version. Currently, IPv6 is tried before
-+ IPv4.
-+
-+ - No IPv6 open relay checks. Since there is no IPv6 RBL service
-+ around at the moment (I'm considering setting one up but it's
-+ not a very hot issue), no lookups for IPv6 clients are ever done.
-+ Let's not have a lot of worthless DNS traffic. Of course, when
-+ this gets implemented, IPv6 client lookups will only be made
-+ to DNSBLs that support these.
-+
-+ - Tru64Unix: Using 'mynetworks_style = subnet' (which I do not
-+ recommend in any case...) causes Postfix to assume a /64 for
-+ all IPv6-connected IPv6 subnets. I have yet to find a good way
-+ for obtaining the prefixlength. Suggestions are welcome!
-+
-+ REPORTING BUGS
-+ ---------------
-+
-+ Of course there may be bugs in the patch. Please report bugs in the
-+ patch to <dean@ipnet6.org>. Please be thorough in the report.
-+ Patches, when possible, are greatly appreciated too!
-+
-+ Please differentiate when possible between
-+ - Bugs in vanilla Postfix: mailto:<postfix-users@postfix.org>
-+ - Bugs in Lutz' TLS patch: mailto:<postfix_tls@aet.tu-cottbus.de>
-+ - Bugs in the IPv6 code: mailto:<postfix-ipv6@stack.nl>
-+
-+ --
-+ Dean Strik <dean@ipnet6.org>
-diff -Pcr postfix-2.0.16/conf/master.cf postfix-2.0.16-ti1.20/conf/master.cf
-*** postfix-2.0.16/conf/master.cf Mon Apr 28 00:51:13 2003
---- postfix-2.0.16-ti1.20/conf/master.cf Mon Jan 5 16:58:04 2004
-***************
-*** 72,82 ****
---- 72,87 ----
- # (yes) (yes) (yes) (never) (100)
- # ==========================================================================
- 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 -Pcr postfix-2.0.16/conf/postfix-files postfix-2.0.16-ti1.20/conf/postfix-files
-*** postfix-2.0.16/conf/postfix-files Sun Jan 12 18:08:12 2003
---- postfix-2.0.16-ti1.20/conf/postfix-files Mon Jan 5 16:58:04 2004
-***************
-*** 70,75 ****
---- 70,76 ----
- $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
-***************
-*** 141,146 ****
---- 142,148 ----
- $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
-***************
-*** 150,155 ****
---- 152,158 ----
- $sample_directory/sample-debug.cf:f:root:-:644
- $sample_directory/sample-filter.cf:f:root:-:644
- $sample_directory/sample-flush.cf:f:root:-:644
-+ $sample_directory/sample-ipv6.cf:f:root:-:644
- $sample_directory/sample-ldap.cf:f:root:-:644
- $sample_directory/sample-lmtp.cf:f:root:-:644
- $sample_directory/sample-local.cf:f:root:-:644
-***************
-*** 168,173 ****
---- 171,177 ----
- $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/ADDRESS_CLASS_README:f:root:-:644
-***************
-*** 176,181 ****
---- 180,186 ----
- $readme_directory/ETRN_README:f:root:-:644
- $readme_directory/FILTER_README:f:root:-:644
- $readme_directory/INSTALL:f:root:-:644
-+ $readme_directory/IPV6_README:f:root:-:644
- $readme_directory/LDAP_README:f:root:-:644
- $readme_directory/LINUX_README:f:root:-:644
- $readme_directory/LMTP_README:f:root:-:644
-diff -Pcr postfix-2.0.16/conf/sample-auth.cf postfix-2.0.16-ti1.20/conf/sample-auth.cf
-*** postfix-2.0.16/conf/sample-auth.cf Fri Mar 29 22:36:53 2002
---- postfix-2.0.16-ti1.20/conf/sample-auth.cf Mon Jan 5 16:58:04 2004
-***************
-*** 69,74 ****
---- 69,101 ----
- #smtpd_sasl_security_options = noanonymous, noplaintext
- smtpd_sasl_security_options = noanonymous
-
-+ # The smtpd_sasl_tls_security_options parameter controls what authentication
-+ # mechanism the Postfix SMTP server will offer to the client, in case the
-+ # connection is protected by a TLS encrypted session.
-+ # This parameter allows to provide for example plaintext authentication that
-+ # otherwise would not be allowed without encryption.
-+ # The default is to use the same settings as in the unencrypted case.
-+ #
-+ # Warning: this option only works against passive (eavesdropping) attackes.
-+ # An active attacker (man in the middle) may modify the AUTH options offered
-+ # and/or remove the STARTTLS offer from the EHLO response. Protection against
-+ # active attackers is only possible by enforcing TLS at the client side.
-+ #
-+ #smtpd_sasl_tls_security_options = noanonymous
-+ smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
-+
-+ # 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, if 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 = yes
-+ smtpd_tls_auth_only = no
-+
- # The smtpd_sasl_local_domain parameter specifies the name of the
- # local authentication realm.
- #
-***************
-*** 117,119 ****
---- 144,177 ----
- #
- #smtp_sasl_security_options =
- smtp_sasl_security_options = noplaintext
-+
-+ # The smtp_sasl_tls_security_options parameter controls, what authentication
-+ # mechanisms the local Postfix SMTP client is allowed to use, if the session
-+ # is encrypted via TLS. This provides the option to permit plaintext passwords
-+ # that otherwise could not be used.
-+ #
-+ # The settings allowed are the same as for the non-encrypted sessions
-+ # (smtp_sasl_security_options).
-+ #
-+ # Warning, Warning, Warning: This option only works against passive
-+ # (eavesdropping) attacks. An active attacker (man in the middle) may provide
-+ # a TLS capabable server (proxy) and in such way obtain the password
-+ # information. The only way to prevent a man in the middle attack is to check
-+ # the hostname of the server presented in the certificate. This is assured
-+ # in the (preferrably used) smtp_sasl_tls_verified_security_options case.
-+ #
-+ #smtp_sasl_tls_security_options =
-+ smtp_sasl_tls_security_options = $smtp_sasl_security_options
-+
-+ # The smtp_sasl_tls_verified_security_options parameter controls, what
-+ # authentication mechanisms the local Postfix SMTP client is allowed to use,
-+ # if the session is encrypted via TLS _and_ the server has proven its
-+ # identity (expected hostname matches certificate, verification successfull).
-+ # This provides the option to permit plaintext passwords that otherwise could
-+ # not be used.
-+ #
-+ # The settings allowed are the same as for the non-encrypted sessions
-+ # (smtp_sasl_security_options).
-+ #
-+ #smtp_sasl_tls_verified_security_options =
-+ smtp_sasl_tls_verified_security_options = $smtp_sasl_tls_security_options
-diff -Pcr postfix-2.0.16/conf/sample-ipv6.cf postfix-2.0.16-ti1.20/conf/sample-ipv6.cf
-*** postfix-2.0.16/conf/sample-ipv6.cf Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/conf/sample-ipv6.cf Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,48 ----
-+ # 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 IPv6 operation of Postfix. Most of
-+ # the parameters below are also described in the subsystem-specific
-+ # sample cf files.
-+
-+ # SMTP CLIENT CONTROLS
-+
-+ # It can be preferable to assign a certain source address for outgoing
-+ # SMTP connections. Since multiple address families (IPv4, IPv6) are
-+ # supported, we need one binding address per address family.
-+ #
-+ # For IPv4, we use the smtp_bind_address parameter. The address is
-+ # specified as an unbracketed dotquad IP.
-+ # For IPv6, we use the smtp_bind_address6 parameter. The address is
-+ # specified as a bracketed hex IPv6 address.
-+ #
-+ # The default is to bind to the wildcard IPv4 and IPv4 addresses,
-+ # i.e. the address is automatically determined by the kernel based
-+ # on the destination address.
-+ #
-+ smtp_bind_address = 1.2.3.4
-+ smtp_bind_address6 = [2001:610:1108:5010::225]
-+
-+ # LMTP CLIENT CONTROLS
-+
-+ # It's also possible that you want to assign a source address for
-+ # LMTP client connections. This is not very likely, but possible
-+ # anyway. Syntax and semantics are identical to the case described
-+ # under 'SMTP CLIENT CONTROLS'.
-+ #
-+ lmtp_bind_address = 1.2.3.4
-+ lmtp_bind_address6 = [2001:610:1108:5010::225]
-+
-+ # MISCELLANEOUS PARAMETERS
-+
-+ # The tls_ipv6_version parameter specifies the version number of the
-+ # TLS+IPv6 or IPv6 patch by Dean Strik. This version string can be
-+ # used in e.g. bugreports.
-+ # Note that the non-TLS version of the patch still names this parameter
-+ # tls_ipv6_version. To determine whether TLS was actually compiled in,
-+ # there are a lot of sources to look at it, for example check whether
-+ # the parameter smtp_use_tls is defined.
-+ #
-+ tls_ipv6_version = 1.18a
-+
-diff -Pcr postfix-2.0.16/conf/sample-smtp.cf postfix-2.0.16-ti1.20/conf/sample-smtp.cf
-*** postfix-2.0.16/conf/sample-smtp.cf Mon Dec 23 22:16:51 2002
---- postfix-2.0.16-ti1.20/conf/sample-smtp.cf Mon Jan 5 16:58:04 2004
-***************
-*** 189,194 ****
---- 189,202 ----
- #
- 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 -Pcr postfix-2.0.16/conf/sample-smtpd.cf postfix-2.0.16-ti1.20/conf/sample-smtpd.cf
-*** postfix-2.0.16/conf/sample-smtpd.cf Tue Aug 12 18:28:46 2003
---- postfix-2.0.16-ti1.20/conf/sample-smtpd.cf Mon Jan 5 16:58:04 2004
-***************
-*** 189,194 ****
---- 189,199 ----
- #
- 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 -Pcr postfix-2.0.16/conf/sample-tls.cf postfix-2.0.16-ti1.20/conf/sample-tls.cf
-*** postfix-2.0.16/conf/sample-tls.cf Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/conf/sample-tls.cf Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,499 ----
-+ # 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). Checks are performed against
-+ # all names provided as dNSNames in the SubjectAlternativeName. If no
-+ # dNSNames are specified, the CommonName is checked.
-+ # 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 -Pcr postfix-2.0.16/makedefs postfix-2.0.16-ti1.20/makedefs
-*** postfix-2.0.16/makedefs Thu Jan 23 14:45:02 2003
---- postfix-2.0.16-ti1.20/makedefs Mon Jan 5 16:58:04 2004
-***************
-*** 302,307 ****
---- 302,334 ----
- ;;
- esac
-
-+ # Check for IPv6 support
-+
-+ if [ -z "$NO_IPV6" ] ; then
-+ if [ -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 ]; then
-+ case "$SYSTYPE" in
-+ SUNOS5) INET6=solaris ;;
-+ OSF1) INET6=osf1 ;;
-+ *) ;;
-+ esac
-+ fi
-+ if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then
-+ INET6=linux
-+ fi
-+ fi # [-z NO_IPV6]
-+
- # Defaults that can be overruled (make makefiles CC=cc OPT=-O6 DEBUG=)
- # Disable optimizations by default when compiling for Purify. Disable
- # optimizations by default with gcc 2.8, until the compiler is known to
-***************
-*** 317,322 ****
---- 344,374 ----
- esac
-
- : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
-+
-+ case "$INET6" in
-+ kame)
-+ CCARGS="$CCARGS -DINET6 -DINET6_KAME"
-+ CCARGS="$CCARGS -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 -DINET6_KAME"
-+ CCARGS="$CCARGS -D__ss_family=ss_family -D__ss_len=ss_len"
-+ ;;
-+ solaris|osf1)
-+ 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 -Pcr postfix-2.0.16/man/man8/tlsmgr.8 postfix-2.0.16-ti1.20/man/man8/tlsmgr.8
-*** postfix-2.0.16/man/man8/tlsmgr.8 Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/man/man8/tlsmgr.8 Mon Jan 5 16:58:04 2004
-***************
-*** 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 -Pcr postfix-2.0.16/pfixtls/ACKNOWLEDGEMENTS postfix-2.0.16-ti1.20/pfixtls/ACKNOWLEDGEMENTS
-*** postfix-2.0.16/pfixtls/ACKNOWLEDGEMENTS Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/ACKNOWLEDGEMENTS Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,56 ----
-+ - Walcir Fontanini <walcir@densis.fee.unicamp.br>
-+ * tested on Solaris 2.5 and and reported missing "snprintf()"
-+ -> was fixed in pfixtls-0.1.2
-+ * contributed the script to add fingerprints
-+ contributed/fp.csh
-+
-+ - Matti Aarnio <matti.aarnio@sonera.fi> (www.zmailer.org)
-+ * updated pfixtls_dump to need fewer strcat and strcpy calls.
-+
-+ - Cerebus <cerebus@sackheads.org>
-+ * Missing variable initialization in client mode enable STARTTLS
-+ negotiation even when not wanted.
-+ -> fixed in pfixtls-0.2.8
-+
-+ - Bodo Moeller <bode@openssl.org>
-+ * The SSL connection was not shut down at the end of the session, because
-+ SSL_CTX_set_quiet_shutdown() was set. This however did not mean "do a
-+ quiet shutdown" but "do not shutdown SSL".
-+ -> fixed in pfixtls-0.3.3
-+
-+ - Jeff Johnson <jeff@websitefactory.net>
-+ * noted that the patch code will not compile with SSL disabled anymore,
-+ because a ´#ifdef HAS_SSL #endif´ encapsulation was missing in
-+ smtp/smtp_connect.c. This must have been in since the very beginning
-+ of client mode support (0.2.x).
-+ -> fixed in 0.3.6
-+
-+ - Craig Sanders <craig@taz.net.au>
-+ * noted that the Received: header does not contain sufficient information
-+ whether a client certificate was not requested or not presented.
-+ He also reminded me that the session cache must be cleared when
-+ experimenting with the setup and certificates, what is not explained
-+ in the documenation.
-+ -> fixed in 0.4.4
-+
-+ - Claus Assmann <ca+tls@esmtp.org>
-+ * pointed out that the Received: header logging about the TLS state violated
-+ RFC822. The TLS information must be in comment form "(info)".
-+ -> fixed in 0.6.3
-+
-+ - Wietse Venema <wietse@porcupine.org>
-+ * uncounted important suggestions to start the integration into the Postfix
-+ mainstream code.
-+ * code adjustments in the dict_*() database code to allow easier inclusion
-+ and use for session caching, and this is only the beginning :-)
-+ -> started reprogramming Postfix/TLS to fit both Wietse's and my
-+ requirements as of 0.6.0
-+
-+ - Damien Miller <djm@mindrot.org>
-+ * Found mismatch between documentation and code with regard to logging.
-+ -> fixed in 0.6.6
-+
-+ - Deti Fliegl <fliegl@cs.tum.edu>
-+ * Provided an initial patch to support SubjectAlternativeName/dNSName
-+ checks.
-+ -> added in 0.8.14
-diff -Pcr postfix-2.0.16/pfixtls/CHANGES postfix-2.0.16-ti1.20/pfixtls/CHANGES
-*** postfix-2.0.16/pfixtls/CHANGES Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/CHANGES Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,2297 ----
-+ 2003/09/10 == Releasd 0.8.16 ==
-+
-+ 2003/09/09
-+ - Postfix 2.0.15 has been released including another workaround for
-+ select() on Solaris problems. It contains additional code to catch
-+ EAGAIN on read() in the timed_read() routine (and the respective
-+ precautions in timed_write()
-+ - Note: this fix is not yet part of Postfix 2.0.14-20030812.
-+ - Added corresponding code to pfixtls_timed_read()/_write().
-+ - Changed SSL wrappermode behaviour: use smtpd_sasl_tls_security_options
-+ instead of smtpd_sasl_security_options as is to be expected because TLS
-+ is active. (Bug reported by Bob Snyder <rsnyder@toontown.erial.nj.us>.)
-+
-+ 2003/08/29 == Re-released 0.8.15 ==
-+
-+ 2003/08/29
-+ - Adapted patchkit to Postfix 2.0.14. No patch conflicts.
-+
-+ 2003/07/08 == Released 0.8.15 ==
-+
-+ 2003/07/07
-+ - Postfix 2.0.13 and 2.0.13-20030706 are released.
-+ Patchkit for 2.0.13 applies cleanly.
-+ Patchkit for 2.0.13-20030607 requires several adaptations (patch conflicts,
-+ no functional changes).
-+ - Slightly modified SASL interface code (smpt[d]_sasl_glue layer) to
-+ allow setting the security policy during session setup instead of
-+ process start. This allows to actually choose SASL mechanisms available
-+ depending on the availability of TLS encryption and authentication.
-+ New parameters: smtpd_sasl_tls_security_options,
-+ smtp_sasl_tls_security_options, smtp_sasl_tls_verified_security_options
-+ - Submitted change to SASL interface to Wietse, who accepted the change
-+ as part of the Snapshot line.
-+
-+ 2003/06/19 == Released 0.8.14 ==
-+
-+ 2003/06/19
-+ - Add support for SubjectAlternativeName "dNSName" entries in certificate
-+ checking (applies for client mode only).
-+ If the client connects to the server, it does check the list of dNSName
-+ entries against the expected hostname (therefore allowing the server to
-+ have multiple identities). As described in RFC2818 (HTTP over TLS),
-+ CommonName (CN) entries are only checked, if no dNSName entries are found
-+ at all.
-+ Initial patch proposed by Deti Fliegl <fliegl@cs.tum.edu>, reworked to
-+ follow the RFC2818 rules and some cleanup.
-+
-+ 2003/06/18
-+ - Checked out similar settings, found another missing entry:
-+ var_smtp_scert_vd was missing src/smtp/smtp.c.
-+ - Renamed HAS_SSL to USE_SSL for compilation (have to use -DUSE_SSL
-+ in the future). Currently pfixtls.h will take care of setting
-+ USE_SSL, when HAS_SSL has been defined.
-+
-+ 2003/06/17
-+ - Received bug reports about Postfix/TLS failing (connection closing)
-+ after having finished the "STARTTLS"/"220 Ready to start TLS"
-+ dialogue. (Actually the first report came in via private mail on
-+ 2003/06/12, but the information was too diffuse to track down).
-+ Tracking down became possible after it became clear, that only Solaris
-+ systems are affected.
-+ Analysis:
-+ * As of 2003/06/09 postfix uses non-blocking socket I/O for the SMTP
-+ connection on Solaris platforms. This requires using "select()" style
-+ waiting before read() or write() access (which are not prepared EAGAIN
-+ or EWOULDBLOCK in the Postfix case and therefore indicate error).
-+ * As the var_smtpd_starttls_tmout variable is not correctly initialized
-+ (value is 0), the select() style function is not called, therefore
-+ read() fails with EAGAIN and the connection is closed due to a
-+ presumed error condition.
-+ * The initialization of the variable should be done in the time_table[]
-+ list during main().
-+ The entry however was lost during the patch adaptation from 0.7.13e
-+ to 0.7.14-snap20020107 on 2002/01/07.
-+ Impact:
-+ * On Solaris systems, STARTTLS fails during handshake (server only).
-+ * On other systems, the TLS negotiation phase is not protected by the
-+ smtpd_starttls_tmout (default 300s) value and may hang until the
-+ watchdog kills smtpd, if the client does not continue the handshake.
-+ Restored var_smtpd_starttls_tmout variable initialization.
-+
-+ 2003/06/12 == Re-released 0.8.13 ==
-+
-+ 2003/06/11
-+ - Adapted to snapshot 2.0.12-20030611. No patch conflicts.
-+
-+ 2003/06/11
-+ - Adapted to snapshot 2.0.11-20030609. One minor patch conflict.
-+
-+ 2003/05/23 == Re-released 0.8.13 ==
-+
-+ 2003/05/23
-+ - First release against snapshot 2.0.10-20030523.
-+
-+ 2003/04/26 == Re-released 0.8.13 ==
-+
-+ 2003/04/26
-+ - Updated patchkit to apply to Postfix 2.0.9.
-+ - Updated patchkit-name to reflect the release of OpenSSL 0.9.7b.
-+
-+ 2003/03/06 == Re-released 0.8.13 ==
-+
-+ 2003/03/06
-+ - Postfix 2.0.6 has been released. No patch conflicts.
-+
-+ 2003/03/02 == Re-released 0.8.13 ==
-+
-+ 2003/03/02
-+ - Postfix 2.0.4 has been released. "patch" should work with some warnings
-+ about moved line numbers.
-+ - OpenSSL 0.9.7a has been released. No visible changes with respect to
-+ Postfix/TLS.
-+
-+ 2003/01/26 == Re-released 0.8.13 ==
-+
-+ 2003/01/26
-+ - Postfix 2.0.3 has been released. One minor patch-conflict.
-+
-+ 2003/01/13 == Released 0.8.13 ==
-+
-+ 2003/01/13
-+ - Postfix 2.0.1 has been released. Some minor patch conflicts resolved.
-+ - Added HOWTO documents contributed by Justin Davies <justin@palmcoder.net>
-+ to the contribution area.
-+ - Added RFC3207 (SMTP Service Extension for Secure SMTP over Transport Layer
-+ Security) to the documentation. RFC3207 is the successor of RFC2487.
-+ - Updated TODO list to reflect release ideas up to the release of
-+ Postfix/TLS 0.9.0. (Or will it finally be 1.0.0? :-)
-+
-+ 2002/12/30
-+ - OpenSSL 0.9.7 has been released. Postfix/TLS works best with the new
-+ 0.9.7 release.
-+
-+ 2002/12/24 == Re-released 0.8.12 ==
-+
-+ 2002/12/24
-+ - Postfix 2.0.0.1 has been released. Resolved one minor patch conflict.
-+
-+ 2002/12/20 == Re-released 0.8.12 ==
-+
-+ 2002/12/20
-+ - Postfix snapshot 1.1.12-20021214 has been released. Resolved minor
-+ patch conflicts.
-+
-+ 2002/12/15 == Re-released 0.8.12 ==
-+
-+ 2002/12/15
-+ - Postfix snapshot 1.1.12-20021214 has been released. Two minor patch
-+ conflicts.
-+
-+ 2002/12/06 == Released 0.8.12 ==
-+
-+ 2002/12/06
-+ - OpenSSL 0.9.6h has been released. Update documentation and filenames
-+ to reflect this new release.
-+ - Minor bug fix: when calling "sendmail -bs", smtpd is not run with
-+ superuser permissions, therefore the loading of the private key fails.
-+ STARTTLS is not used anyway, so the key is not needed anyway, but the
-+ failure to load creates a misleading warning.
-+ Do not initialize TLS engine at all when not started with superuser
-+ permissions.
-+
-+ 2002/12/03
-+ - Postfix snapshot 1.1.12-20021203 has been released. Resolved one patch
-+ conflict.
-+
-+ 2002/11/01 == Re-released 0.8.11a ==
-+
-+ 2002/11/01
-+ - Postfix snapshot 1.1.11-20021031 has been released. No patch conflicts.
-+
-+ 2002/10/30 == Re-released 0.8.11a ==
-+
-+ 2002/10/30
-+ - Postfix snapshot 1.1.11-20021029 has been released. No patch conflicts.
-+
-+ 2002/09/30 == Re-released 0.8.11a ==
-+
-+ 2002/09/30
-+ - Postfix snapshot 1.1.11-20020928 has been released. No patch conflices.
-+
-+ 2002/09/24
-+ - Postfix snapshot 1.1.11-20020923 has been released. Adapt patchkit.
-+
-+ 2002/09/19 == Re-released 0.8.11a ==
-+
-+ 2002/09/18
-+ - Postfix snapshot 1.1.11-20020917 has been released. Adapt patchkit.
-+
-+ 2002/08/23 == Re-released 0.8.11a ==
-+
-+ 2002/08/23
-+ - Postfix snapshot 1.1.11-20020822 has been released. Adapt patchkit.
-+
-+ 2002/08/20
-+ - Postfix snapshot 1.1.11-20020819 has been released with several
-+ enhancements and changes. Adapt patchkit (minor issues).
-+
-+ 2002/08/12
-+ - OpenSSL has experienced several (security critical) updates.
-+
-+ 2002/07/26 == Re-released 0.8.11a ==
-+
-+ 2002/07/26
-+ - On popular demand, a new diff for the snapshot version of Postfix
-+ is created: postfix-1.1.11-20020719.
-+
-+ 2002/06/18 == Re-released 0.8.11a ==
-+
-+ 2002/06/18
-+ - On popular demand, a new diff for the snapshot versions of Postfix
-+ is created: postfix-1.1.11-20020613.
-+
-+ 2002/06/03 == Released 0.8.11a ==
-+
-+ 2002/06/03
-+ - When compiling with SSL but without SASL, compilation fails due to
-+ the modification of state->sasl_mechanism_list that is not part of the
-+ "state" structure when SASL is not compiled in.
-+ This bug was introduced in version 0.8.11.
-+ Bug reported and patch supplied by Bernd Matthes
-+ <bernd.matthes@gemplus.com>.
-+
-+ 2002/05/29 == Released 0.8.11 ==
-+
-+ 2002/05/29
-+ - Postfix 1.1.11 is released.
-+
-+ 2002/05/25
-+ - Fix processing of options after STARTTLS handshaking: AUTH= was not
-+ handled, as the "=" was not recognized as for the extension list for
-+ the case without TLS. (The TLS case was a copy of an older version
-+ of the code not yet containing the "=" and the change in the main
-+ code slipped through without noting the difference, hence the option
-+ as not added to the TLS part.
-+ Found by "Christoph Vogel" <Christoph.Vogel@Corbach.de>.
-+
-+ 2002/05/24
-+ - Bug reported by "Christoph Vogel" <Christoph.Vogel@Corbach.de>:
-+ Client side AUTH does not work, if STARTTLS is used: if a server
-+ announces AUTH and STARTTLS, AUTH is being used if TLS is disabled.
-+ Once TLS is enabled, AUTH is still offered by the server, but the
-+ client does not use it any longer.
-+ Reason: when AUTH is offered, not only the SMTP_REATURE_AUTH flag
-+ is set in state->features, but also the available mechanisms are
-+ remembered in state->sasl_mechanism_list. As AUTH may be offered
-+ twice by some hosts (in the correct "AUTH mech" form and the older
-+ and deprecated "AUTH=mech" form), a check against processing the
-+ line twice is included in smtp_sasl_helo_auth(). This check now
-+ prevented the correct processing in the second evaluation of the
-+ ESMTP extensions offered after the STARTTLS activation.
-+ Solution: reset state->sasl_mechanism_list before processing the
-+ extension list just like state->features.
-+
-+ 2002/05/15 == Released 0.8.10 ==
-+
-+ 2002/05/15
-+ - Postfix 1.1.10 has been released. No changes.
-+
-+ 2002/05/14 == Released 0.8.9 ==
-+
-+ 2002/05/14
-+ - Postfix 1.1.9 has been released. Patchkit requires a small adjustment
-+ (supplied by Tuomo Soini <tis@foobar.fi>).
-+
-+ 2002/05/10 == Released 0.8.8 ==
-+
-+ 2002/05/10
-+ - OpenSSL 0.9.6d has been released. Release the unchanged patchkit
-+ with a new version number and under a new filename to indicate
-+ that it should be built against 0.9.6d (it has the session caching
-+ failure of 0.9.6c fixed). Update documentation accordingly.
-+
-+ 2002/05/05
-+ - Postfix 1.1.8 has been released, the patchkit applies cleanly.
-+
-+ 2002/04/03 == Re-released 0.8.7 ==
-+
-+ 2002/04/03
-+ - Postfix 1.1.7 has been released, the patchkit applies cleanly.
-+ Re-released the patchkit.
-+
-+ 2002/03/29 == Released 0.8.7 ==
-+
-+ 2002/03/29
-+ - Postfix/TLS did not honor the per-recipient-switching-off in SMTP
-+ client mode via tls_per_site (per-host-switching off was honored).
-+ Patch by Will Day <wd@hpgx.net>.
-+
-+ 2002/03/27 == Released 0.8.6 ==
-+
-+ 2002/03/27
-+ - Postfix 1.1.6 has been released. Adapted patchkit to resolve minor
-+ patch conflict. (Template provided by Simon Matter
-+ <simon.matter@ch.sauter-bc.com>)
-+
-+ 2002/03/13 == Released 0.8.5 ==
-+
-+ 2002/03/13
-+ - Postfix 1.1.5 has been released. The patchkit would apply cleanly, but
-+ obviously the "lock_fd" change that applies to dict_dbm.c (Wietse)
-+ also has to be applied to dict_sdbm.c. Tuomo Soini <tis@foobar.fi>
-+ kindly provided this change.
-+
-+ 2002/02/25 == Released 0.8.4 ==
-+
-+ 2002/02/25
-+ - Postfix 1.1.4 became visible. One patch conflict in a Makefile
-+ (Carsten Hoeger <choeger@suse.de>).
-+
-+ 2002/02/21
-+ - Dates in this CHANGES document were showing 2001 even though 2002 already
-+ began :-). Fixed. (Marvin Solomon <solomon@conceptshopping.com>)
-+
-+ 2002/02/07
-+ - Bug in the documentation (setup.html): the main.cf variables for the
-+ SMTP server process have to be named smtpd_* instead of smtp_*.
-+ Found by Andreas Piesk <a.piesk@gmx.net>.
-+
-+ 2002/02/03 == Released 0.8.3 ==
-+
-+ 2002/02/03
-+ - Patch from Andreas Piesk <a.piesk@gmx.net>: remove some compiler warnings
-+ by using explicit type casts in hexdump print statements.
-+ - Re-released otherwise unchanged patchkit against Postfix-1.1.3.
-+
-+ 2002/01/30 == Released 0.8.2 ==
-+
-+ 2002/01/30
-+ - Re-released unchanged patchkit against Postfix-1.1.2.
-+
-+ 2002/01/24 == Released 0.8.1 ==
-+
-+ 2002/01/24
-+ - Postfix-1.1.1 has been released. The patchkit needed some small adjustment.
-+ - Both Tuomo Soini <tis@foobar.fi> and Carsten Hoeger <choeger@suse.de>
-+ helped out with this small adjustment. As a side effect of Carsten's
-+ complete pfixtls.diff, which I compared after applying Tuomo's adjustment,
-+ I found that pfixtls.c contained several wrong "'" characters: on the
-+ german keyboard there is an accent looking like the apostroph but producing
-+ a different binary code. Obviously on Carsten's machine the code was
-+ changed which became obvious during the comparison.
-+ (Conclusion: I wrote the comments affected on my SuSE-Linux PC at home with
-+ german keyboard. In my university-office I do have HP-UX workstations
-+ with US keyboards.)
-+
-+ 2002/01/22 == Released 0.8.0 ==
-+
-+ 2002/01/22
-+ - Received a comment from Wietse on the mailing list, that it is better
-+ to resolve the "standalone" issue by using the already available
-+ SMTPD_STAND_ALONE() macro in smtpd. Undid 0.7.16 change and made
-+ new change in smtpd.c.
-+ - Updated links in the References section of the documentation.
-+
-+ 2002/01/21 == Released 0.7.16 ==
-+
-+ 2002/01/21
-+ - When calling "sendmail -bs" and STARTTLS is enabled, smtpd tries to
-+ read the private key and fails due to insufficient permissions (smtpd
-+ is run with the privileges of the user). This case is caught since
-+ version 0.6.18 of the Postfix/TLS patchkit: STARTTLS is still being
-+ offered but a "465 temporary failure" message is issued. Some mailers
-+ (read this: PINE) will then refuse to continue. (And an irritating
-+ error message indicating the failure to read the key will be logged.)
-+ Experienced by "Lucky Green" <shamrock@cypherpunks.to> .
-+ - Solution: Disable STARTTLS when running "sendmail -bs" by adding
-+ "-o smtpd_use_tls=no -o smtpd_enforce_tls=no" to smtpd's arguments
-+ upon startup. Using STARTTLS does not make sense in simulated
-+ SMTP mode.
-+
-+ 2002/01/18 == Released 0.7.15 ==
-+
-+ 2002/01/18
-+ - Postfix 1.1.0 has been released. The patchkit for the former snapshot
-+ version applied cleanly and now becomes the patchkit for the stable
-+ version.
-+
-+ 2002/01/16 == Released 0.7.14a ==
-+
-+ 2002/01/16
-+ - Snapshot-20020115 is released. Adapted patchkit.
-+ - Add Postfix/TLS entries into the new conf/postfix-files
-+ (Tuomo Soini <tis@s.foobar.fi>, Carsten Hoeger <choeger@suse.de>).
-+
-+ 2002/01/14
-+ - OpenSSL: a user reported that session caching stopped working for him
-+ with OpenSSL 0.9.6c. I found that this is also true for my own
-+ Postfix/TLS installation.
-+ Solution: server side session caching is broken in OpenSSL 0.9.6c when
-+ using non-blocking semantics (Postfix/TLS is affected as it uses
-+ BIO-pairs); sessions are simply not added to the cache. This bug
-+ is not security relevant. A fix has been applied to the OpenSSL source
-+ tree for the next release.
-+
-+ 2002/01/08 == Released 0.7.14 ==
-+
-+ 2002/01/07
-+ - New snapshots released as release candidates. Adapted the patchkit
-+ to snapshot-20020107. Moved our production servers from 20010228-pl08
-+ to snapshot-20020107 with the adapted patchkit.
-+ - Fix documentation: tlsmgr can be run chrooted since a long time.
-+
-+ 2001/12/21
-+ - OpenSSL 0.9.6c is released. Postfix/TLS is fully compatible.
-+
-+ 2001/12/19 == Released 0.7.13e ==
-+
-+ 2001/12/19
-+ - Adapted patchkit to snapshot-20011217.
-+
-+ 2001/12/12 == Released 0.7.13d ==
-+
-+ 2001/12/12
-+ - Adapted patchkit to snapshot-20011210. Adaption provided by
-+ Tuomo Soini <tis@foobar.fi>.
-+
-+ 2001/11/28 == Released 0.7.13c ==
-+
-+ 2001/11/28
-+ - Adapted patchkit to snapshot-20011127.
-+
-+ 2001/11/26 == Released 0.7.13b ==
-+
-+ 2001/11/26
-+ - Adapted patchkit to snapshot-20011125.
-+
-+ 2001/11/22 == Released 0.7.13a ==
-+
-+ 2001/11/22
-+ - Adapted patchkit to snapshot-20011121.
-+
-+ 2001/11/15 == Released 0.7.13 ==
-+
-+ 2001/11/15
-+ - Adapted patchkit to postfix-20010228-pl08 and snapshot-20011115.
-+
-+ 2001/11/06 == Re-released 0.7.12 ==
-+
-+ 2001/11/06
-+ - Snapshot-20011105 released. No patch conflicts, but in order to have
-+ the pfixtls-* filename and home page entry reflect the new version,
-+ I'll re-release 0.7.12.
-+
-+ 2001/11/05 == Released 0.7.12 ==
-+
-+ 2001/11/05
-+ - Release of Postfix-20010228-pl06 and snapshot-20011104. The snapshot
-+ version had some minor patch conflicts to be resolved.
-+
-+ 2001/10/14 == Released 0.7.11 ==
-+
-+ 2001/10/14
-+ - Bug fix (client mode): when the peername is checked against the CommonName
-+ in the certificate, the comparison does not correclty ignore the case
-+ (the peername as returned by DNS query or set in the transport map
-+ is not transformed to lower case). This bug was introduced in 0.7.5.
-+
-+ 2001/10/09 == Released 0.7.10 ==
-+
-+ 2001/10/09
-+ - Snapshot-20011008 is released. Some minor adaptions are required to
-+ sort out patch conflicts.
-+
-+ 2001/09/28
-+ - Received patch from Uwe Ohse <use@ohse.de>: There is a bug in sdbm's
-+ handling of the .dir file, that also applies to Postfix/TLS.
-+ The problem only appears for large databases.
-+ - The example entries in conf/master.cf for the submission and smtps services
-+ use "chroot=y" flags, while the Postfix default is "chroot=n". This could
-+ lead to hardly explainable problems when users did not note this fact
-+ during setup.
-+ Fixed example entries to also use "chroot=n" default.
-+
-+ 2001/09/18
-+ - Wietse releases Postfix-20010228-pl05. The patch applies cleanly with
-+ "patch -p1 ...", so it is not necessary to release a new patchkit.
-+
-+ 2001/09/04 == Released 0.7.9 ==
-+
-+ 2001/09/04
-+ - Due to unititialized variable in smtpd_state.c, AUTH may not be offered
-+ without TLS even though smtpd_tls_auth_only was not enabled.
-+ (Patch from Nick Simicich <njs@scifi.squawk.com>.)
-+
-+ 2001/08/29
-+ - In the snapshot-20010808 version of 0.7.9, the "tlsmgr" line in the sample
-+ conf/master.cf is missing (reported by Will Day <wd@hpgx.net>). Fixed.
-+
-+ 2001/08/27 == Released 0.7.8 ==
-+
-+ 2001/08/27
-+ - Received bugreport about issuer_CN imprints consisting of long strings
-+ of nonsense. This only appeard with certificates issued from a certain
-+ CA (RSA Data Security Inc., Secure Server Certification Authority).
-+ (Will Day <wd@hpgx.net>)
-+ - The problem: the issuer data of this certificate is:
-+ Issuer
-+ C=US
-+ O=RSA Data Security, Inc.
-+ OU=Secure Server Certification Authority
-+ It does not contain a CN (CommonName) field. OpenSSL's
-+ X509_NAME_get_text_by_NID() function does not catch this condition
-+ (no error flag set), but it also does not set the name in the memory
-+ location specified.
-+ - Solution:
-+ 1. Preset the memory for the string to '\0', so that a string of length
-+ 0 is obtained on the failure described above.
-+ 2. When no CN data is available, use the O (Organization) field
-+ instead. The data are used for logging only (it is the issuer, not
-+ the subject name), so this change does not affect functionality.
-+
-+ 2001/08/22 == Released 0.7.7 ==
-+
-+ 2001/08/22
-+ - Found one more bug: erronously called SSL_get_ex_new_index() instead
-+ of SSL_SESSION_get_ex_new_index() (note the _SESSION missing). This
-+ could be responsible for the failure at the locations found during
-+ debugging. Works fine on HP-UX (did also before), must cross check
-+ at home...
-+
-+ 2001/08/21
-+ - Received report, that smtp (client) fails with signal 11 (platform:
-+ linux redhat). Cannot reproduce any problem on HP-UX (did run 1
-+ week in production before release). But malloc() and stack strategies
-+ are different between platforms.
-+ - Can reproduce the failure on my Linux PC at home :-(.
-+ - Found one bug in new_session_cb(): on successfull external caching,
-+ success is reported by a return value of 1. This however must be another
-+ bug, as it has nothing to do with the locations of the failure, when
-+ analyzing the core dumps/running under debugger.
-+ Still getting SIGSEGV...
-+
-+ 2001/08/20 == Released 0.7.6 ==
-+
-+ 2001/08/20
-+ - Following "popular demand" implemented new feature and configuration option
-+ "smtpd_tls_auth_only": Only allow authentication using the AUTH protocol,
-+ when the TLS encryption layer is active. Default is "no" in order to
-+ keep compatiblity to postfix without TLS patch.
-+ This option does not distinguish between different AUTH mechanisms.
-+
-+ 2001/08/16 == Released 0.7.5 ==
-+
-+ 2001/08/15
-+ - The new session cache handling is working now at my site for quite some
-+ time.
-+ - Client side: modified peername matching code, such that wildcard
-+ certificates can be used. Matching is done as in HTTP/TLS: only the
-+ leftmost part of the hostname may be replaced by a '*'.
-+
-+ 2001/08/09
-+ - Further debugged the CRYPTO_set_ex_data() functionality.
-+ - Unified "external cache write" and "external cache remove" callbacks
-+ for client and server side. The "external cache read" functions are not
-+ that easy to combine, as the lookup keys are quite different and do not
-+ match the fixed interface to the callback function.
-+ - Change shutdown behaviour according to SSL_shutdown(). When SSL_shutdown()
-+ returns, the shutdown handshake may not be complete, if we were the first
-+ party to send the shutdown alert. We must call SSL_shutdown() again,
-+ to wait for the peer's alert.
-+
-+ 2001/08/08
-+ - Postfix snapshot 20010808 is being released.
-+
-+ 2001/08/08
-+ - Rewrite server side to remove externally cached sessions via callback.
-+ - Rewrite client side to remove externally cached sessions via callback.
-+ This turns out to be more difficult as expected, as the client side
-+ session cache is sorted by hostnames, but the callbacks are called
-+ with the SSL_SESSION objects. The information must be stored into the
-+ SSL_SESSION objects by using the CRYPTO_set_ex_data() functionality,
-+ the documentation of which, ahem, ...
-+ - Reloading sessions stays separate, as the functionality is different.
-+
-+ 2001/08/07
-+ - Started reworking the session cache code.
-+ * On the server side the retrieval from the external cache and the writing
-+ to the cache are handled by callback functions. The removal is handled
-+ directly.
-+ * On the client side, all session cache operations are performed explicitly.
-+ * The explicit handling is on the client side is bad, as it requires a
-+ quite complicated logic to detect session reuse and the appropriate
-+ handling.
-+ * The explicit handling of session removal on both sides is bad, as
-+ the OpenSSL library will remove sessions (on session failure) according
-+ to the TLS specifications automatically, so we want to take advantage
-+ of this feature and have the externally cached sessions removed as
-+ required via callback.
-+ - First step: on the client side, also use the new_session_cb(), so that
-+ new sessions are automatically saved to the external cache on creation.
-+
-+ 2001/08/01
-+ - Postfix-20010228-pl04 is being released.
-+
-+ 2001/07/11 == Released 0.7.4 ==
-+
-+ 2001/07/10
-+ - Postfix snapshot 20010709 was released. Resolved some minor patch
-+ conflicts.
-+
-+ 2001/07/10
-+ - OpenSSL 0.9.6b has been released including a security fix for the
-+ libraries internal pseudo random number generator.
-+ * Note: to exploit the weakness, an attacker must be able to retrieve
-+ single random bytes. As in Postfix/TLS random bytes are only used
-+ indirectly during the SSL handshake, an attacker could never access
-+ the PRNG in the way required to exploit the weakness.
-+ * Postfix/TLS is therefore not vulnerable (as are most (all?) applications
-+ utilizing the SSL layer).
-+ * The OpenSSL team however recommends to upgrade or install the bugfix
-+ included in the announcement in any case.
-+ * Details can be found at http://www.openssl.org/
-+
-+ 2001/05/31 == Released 0.7.3a ==
-+
-+ 2001/05/30
-+ - Report from <Andre.Konopka@Presse-Data.de>: TLS logging does not work.
-+ Reason: parameters are not evaluated in mail_params.c, as the corresponding
-+ lines for other_int_defaults[] were missing from the patch. This
-+ only affected the 0.7.3-snapshot version, the version for "stable"
-+ is correct.
-+ I will release 0.7.3a with this fix only for the snapshot version to keep
-+ version numbering consistent with the "stable" version.
-+
-+ 2001/05/28 == Released 0.7.3 ==
-+
-+ 2001/05/28
-+ - Upgraded to snapshot-20010425: resolved some minor patch conflicts.
-+ No functional changes.
-+
-+ 2001/05/16
-+ - Received french documentation (doc_french/) contributed by
-+ Etienne Roulland <Etienne.Roulland@univ-poitiers.fr>.
-+
-+ 2001/05/03 == Released 0.7.2 ==
-+
-+ 2001/05/03
-+ - Postfix-Snapshot 20010502 is released. Bernhard Rosenkraenzer
-+ <bero@redhat.de> supplies an adapted patch for Postfix/TLS, as the
-+ normal patch has several rejections because of code changes;
-+ functionality has not changed.
-+
-+ 2001/05/01
-+ - Patchlevel 02 of Postfix 20010228 is being released. The Postfix/TLS
-+ patchkit applies cleanly when using the "-p1" switch to patch.
-+
-+ 2001/04/09 == Released 0.7.1 ==
-+
-+ 2001/04/06
-+ - OpenSSL 0.9.6a is released. It contains several bugfixes and will become
-+ the recommended version to be used with Postfix/TLS.
-+ I will run some more test and then re-release Postfix/TLS (without
-+ additional changes to the source) as 0.7.1 to make people aware of the
-+ new versions of Postfix and OpenSSL.
-+
-+ 2001/04/05
-+ - Hint from Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>:
-+ the "Known Bugs" section in doc/test.html actually contains bugs
-+ of clients and/or interoperatbility problems. Better name it
-+ "Known interoperability problems" and rename the entries
-+ "Postfix/TLS server" and "Postfix/TLS client" to improve clarity.
-+
-+ 2001/03/29
-+ - Patchlevel 01 of Postfix 20010228 is being released. The Postfix/TLS
-+ patchkit applies cleanly when using the "-p1" switch to patch.
-+ OpenSSL 0.9.6a will be out within the next handful of days, so I will
-+ delay the release of a new patchlevel until then.
-+
-+ 2001/03/01 == Released 0.7.0 ==
-+ - IMPORTANT: If you are upgrading from a much older version, you will find
-+ that some configuration options have changed over time (fingerprints are
-+ now handled with ':'. check_relay_ccerts is now permit_tls_clientcerts.
-+ Session caching has been reworked.)
-+ It is recommended to re-read the sample-tls.cf file or the html version
-+ in the documentation.
-+
-+ 2001/03/01
-+ - Wietse has announced the _release_ version (non-beta) or postfix:
-+ 20010228!
-+ - Applied the Patchkit to the _release_ version (not the snapshot version).
-+ Resolved one minor patch conflict.
-+ - So, it's time to call this Postfix/TLS 0.7.0.
-+
-+ 2001/02/26 == Released 0.6.38 ==
-+
-+ 2001/02/26
-+ - Snapshot-20010225 has been released. Resolved one minor patch conflict.
-+
-+ 2001/02/23 == Released 0.6.37 ==
-+
-+ 2001/02/23
-+ - Snapshot-20010222 has been announced as RELEASE CANDIDAT. Resolved one
-+ minor patch conflict.
-+ - Removed "check_relay_ccerts" restriction which has been replaced
-+ by "permit_tls_clientcerts" in 0.6.24. (Was left in until now for
-+ transition.)
-+ - Do not try to save session data > 8kB, since this cannot be handled
-+ by SDBM. (This is more or less academical, since I have never met a
-+ session even half that large.)
-+
-+ 2001/02/19 == Released 0.6.36 ==
-+
-+ 2001/02/05
-+ - Snapshot-20010204 has been released. Resolved one minor patch conflict.
-+
-+ 2001/02/03 == Released 0.6.35 ==
-+
-+ 2001/02/03
-+ - Snapshot-20010202 has been released. Resolved one minor patch conflict.
-+
-+ 2001/01/29 == Released 0.6.34 ==
-+
-+ 2001/01/29
-+ - Snapshot-20010128 has been released. Resolved some minor patch conflicts.
-+
-+ 2001/01/11 == Released 0.6.33 ==
-+
-+ 2001/01/10
-+ - Discussion in Thread "When to get peer certificate?" continues and it
-+ comes out, that cross references between datastructures are well maintained
-+ inside OpenSSL. A fact not well known due to lack of documentation
-+ (seems I am facing some more work on the OpenSSL manpages :-).
-+ - Moved around data needed for the certificate verification: a lot of
-+ "static" entries globally needed inside pfixtls.c could now be moved
-+ into the connection specific TLScontext.
-+
-+ 2001/01/07 == Released 0.6.32 ==
-+
-+ 2001/01/07
-+ - Since now the checks at handshake stage (in pfixtls.c) are more strict,
-+ some of the checks in smptd.c and smtp_proto.c could be removed.
-+ At a later point I can probably move even more checks into pfixtls.c...
-+
-+ 2001/01/05
-+ - Had a discussion with Ari Pirinen <aripirin@europe.com> on openssl-users
-+ (Thread: When to get peer certificate?) about the earliest possible
-+ place to check the CommonName of the peer against the expected name.
-+ (This is what smtp does when enforcing the peername of the server it
-+ is connecting to.)
-+ The final result was, that the check can already been done inside the
-+ verifiy_callback() routine even before the handshake is completed.
-+ The positive side effect is, that since the session is never completly
-+ established, it is also not cached on either client or server.
-+ - Since this is a good idea, I have extended the verify_callback in
-+ src/global/pfixtls.c to check the CommonName of the peer (if applicable)
-+ and have the handshake shut down immediatly on failure. I have also
-+ changed the behaviour so that whenever a positive certificate verification
-+ is required, the handshake is shut down immediatly.
-+ (The versions up to now did delay these checks until the session was
-+ established and then shut down the connection. I had established this
-+ practice while working on BIO-pairs and running into a bug in
-+ OpenSSL 0.9.5 (fixed now) and with the verify depth.)
-+
-+ 2000/12/23 == Released 0.6.31 ==
-+
-+ 2000/12/23
-+ - Bug: When only enabling smtpd_tls_wrappermode and not additionally setting
-+ smtpd_use_tls or smtpd_enforce_tls, the TLS engine was not fired up on
-+ startup of smtpd
-+ Fixed: also start TLS engine when only smtpd_tls_wrappermode is enabled.
-+ (Experienced by "Fiamingo, Frank" <FiamingF@strsoh.org>)
-+
-+ 2000/12/18 == Released 0.6.30 ==
-+
-+ 2000/12/18
-+ - New snapshot 20001217 has been released. Due to the change of "timeout"
-+ parameters now being its own class and table, the old patchkit does not
-+ apply cleanly!
-+ - Checked out Postfix/TLS parameters being timeout values and put them into
-+ the new style time parameter table. This allows to specify time values
-+ like 3600s or 1h. Updated sample configuration to reflect this new style.
-+ - "Fiamingo, Frank" <FiamingF@strsoh.org> pointed out to me, that there are
-+ three parameters in src/global/mail_params.h (namely DEF_TLS_RAND_EXCH_NAME,
-+ DEF_SMTPD_TLS_CERT_FILE, DEF_SMTPD_TLS_CA_FILE) that are hardcoded as
-+ "/etc/postfix/something".
-+ This does not match the usual style of postfix, where no paths are
-+ hardcoded this way. I have removed the defaults for CERT_FILE and CA_FILE.
-+ The RAND_EXCH is needed for good PRNG seeding on systems without
-+ /dev/urandom, I however don't know yet, how to rearrange this requirement.
-+ I could use the Postfix internal mechanisms to enforce a parameter, but
-+ this would annoy people having compiled in TLS but not activated.
-+
-+ 2000/12/13 == Released 0.6.29 ==
-+
-+ 2000/12/13
-+ - Snapshot-20001212 has been released.
-+ - Undid bugfixes for 20001210 which now are included in the new snapshot.
-+
-+ 2000/12/12 == Released 0.6.28 ==
-+
-+ 2000/12/12
-+ - Added bugfix provided by Wietse on postfix-users@postfix.org for
-+ "postconf -m" behaviour.
-+
-+ 2000/12/11
-+ - New snapshot-20001210 released. Some patch conflicts occur. Additionally
-+ * adjusted calls to myflock() to changed interface,
-+ * fixed bug in smtpd_sasl_glue(), where a change to the name_mask()
-+ call was not applied in the original snapshot.
-+
-+ 2000/12/05 == Released 0.6.27 ==
-+
-+ 2000/12/04
-+ - Print informational message "SSL session removed" only when
-+ var_smtp[d]_loglevel >= 2. (Proposed by Craig Sanders <cas@taz.net.au>.)
-+ - Extend logging of "setting up TLS connection from/to" and corresponding
-+ success/failure messages so that they include the hostname/ip address.
-+ This way it is much easier to automatically analyze errors by simply
-+ grepping for e.g. "SSL_accept error" and immediately get the peer
-+ causing the problem without further logfile processing.
-+ (Proposed by Craig Sanders <cas@taz.net.au>.)
-+ - When experiencing a TLS failure due to TLS-enforced failure in client mode
-+ (no certificate or hostname/certificate mismatch etc), immediately shut
-+ down the TLS mode with "failure" indication, so that the SSL session is
-+ removed immediately. This way a new session is always enforced in the
-+ case the peer has fixed the problem; no need to wait for the timeout.
-+
-+ 2000/11/29 == Released 0.6.26 ==
-+
-+ 2000/11/29
-+ - Found security relevant bug in the OpenSSL library: the verify_result
-+ stating whether or not the certificate verification succeeded is not
-+ stored in the session data to be cached and reused.
-+ - This bug was found during the development of Postfix/TLS around one
-+ year ago, the bug in the library was however only fixed for the server
-+ side. At that time I also tested the server side behaviour but ommitted
-+ to check the client side, too.
-+ - Versions before Postfix/TLS 0.4.4 experienced this problem for both
-+ server and client side. Before 0.6.0 a workaround was active for both
-+ sides, which has been removed at 0.6.0 in the believe that the bug
-+ was gone (I only tested the server side, which was fixed).
-+ - Fixed that bug in OpenSSL also for the client side (I can do this myelf
-+ now that I have been invited to join the OpenSSL developers team :-).
-+ The fix is availabe as of today and will be part of the 0.9.7 release
-+ of OpenSSL (or 0.9.6a, if this release will be published).
-+ - Included a workaround inside Postfix/TLS for OpenSSL library versions
-+ before 0.9.6a or 0.9.7, respectively.
-+
-+ ********************** Begin Description
-+
-+ - By not caching the verify_result for the client side, the following
-+ behaviour could appear:
-+ * The problem can only appear when smtp_tls_session_cache_database
-+ is activated.
-+ * smtp_use_tls = yes
-+ X On the first connection, the certificate fails verification, failure
-+ is logged:
-+ smtp[*]: Unverified: subject_CN=serv01.aet.tu-cottbus.de, issuer_CN=BTU-CA
-+ For any following connections until the session times out (default 1 hour),
-+ the peer certificate seems to pass verification:
-+ smtp[*]: Verified: subject_CN=serv01.aet.tu-cottbus.de, issuer_CN=BTU-CA
-+ X Security Impact:
-+ Unverified certificates are logged as if verification had succeeded.
-+ * smtp_enforce_tls = yes
-+ X After the verification failure, the session is never correctly established
-+ and hence not reused.
-+ X Security impact:
-+ None, as the session is never reused.
-+ * smtp_enforce_tls = yes after smtp_tls_enforce_tls = yes for a server.
-+ X If the session has been recorded with use_tls and then for this server
-+ enforce_tls is set, the wrong verify_result could be used within the
-+ session cache timeout (default = 1 hour).
-+ X Security impact:
-+ If TLS shall be enforced for a recipient, there is a window of approx.
-+ one hour from setting the "enforce_tls" switch until a verification
-+ failure is noted. For this to happen, a TLS session to that server must
-+ have been used with use_tls set and the not-verifiable certificate must
-+ have been recorded in that session.
-+ - Evaluation:
-+ Even though this _is_ a security problem, I consider risk to be *low*,
-+ given the conditions under which the problem might occur.
-+
-+ ********************** End Description
-+
-+ 2000/11/27 == Released 0.6.25 ==
-+
-+ 2000/11/26
-+ - Added "permit_tls_all_clientcerts" for smtpd_recipient_restrictions.
-+ When this option is enabled, any valid client certificate allows relaying.
-+ This can be practical, if e.g. a company has a special CA to create
-+ these certificates and only this CA is "trusted". It however does not
-+ allow finer control, so if e.g. an employee leaves, he could still
-+ relay. Postfix/TLS does not (yet) allow CRL (certificate revocation lists).
-+ (Added on popular demand.)
-+ - Make the client behaviour more configurabe: when enforcing TLS connections,
-+ the peer's name is checked against the CommonName in its certificate.
-+ New configuration variable "smtp_tls_enforce_peername" (default=yes)
-+ can now be used to accept peername!=CommonName. The server's certificate
-+ must still pass the verifcation process against a trusted CA!
-+ In tls_per_site, the according key is MUST_NOPEERMATCH.
-+ (Added on demand.)
-+
-+ 2000/11/24
-+ - If the server requires a client certificate and no certificate is presented
-+ or the certificate fails verification, the connection is shut down but
-+ no information is logged.
-+ -> add according msg_info() in smtpd/smtpd.c:startls_cmd().
-+ - If TLS is not enforced, it does not make sense for a server to require a
-+ client certificate. If no STARTTLS is issued, the SMTP would continue
-+ anyway, so why shut down when TLS is activated without verifyable client
-+ certificate?
-+ -> ignore smtpd_tls_req_ccert=yes, if TLS is not enforced and only treat
-+ like smtpd_tls_ask_ccert = yes with an according information logged.
-+
-+ 2000/11/22 == Released 0.6.24 ==
-+
-+ 2000/11/22
-+ - Installed on my own servers and changed configuration to use the new
-+ "permit_tls_clientcerts" option name. Patchkit will be released after
-+ some hours of successfull operation.
-+
-+ 2000/11/21
-+ - New snapshot-20001121 is being released. The patch applies without any
-+ conflict when applied with "patch -p1", so no need to rush out an updated
-+ patchkit.
-+ - Rename the smtpd_recipient_restrictions option from "check_relay_ccerts"
-+ to "permit_tls_clientcerts" to better match the naming scheme.
-+ Leave in the old option for now to not break existing configurations.
-+ The final incompatible removing is scheduled of release 0.7.0 of the
-+ patchkit which will be matching the next "stable" release of postfix.
-+ - There is no manual page for tlsmgr.8 (pointed out by Terje Elde
-+ <terje@thinksec.com>).
-+ Fix the comments at the beginning of tlsmgr.c and create tlsmgr.8.
-+ - In the session cache code an additional 20 bytes were allocated when
-+ converting SSL_SESSION data to binary using i2d_SSL_SESSION().
-+ In adding these 20 bytes to the size listed by i2d_SSL_SESSION() I followed
-+ the example in the OpenSSL source (PEM_ASN1_write()). These 20 bytes are
-+ only added since when writing the PEM, a 20 byte checksum is added, so
-+ we don't need it in our case -> removed.
-+ (Researched after Carlos Vicente <cvicente@mat.upc.es> asked what these
-+ 20 bytes are good for :-)
-+
-+ 2000/10/30 == Re-Released 0.6.23 ==
-+
-+ 2000/10/30
-+ - Postfix snapshot-20001030 with an important bug fix is made available.
-+ The patchkit applies without any problem (patch -p1).
-+ Hence, I re-release the 0.66.23 release for the new snapshot.
-+
-+ 2000/10/30 == Released 0.6.23 ==
-+
-+ 2000/10/30
-+ - New Postfix snapshot 20001029 available with some important bug fix.
-+ Adjusted patchkit (only minor conflicts).
-+
-+ 2000/10/27
-+ - The CN_sanitize function (src/smtpd/smtpd.c) that shall make sure that
-+ no illegal sign is included into the Received: header does not work
-+ on systems were "char" is unsigned by default.
-+ (Linux on s390, found by Carsten Hoeger <choeger@suse.de>)
-+ -> Worked out a more precise (even though not looking elegant) solution
-+ that checks out all acceptable characters.
-+ - Sent new smptd.c to Carsten Hoeger for testing, will wait with new
-+ Postfix/TLS release.
-+
-+ 2000/10/06 == Released 0.6.22 ==
-+
-+ 2000/10/06
-+ - snapshot-20001005 has been released, featuring fast ETRN. Only some minor
-+ patch conflicts needed to be resolved.
-+
-+ 2000/09/28 == Released 0.6.21 ==
-+
-+ 2000/09/28
-+ - snapshot-20000924 seems to be somewhat longer lasting. I have been asked
-+ for a new Postfix/TLS release against snapshot-20000924, hence I will
-+ create one.
-+ - Running OpenSSL 0.9.6 for a week now to my full satisfaction. I will bump
-+ bump up the Postfix/TLS version counting to include "0.9.6", even though
-+ it will still run fine with 0.9.5a.
-+
-+ 2000/09/25/
-+ - snapshot-20000924 is available; only small adjustments.
-+ - Wietse seems to release new snaphots on a daily basis, it doesn't make
-+ sense to follow with a new Postfix/TLS release every day.
-+
-+ 2000/09/23 == Released 0.6.20 ==
-+
-+ 2000/09/23
-+ - Recompile OpenSSL-0.9.6-beta3 with the change and reinstall old pfixtls.c:
-+ works again. Hence, all versions of Postfix/TLS working against 0.9.5a
-+ will also work again 0.9.6-final, which shall be released on 2000/09/24!
-+ - Wietse releases snapshot-20000923, patchkit adapted.
-+ - Went through the "install.html" document to add a remark about
-+ OpenSSL-0.9.6. This document is of historic quality but did not fit
-+ actual versions of Postfix/TLS, we are far beyond OpenSSL 0.9.2: Updated.
-+
-+ 2000/09/22
-+ - Wietse releases snapshot-20000922. The source directory hierarchie has
-+ changed, so the patch needs to be adjusted at several places.
-+ - Run tests against OpenSSL 0.9.6-beta3: problems occur!
-+ * Certificates are no longer verified, since an informationa flag about the
-+ CA certificate search process is written into the error storage and
-+ thus misinterpreted as verification failure.
-+ * Changed Postfix/TLS source to maintain its own error storage based on
-+ the verify_callback, send out according warning to Postfix/TLS mailing
-+ list.
-+ * Unfortunately, this will break all older versions of Postfix/TLS.
-+ Sent out analysis to OpenSSL-bugs@openssl.org.
-+ * Additional change is made to OpenSSL: the new behaviour is only activated
-+ when a special flag is set, so compatibility is restored!
-+
-+ 2000/09/21
-+ - Wietse releases snapshot-20000921. Some minor patch conflicts resolved.
-+
-+ 2000/09/14 == Released 0.6.19 ==
-+
-+ 2000/09/14
-+ - Received a bug report: Postfix/TLS will accept a mail even though
-+ smtpd_req_ccert=yes (require use of client certificate) and no
-+ client certificate is presented.
-+ Reason: when no client certificate is presented SSL_get_verify_result()
-+ will return X509_V_OK, since this is the default value.
-+ Solution: only set "peer_verified" internal information, if the
-+ verify_result is X509_V_OK _and_ a peer certificate is available.
-+ Remark: This default value does not make too much sense. I will file
-+ a bug report/patch before the next release of OpenSSL...
-+
-+ 2000/09/03 == Released 0.6.18 ==
-+
-+ 2000/09/03
-+ - When calling "sendmail -bs", smtpd is started without root privileges,
-+ hence it cannot open the private key file and the session cache database.
-+ Since the database routines do not offer a graceful return (only fatal
-+ and abort), this leads to a failure when TLS and session caching is
-+ activated.
-+ This affects PINE users (noted by Craig Sanders <cas@taz.net.au>).
-+ Solution: Try to read the private key first; if that fails, we can
-+ gracefully recover and won't touch the session cache database at all.
-+ - When STARTTLS is configured for smtpd but does not work (e.g. because of
-+ unaccessible keys), smtpd answers with "465 TLS not available due to
-+ temporary reasons". After that the connection was closed, this is however
-+ not necessary, as the client may decide to continue without TLS activated.
-+ - Craig Sanders <cas@taz.net.au> contributes a script to automatically
-+ generate the keys and certificates for Postfix/TLS usage. Added
-+ "make-postfix-cert.sh" to the contributed/ directory.
-+
-+ 2000/09/02 == Released 0.6.17 ==
-+
-+ 2000/09/02
-+ - Craig Sanders <cas@taz.net.au> reports that he has connection problems
-+ with a site; the message in the log is:
-+ SSL_connect error 0
-+ 8847:error:140943F2:SSL routines:SSL3_READ_BYTES:sslv3 alert unexpected message:s3_pkt.c:956:SSL alert number 10:
-+ * This is the error caused by the faulty TLS implementation with
-+ CommunigatePro. The bug is fixed in later versions of CommunigatePro,
-+ The site shall be contacted, they should update.
-+ - More important, he reports a segmentation fault immediately after this
-+ problem.
-+ - Bug: when not using session caching and an error occurs during the TLS
-+ handshake, pfixtls_start_clienttls() tried to remove the erronous
-+ session from a non-existant session cache.
-+ Fix: check the existence of the session cache before trying to access it.
-+ Comment: at all other places in the code this condition was already
-+ caught.
-+ - Remark: actually session caching was configured, but the configuration
-+ variable was mistyped because...
-+ it was wrong in conf/sample-tls.cf and doc/conf.html.
-+ The correct values are "smtp[d]_tls_session_cache_database" instead of
-+ "smtp[d]_tls_use_session_cache_database".
-+ Unfortunately this is not flagged by Postfix...
-+
-+ 2000/08/25 == Released 0.6.16 ==
-+
-+ 2000/08/25
-+ - Make sure, that the smtp[d] processes will try to access the "daemon"
-+ entropy sources, but will only print an info when not available. Using
-+ the PRNG-exchange file, they can happily run without.
-+ - Moved HAS_SSL checks, such that the package compiles also when configured
-+ without -DHAS_SSL.
-+
-+ 2000/08/24
-+ - Changed the handling of the PRNG-exchange file. Until now it was written
-+ by tlsmgr and read by the smtp[d] daemons. This had the disadvantage, that
-+ until tlsmgr rewrote new bytes to the file, all starting daemons read the
-+ same seed (to which some more bits, but not too much were added).
-+ - Now the file is handled in read->stir into pool->write back mode, so that
-+ every daemon will add its own entropy bits.
-+ - The smtp[d] processes will do so when starting, when opening a TLS
-+ connection and when closing.
-+ - The tlsmgr will also read back the file and add it to its pool, so that
-+ no entropy is lost.
-+ - This change significantly increases the "self seeding" capability of
-+ the TLS service.
-+
-+ 2000/08/09
-+ - Cleaned up the new PRNG-seeding.
-+ - When tlsmgr looses connection to an EGD-source (because it was restarted),
-+ tlsmgr performes an exit(0), so that a newly started tlsmgr can reconnect.
-+ [chroot/dropped privileges].
-+
-+ 2000/08/04
-+ - Introduced new entropy sources for single daemons:
-+ * tls_daemon_random_source
-+ Using this source (same style as for tlsmgr), each starting daemon can
-+ obtain additional entropy (32 bytes by default). The PRNG-exchange file
-+ is still read.
-+ - I am not sure about the policy for this feature. If such a source is
-+ given, should a failure be considered fatal?
-+
-+ 2000/07/23
-+ - Started reworking the PRNG seeding:
-+ * tlsmgr now recognizes tls_random_source as
-+ dev:/dev/urandom /* Direct read from device file */
-+ egd:/path/to/socket /* Connection via EGD-socket */
-+ /path/of/plain-file
-+ * If a dev: or egd: is given, tlsmgr will connect and keep the connection
-+ open, so that it now can run in chroot-mode with dropped privileges.
-+ - Since EGD can be drained, but the connection is permanently open, only
-+ suck a small number of bytes (default 32) at a time, but do it more
-+ often.
-+
-+ 2000/08/09 == Released 0.6.15 ==
-+
-+ 2000/08/09
-+ - Traced through OpenSSL to learn more about the verify_callback-feature.
-+ The callback is called several times. When it returns "1", the handshake
-+ will continue, when it calls "0", the handshake will immediately fail
-+ (and Postfix/TLS will also close the TCP connection).
-+ - Following the sample in the OpenSSL-apps, the verification chain depth
-+ was the only property triggering this effect, so this stood hidden until
-+ now. Obviously, users having longer chains did set the verifcation
-+ depth accordingly or they gave up, since this was never reported...
-+ - Changed the behaviour of verify_callback() to never return "0", such that
-+ we can deal with the verification result later in a more consistent manner.
-+ If we only enable and not enforce, we simply want to ignore problems with
-+ the certificate.
-+ - verify_callback() did not print out all information, since the wrong
-+ state variables (pfixtls_*active instead of pfixtls_*engine) were
-+ checked. The *active state variables are only set later.
-+ As the verify process now became rather narrative, the normal logging
-+ is only done in loglevel 2!
-+ - Arrrghhh. The conf/sample-tls.cf _and_ the html-docu (which is actually
-+ copied from conf/sample-tls.cf) has wrong names for the verification-
-+ depth parameters. *_vd instead of *_verifydepth and ccert<->scert.
-+ [Wondering, why this never popped up before...]
-+ - Changed the default-verifydepth to "5" which should suffice for most
-+ cases. Maybe the limit could also be completely removed, but we should
-+ at least receive a warning hint when something goes wild.
-+ Since OpenSSL>=0.9.5 is required for Postfix/TLS anyway, certificate chain
-+ verification can now be used, so the caution applied before is no longer
-+ necessary.
-+
-+ 2000/08/08
-+ - Tracked down the double-free() call in smtp with Efence. SSL_free()
-+ does call SSL_SESSION_free() on the negotiated session. Hence, I must
-+ not call SSL_SESSION_free() on the session in question, it will be
-+ removed anyway.
-+ - Also tracked down the certificate chain feature. Reason is the
-+ verify_callback() in global/pfixtls.c. It flags a chain depth that
-+ is too long as fatal, hence the connection is immediately closed.
-+
-+ 2000/08/04
-+ - Received information from Alain Thivillon <Alain.Thivillon@hsc.fr>:
-+ FreeBSD-CURRENT offers malloc() with additional checks enabled.
-+ After successfully delivering, smtp dumps core with free() called
-+ twice in TLS mode.
-+ - I noted, that there is a communication problem with his site an my new
-+ certificate issued by the universities computer center (which has a chain
-+ depth of 2). Step back to the old self certificate for the time being.
-+
-+ 2000/07/27 == Released 0.6.14 ==
-+
-+ 2000/07/27
-+ - Introduced new configuration parameter "smtpd_tls_wrappermode" that
-+ enables the (deprecated) old style SSL-wrapping around SMTP. It could
-+ be run on a different port (once smtps=465) was recommended for this
-+ services.
-+ This method is used by old versions of Outlook (Express), the Mac versions
-+ and even actual versions, when not run on port 25.
-+ [Actually it was only a handful of lines, so it doesn't hurt too much,
-+ even though it does not follow any RFC.]
-+ - I recommend using this option only from master.cf. Example lines added
-+ to conf/master.cf and description added to Postfix/TLS-doc/conf.html.
-+ - When having SASL enabled and TLS-enforce mode in "smtpd", only offer
-+ AUTH, when TLS has been activated. Otherwise the client might simply
-+ send the unencrypted credentials before it receives
-+ 530 Must issue a STARTTLS command first
-+ and an eavesdropper already has what he was looking for.
-+
-+ 2000/07/19 == Released 0.6.13 ==
-+
-+ 2000/07/19
-+ - Changed the library-initializaton call to new naming scheme
-+ (SSLeay_add_ssl_algorithms() to OpenSSL_add_ssl_algorithms() :-).
-+ - Updated documentation to reflect the use of chain certificates with
-+ CAfile and smtp[d]_tls_cert_file (see 2000/07/06).
-+ - Documentation: the interoperability problem with CommunigatePro has been
-+ solved: CommunigatePro violated the TLS-RFC and has been fixed.
-+ - Typo: It is "to stir" not "to stirl" :-)
-+
-+ 2000/07/06
-+ - Received certificate for our site from our computer center. It's a chain
-+ certificate. Now load the cert with SSL_CTX_use_certificate_chain_file(),
-+ in order to better load the chain CA certificates.
-+
-+ 2000/07/04
-+ - Reported Wietse about a possible problem in the SASL code, a relay check
-+ may also be performed if sasl was not enabled and might lead to unwanted
-+ relay.
-+ As the fix is in my own codebase, I will leave it Postfix/TLS until a
-+ new snapshot (or final release) is available.
-+
-+ 2000/06/02 == Released 0.6.12 ==
-+
-+ 2000/06/02
-+ - Adapted to Snapshot-20000531 (minor patch conflict).
-+ - Cleaned up some old header file dependencies in global/pfixtls.c and
-+ global/Makefile.in that are no longer needed due to the interface changes
-+ (timed_read()/write()) in 0.6.7.
-+
-+ 2000/05/29 == Released 0.6.11 ==
-+
-+ 2000/05/29
-+ - Following Bodo Moeller's analysis, the error is due to a mismatch between
-+ the CA certificate accessible in the smtp[d]_tls_CAfile and the one used
-+ in the actual certificate (smtp[d]_tls_cert_file).
-+ Daniel Miller fixed his setup and the problem is gone.
-+ - Introduced a workaround into Postfix/TLS: if the padding error is found,
-+ it is removed from the error-queue by Postfix/TLS, in order to protect
-+ more sites from experiencing this problem.
-+ - Added a warning to conf/sample-tls.cf
-+ - Updated to the latest snapshot-20000528.
-+
-+ 2000/05/27
-+ - After some fiddling around working through the binary certificate data to
-+ see where it is modified at 0.6.10, I actually note, that both 0.6.9 and
-+ 0.6.10 choke on the data. Now going back up through the functions very
-+ fast reveals the problem:
-+ * The certificate supplied triggers the "RSA-padding" error in any case.
-+ Since the certificate authencity is not enforced on OpenSSL-library level
-+ but inside postfix later, the error is not enforced.
-+ The error messages generated stay however in the error queue.
-+ - For blocking sockets, the SSL_accept()/connect() calls return
-+ "success", so the error-queue is never checked.
-+ - With BIO-pairs, the error queue is checked to find out, whether the
-+ function has just to be called again to continue the handshake, so
-+ the error messages are found and the connection is shut down due to
-+ the error condition.
-+ - Submitted bug report to Bodo Moeller. Bug fix is checked into the OpenSSL
-+ CVS archive: if the error is ignored during the handshake, clear the
-+ error-queue.
-+ * The next release of OpenSSL will behave consistently.
-+ - This leaves open the question, why the RSA-padding error is issued in the
-+ first place. Sent a query to the OpenSSL-* mailing lists.
-+
-+ 2000/05/26
-+ - A second site experiencing this problem pops up.
-+ -> Issued a warning to the postfix_tls mailing list.
-+
-+ 2000/05/24
-+ - Contacted Damien Miller <djm@mindrot.org>. He did not change his TLS setup
-+ in the last time. He is running Postfix/TLS-0.6.6.
-+ - Contacted Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>, the author
-+ of the BIO-pair part of OpenSSL for some debugging hints. Received several
-+ worthful remarks on what to look for.
-+ - Checked byte-for-byte the data fed into the OpenSSL-library. It does not
-+ differ between 0.6.9 and 0.6.10, so my handling seems to be actually
-+ correct.
-+
-+ 2000/05/23
-+ - A communication error occurs when talking to mail.mindrot.org:
-+ SSL_accept error -1
-+ 10264:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:100:
-+ 10264:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:396:
-+ 10264:error:0D079006:asn1 encoding routines:ASN1_verify:bad get asn1 object call:a_verify.c:109:
-+ - The error occurs both in client and server mode. 0.6.9 does not show
-+ this problem.
-+ - Tried to connect with several other sites, all connections are fine,
-+ this includes sendmail and qmail peers; hence decided to not recall 0.6.10.
-+
-+ 2000/05/23 == Released 0.6.10 ==
-+
-+ 2000/05/23
-+ - Sent a note to openssl-dev@openssl.org about the behaviour of SSL_free()
-+ and BIO_free(), hoping for some clarification whether my way of doing
-+ it is the recommended way.
-+ - Run the software in production mode on my own servers...
-+ - Finished writing the in-source documentation.
-+ - Updated sample-tls.cf and sample-smtp[d].cf to reflect the new timeout
-+ parameters.
-+
-+ 2000/05/21
-+ - Removed error messages produced by the now non-blocking behaviour of the
-+ TLS layer [apps_ssl_info_callback()].
-+
-+ 2000/05/20
-+ - Took results home and tried to run it on my Linux-box: SEGV after
-+ successfully handling the SMTP session!!
-+ * It seems that the SSL_free() and BIO_free() functions interact.
-+ SSL_free() releases the underlying BIO and it will bomb out when
-+ it is then explicitely BIO_free()'ed again and vice versa.
-+ * It did not bomb out on HP-UX, but such things happen. I however want to
-+ know, why the example program does not fail...
-+ * With respect to the bevaviour as is, SSL_free(TLScontext->con);
-+ BIO_free(TLScontext->network_bio) and not touching
-+ TLScontext->internal_bio works.
-+ - Introduced special timeout values for the TLS negotiation stage, as the
-+ timeout values may change with protocol state (suggested by Wietse).
-+ - Started writing a full description of the BIO-pair concept and its
-+ special treatment into the pfixtls.c sourcecode.
-+
-+ 2000/05/19
-+ - Systematicly implemented a generalized layer handling:
-+ * do_tls_operation() is the generic handler for all SSL_*() input/output
-+ functions. It deals with the non-blocking behaviour of this functions,
-+ requiring appropriate retrys.
-+ * network_biopair_interop() handles the interaction between the socket/fd
-+ and the buffering BIO-pair.
-+
-+ 2000/05/18
-+ - Based on the example in openssl-0.9.5a/ssl/ssltest.c realized the first
-+ usage of BIO-pairs. (Can do server handshaking.)
-+ - Learned, that the BIO-pair has its own buffering that needs its own
-+ flushing. It is not enough to relay on the SSL_ERROR_WANT_READ/WRITE
-+ state information.
-+
-+ 2000/05/17 == Released 0.6.9 ==
-+ - Important: the seperator in the relay-fingerprints is now ':'!!!
-+ Don't forget to change your relay_clientcerts databases.
-+
-+ 2000/05/16
-+ - Changed pfixtls.c to only use the interface described in util/vstream.c
-+ for handling the VSTREAM.
-+ * Added vstream_context() macro to the VSTREAM-interface.
-+ - Introduce TLScontext to identify the connection instead of the file
-+ descriptor. Move all static data (SSL structure and information gathered
-+ about the connection) into the context.
-+ The TLScontext is allocated on TLS-start for a connection and saved with
-+ the VSTREAM, so several streams can be used at the same time.
-+ - Removed "pfixtls_setfd()" as it is no longer needed.
-+ - Changed the relay_clientcerts list from string_list_* to maps_* interface
-+ to allow usage of ":" in the list.
-+ THIS IS AN INCOMPATIBLE CHANGE!!!!
-+ - Updated documentation accordingly.
-+
-+ 2000/05/12 == Re-released 0.6.8 ==
-+
-+ 2000/05/12
-+ - Wietse announces snapshot-20000511 with an important bugfix.
-+ - Since upgrading from 20000507 to 20000511 is highly recommended,
-+ Postfix/TLS 0.6.8 is re-released for this snapshot (the patch applied
-+ cleanly, just the name of the toplevel directory has changed).
-+
-+ 2000/05/11 == Released 0.6.8 ==
-+
-+ 2000/05/11
-+ - Unlike expected I found some time to install the latest cyrus-sasl-1.5.21
-+ and test some parts the integration. It does, well, work as advertised
-+ (and the advertisement in SASL_README is not too optimistic).
-+ - When checking all of the rejected patch-snippets for 0.6.6->0.6.7
-+ I missed the parameter "smtpd_enforce_tls" (noted since I wanted to
-+ enforce TLS encryption while playing around with plaintext passwords)
-+ in the static CONFIG_BOOL_TABLE bool_table[] = {..} in smtpd/smtpd.c
-+ -> I will immediately release a corrected version 0.6.8.
-+
-+ 2000/05/11 == Released 0.6.7 ==
-+
-+ 2000/05/11
-+ - The latest sendmail.8.11.0.Beta1 includes STARTTLS support; it is available
-+ in source code and also uses OpenSSL.
-+
-+ 2000/05/10
-+ - After having it running at home (Linux) I also install it at work for
-+ the field test.
-+ - No time to install the SASL kit, so this part stays untested as of now.
-+
-+ 2000/05/09
-+ - Downloaded snaphot and apply the patchkit.
-+ - Straightened out the rejected parts of the patch.
-+ - Due to the new layering with timed_read() and timed_write() functions
-+ the integration of the TLS layer needed special adjustment.
-+ * When TLS is active, the timed_read() and timed_write() functions are
-+ replaced by the corresponding pfixtls_timed_read() and
-+ pfixtls_timed_write() functions. When the TLS functionality is stopped,
-+ the old functions are restored.
-+ * The names of the pfixtls_timed_*() functions are looking into the future,
-+ because they are working as before, the timeout functionality is not
-+ in, yet.
-+
-+ 2000/05/08
-+ - Wietse announces snapshot-20000507 with a lot of changes. Especially
-+ important: the I/O handling of the smtp-stream has been changed to
-+ a more layered technique that allows easier integration of the TLS layer.
-+
-+ 2000/04/27 == Released 0.6.6 ==
-+
-+ 2000/04/27
-+ - Fixed inconsistency between documentation and actual behaviour: peer
-+ certificate information was not logged at level 1 (found by
-+ Damien Miller <djm@mindrot.org>).
-+ * While at it: the logged information did not say whether the certificate
-+ data logged passed verification or not: fixed. (The information logged
-+ in the Received: header already contained that information.)
-+ - Backported dict_dbm.c from snapshot-20000309 with the updated
-+ dict_delete() behaviour (key not found is not considered fatal).
-+ Maintained dict_sdbm.c accordingly.
-+
-+ 2000/04/18 == Released 0.6.5 ==
-+ - Important:
-+ * New session cache mechanism SDBM. Please adapt your main.cf and delete
-+ any old ".db" session cache files manually.
-+
-+ 2000/04/18
-+ - I am using the SDBM session cache for a week right now and did not have
-+ any trouble, so I think its worth pushing it out.
-+ - I am not completely happy with the dict_del() behaviour of considering
-+ a not-found key fatal. It might happen when the smtp[d] processes would
-+ be allowed to delete themselves. They are not as of now, so I accept it
-+ for now but will reconsider it.
-+ - Updated documentation accordingly.
-+
-+ 2000/04/17
-+ - Received corrections for the HTML-docs from Ralf Hildebrandt
-+ <R.Hildebrandt@tu-bs.de>.
-+
-+ 2000/04/11
-+ - Transfered SDBM from home (Linux-testbed :-) to work [found and fixed some
-+ small items when compiling on HP-UX]. Started running it under
-+ "real life" conditions.
-+
-+ 2000/04/07
-+ - Implemented "SDBM" Simple Database Management routines as also utilized in
-+ ModSSL. Of course, it requires reopening of the databases, so the
-+ routines are changed, that the _file_descriptors_ are left open, but
-+ the _in_memory_ database stuff (especially the cached data) is closed
-+ and reopened on access. This is what is really needed. The pagesize
-+ is increased from standard DBM compatibility to hold the session
-+ information.
-+ Additionally, this software is in the public domain, so no additional
-+ license problems arise.
-+ - The access goes through the dict_* interface, hence the locking is
-+ performed by myflock().
-+
-+ 2000/04/01 == Released 0.6.4 ==
-+
-+ 2000/04/01
-+ - Updated to the new patchlevel of Postfix (19991231-pl06), some parts of
-+ the patch were rejected due to changes in smtpd.
-+ - Changed patch name with respect of today's release of OpenSSL-0.9.5a.
-+ The code remained unchanged.
-+
-+ 2000/03/25-31
-+ - The cached informations are not deleted by "tlsmgr" even though stored
-+ and retrieved by the smtp[d] processess. Strange.
-+ - Spend some large amount of time digging through the Berkeley DB
-+ documentation and code.
-+ * It claims that Berkeley DB is multi-process capable. Caveat: it takes
-+ the very complicated "transaction model", that I did not use until now.
-+ Hence the session cache does not work as is.
-+ * Even with transaction model, Berkeley DB requires re-opening of the
-+ databases to get rid of cached information. F*ck.
-+ - Finally, I give up on Berkeley DB for session caching. It will never
-+ work for us. Even if it would, it requires a large amount of helper files
-+ and it seems, that the transaction environment is somewhat fragile when it
-+ comes to some problem. I won't rely on it.
-+
-+ 2000/03/28 == Released 0.6.3 ==
-+
-+ 2000/03/28
-+ - As has been pointed out to me, the TLS information in the Received:
-+ header is not conform to RFC822.
-+ - The TLS protocol and peer CN information is now included in '()', so
-+ that it is a comment.
-+
-+ 2000/03/21 == Released 0.6.2 ==
-+
-+ 2000/03/21
-+ - I have been running DB based session caching with the changes for some
-+ more time now without problems. Am I really confident? No, not really.
-+ I remember the trouble I had with Berkeley DB and sendmail on HP-UX.
-+ I don't think I really trust it.
-+ - Realized single "smtp_tls_per_site" lookup. I cannot use the more or
-+ less comfortable "domain_list" lookups as before, since these do not
-+ return the value, just found or not :-(.
-+ Hence the lookup is realized with maps and exact lookup. I never tried
-+ regexp. But if I understand the docs correctly, it should be possible to
-+ use it here to realize wildcard lookups, if it would not have been
-+ disabled :-(.
-+ - Summary:
-+ * Session Cache will be cleaned at "postfix reload" or "postfix start"
-+ * New table "smtp_tls_per_site"
-+ * Gone: "smtp_tls_[use/enforce]_[recipients/sites]"
-+
-+
-+ 2000/03/16
-+ - Changed pfixtls.c, so that it will only open Session Cache databases,
-+ that are already available. tlsmgr is responsible for creation.
-+ - Change tlsmgr.c, such that session cache databases will be removed before
-+ opening, so that fresh databases are used whenever postfix is restarted.
-+ This means, that session information is not kept over a postfix stop/start
-+ or reload sequence, but it also means, that issuing a postfix reload will
-+ clean the session cache.
-+ I don't use simple dict_open with O_TRUNC, because this would not help
-+ against database files, that are locked by hanging smtp[d] processes.
-+ If you think it will also solve the "hang" problem described for
-+ 2000/03/15: in a certain sense it can, since tlsmgr will be killed by
-+ the watchdog and new, fresh cache files are installed, but that is not
-+ more than an ugly hack. It must be solved in a clean manner.
-+
-+ 2000/03/15
-+ - Experienced some strange problem with Berkeley DB based session cache.
-+ The DB routines hang while trying to delete an entry. I did save the
-+ corresponding "hash:" file and could reproduce it (and walk through
-+ the endless loop with a debugger), but I didn't find the reason why.
-+ Since during "db->del" the database is exclusively locked all other
-+ processes hang however, so this is really bad!!!!!!!!
-+
-+ 2000/03/12 == Released 0.6.1 ==
-+
-+ 2000/03/12
-+ - Created tls_info_t structure to hold all information about the active
-+ TLS connection. Remove all global variables except those for the
-+ running client/server engines (those might be replaced with global
-+ variables in smtpd/smtp, though).
-+ - Added field "dNSName" to the structure (still unused). This will be
-+ used with X503v3 extensions.
-+ - Cleaned up TODO, since some items are now done...
-+
-+ 2000/03/11
-+ - Added missing #include <sys/time.h> to tlsmgr.c. (Worked without on HP-UX,
-+ showed up on Linux.)
-+ - Bug: removal of server side sessions from the cache in case of trouble
-+ failed, because uppercase hex was used instead of lowercase for the key.
-+ This does not affect removal of expired sessions by tlsmgr.
-+ - Stepped up to postfix-19991231-pl05.
-+
-+ 2000/03/09 == Released 0.6.0 ==
-+ - Important:
-+ * This release features an additional daemon, the "tlsmgr", please update
-+ your master.cf accordingly.
-+ * This release does not use the /var/spool/postfix/TLS* directories
-+ anymore. Remove them and re-install the original postfix-script.
-+ * Check the new/changed configuration parameters tls_random* and
-+ smtp[d]_tls_session_cache*.
-+ * This release will only work with OpenSSL >= 0.9.5!!!!!
-+
-+ 2000/03/09
-+ - Testcompilation of Postfix/TLS without -DSSL and the OpenSSL includes and
-+ libraries passed.
-+ - Worked through tlsmgr.c to remove unneeded header files.
-+ - Wrote documentation for tlsmgr.c.
-+ - Updated documentation on top of pfixtls.c.
-+ - Put (char *) casts into the myfree() calls, where necessary, to make the
-+ HP compiler happy.
-+ - Updated html PRNG documentation in Postfix/TLS.
-+
-+ 2000/03/08
-+ - Finished first version of "tlsmgr". Does run through session cache
-+ databases and detects and deletes (*) old sessions.
-+ * Had to realize SYNC_UPDATES for the dict_db_delete() function and patch
-+ the flag handling within the function. Changes sent to Wietse.
-+ - Restored qmgr to its original state.
-+ - Extended pfixtls.c to need an additional "needs_095_or_later()" function
-+ when compiled with an older version of postfix.
-+ - The session cache is now enabled, when a database filename is given.
-+ smtp[d]_tls_use_session_cache configuration parameters removed,
-+ updated documenation accordingly.
-+ - Moved the PRNG handling to tlsmgr, applying the new model. tlsmgr will
-+ query external sources at startup and will then feed a PRNG exchange
-+ file with random data in intervals of configurable (but random driven)
-+ length.
-+ If running outside chroot, tlsmgr can query the entropy source (e.g.
-+ EGD or /dev/urandom) again and so increase entropy with time. If the
-+ entropy sources don't limit access, the tlsmgr can run with "postfix"
-+ privileges. Mine does.
-+ -> master.cf became a new entry.
-+ - tlsmgr is realized as a trigger server and has the "fifo" entry. Actually,
-+ it does not take any input. One could utilize it to feed back some entropy
-+ from running smtp[d] processes, but I think this would overload the
-+ issue.
-+ - I will release a 0.6.0 pre-version as is. tlsmgr still lacks the detailed
-+ information in the header and the interface description in pfixtls.c
-+ probably is also not longer up do date.
-+
-+ 2000/03/07
-+ - Since defective session data can cause SEGFAULTs, it is now armored
-+ by a leading structure that does contain a session cache version and
-+ the postfix library version before the timestamp. If a session does
-+ not match exactly the version numbers, it is immediately discarded
-+ and deleted to avoid harm.
-+ - Removed the seperate storage of the peer's certificate verify_result,
-+ so starting from this moment, Postfix/TLS will only work safely with
-+ OpenSSL >= 0.9.5!!!
-+ - Ported server side session cache routines to the client side; works.
-+ - Analyzed structure of "qmgr" to understand consequences for the planned
-+ "tlsmgr" daemon. Transferred the sceleton.
-+ - Received word from sendmail, a (at least preliminary) TLS enabled test
-+ address is "bounce@esmtp.org".
-+
-+ 2000/03/06
-+ - Wietse supplied a change to the dict/dict_db mechanism to allow for
-+ synchronous updates.
-+ Session cache updates for the server side seem to work now, removal of
-+ old sessions (when called from the client) integrated.
-+
-+ 2000/03/05
-+ - Got the database style session cache to run for the server side (at least
-+ partial). The removal of old sessions is not yet realized.
-+ [There are several man pages for OpenSSL as of 0.9.5, but the i2d etc
-+ interfaces are not belong them, so I had to study the source code instead.]
-+ * What is not working by now is the synchronization of the memory database
-+ to disk. It only is synchronized automatically upon close. It would be
-+ necessary to sync after each update or delete, but this is not implemented
-+ in Wietse's dict library. I will post an according proposal.
-+
-+ 2000/03/04
-+ - Wietse posts a patch to select "EHLO" negotiation even if ESMTP is
-+ not recognized from the 220 greeting. Activating this flag will however
-+ break compatibility with mailers, that simply close the connection
-+ upon EHLO. I don't know how the large the number of these broken mailers
-+ is, but activating "smtp_always_send_ehlo" is a tradeoff.
-+ - Integrated Wietse's patch into Postfix/TLS.
-+
-+ 2000/03/03
-+ - Received update from Matti Aarnio (Zmailer) is now for some time able
-+ to do server _and_ client side TLS. Updated documenation accordingly.
-+ When testing, Postfix client to Zmailer server failed, because
-+ Zmailer announces with "ESMTP+IDENT" and Postfix does not recognize
-+ the ESMTP token (must be seperate), so only HELO is used and STARTTLS
-+ is not offered by the Zmailer server. Informed Matti accordingly,
-+ will wait until the problem is resolved before actually publishing
-+ the update.
-+ - Enhanced the documentation by listing automatic reply services at which
-+ interoperability can be tested.
-+
-+ 2000/03/02
-+ - Went through the Postfix source to check out the database routines.
-+ It should be possible to move session caching from directory/file-
-+ based to database. Since DBM only allows blocks (key+contents) of
-+ 1024 bytes and a session is larger, only Berkeley DB can be used.
-+ Put some first bits into Postfix/TLS.
-+
-+ 2000/02/29 == Released 0.5.5 ==
-+
-+ 2000/02/29
-+ - OpenSSL 0.9.5 has been released. Since I want to promote 0.9.5, as it
-+ contains several bugfixes and enhancements, I release a new version
-+ of Postfix/TLS. My personal highlights:
-+ * The bug with Win32 Netscape not commencing after certificate storage
-+ unlocking should be fixed. (I will leave the not in however, as long
-+ as I have not positively checked it myself. Reproducibility...)
-+ * The bug, that the certificate verifiation result is not stored in the
-+ session cache (discovered for Postfix/TLS 0.4.4) is fixed. I will leave
-+ the Postfix/TLS workaround in as long as it will run with older versions
-+ of OpenSSL.
-+ * The OpenSSL commandline tools like "openssl gendh" now support EGD, so
-+ that the examples for generating the DH parameters now will really work
-+ with high quality random data :-)
-+ * The support of 56bit ciphers has lost its importance since 128bit
-+ versions of Netscape etc are now easily available...
-+ - This version does not feature source code changes but updated documenation
-+ when compared with 0.5.4:
-+ * List examples on how to generate good entropy for the PRNG seed in
-+ /etc/postfix/random_file.
-+ - Update the TODO document with respect to the discussion about session
-+ caching and other security items. This document is a very short summary,
-+ for the full discussion check the mail archive at
-+ http://www.aet.tu-cottbus.de/mailman/listinfo/postfix_tls/
-+
-+ 2000/02/26-28
-+ - Wietse considers including Postfix/TLS into the main release. A discussion
-+ about security relevant features, especially the session cache inside
-+ the chroot jail takes place.
-+ The discussion will definetely lead to some changes; I have however not
-+ decided on the first step, yet :-)
-+
-+ 2000/02/21 == RELEASED 0.5.4 ==
-+ - Important: Another directoy is created in /var/spool/postfix, so don't
-+ forget to install the new versions of conf/postfix-script-*sgid.
-+
-+ 2000/02/21
-+ - Finished the seed-exchange architecture by saving the random seed at exit
-+ of smtp and smtpd.
-+ - Wrote documentation for the PRNG handling to the documentation.
-+ - Tested on HP-UX (with a current OpenSSL-pre-0.9.5 snapshot and 0.9.4)
-+ and on SuSE-Linux (with 0.9.4).
-+ * THIS VERSION WILL STILL RUN WITH OPENSSL-0.9.4, but it will also run
-+ with OpenSSL-0.9.5. Older versions of Postfix/TLS will not, because the
-+ PRNG is not seeded!
-+
-+ 2000/02/19
-+ - Start to implement my own model of collecting entropy. All smtp and smtpd
-+ processes will record some items (mainly the time of actions) to add
-+ some entropy into the PRNG. The state is saved and used to re-seed by the
-+ smtp and smtpd processes, so that entropy adds up into the pool.
-+ The seeding by external file is additionally kept in order to be able
-+ to inject additional entropy.
-+
-+ 2000/02/18
-+ - Included routines to add random seed from a configurable file
-+ "rand_file_name". I don't want to retrieve the entropy from a real
-+ random system source, because the amount of entropy that can be collected
-+ is limited. We might hence stall. Let's think about this problem.
-+ - The SSL_CTX_load_verify_locations() has been fixed in the latest
-+ OpenSSL snapshot.
-+
-+ 2000/02/17
-+ - Tracked down the SSL_CTX_load_verify_locations() problem in the OpenSSL
-+ library. If more than one CA-certificate is loaded, a bogus return value 0
-+ is created, because the count of certs is checked to be "1" instead of
-+ allowing ">=1". Reported to openssl-dev.
-+
-+ 2000/02/16
-+ - Downloaded the latest openssl-SNAPSHOT-20000215 and installed it on
-+ my development machine, then recompiled Postfix/TLS and try to run it.
-+ * Failure: SSL_CTX_load_verify_locations() fails on reading the CAfile with
-+ return value 0, but no actual error is displayed.
-+ If the return value is not checked, the CA-certificates work, so that
-+ they are loaded and the error indicator seems to be bogus.
-+ Reported to openssl-dev mailing list.
-+ * Failure: OpenSSL has become picky about correct seeding of the PRNG
-+ Pseudo Random Number Generator. Installed some "testseed" that is
-+ actually not random, but then Postfix/TLS starts to work again. We
-+ will need some good random seed setup, probably reading from either
-+ /dev/random (if available) or from EGD.
-+ Found out during the experiments, that EGD is not that simple to use
-+ as described in some of my Postfix/TLS docs. Must be upgraded.
-+ Asked in the openssl-dev mailing list about the recommended amount
-+ of random data needed for seeding the PRNG. Ulf Moeller recommends
-+ a minimum of 128bit.
-+
-+ 2000/02/14 == Released 0.5.3 ==
-+
-+ 2000/02/14
-+ - OpenSSL 0.9.5 is to be released within the next hours/days. Since I intend
-+ to use some of its new features soon, I will re-release 0.5.2 as the last
-+ version that will run with 0.9.4 but for the latest postfix patchlevel.
-+ - No functional changes.
-+ - Updated patch for postfix-19991231-pl04.
-+
-+ 2000/01/28 == Released 0.5.2 ==
-+
-+ 2000/01/28
-+ - Stepped up the next postfix patchlevel postfix-19991231-pl03.
-+ No functional changes.
-+
-+ 2000/01/03 == Released 0.5.1 ==
-+
-+ 2000/01/03
-+ - Bug fixed: Don't specify a default value for "smtpd_tls_dcert_file",
-+ assuming that typically a DSA certificate is not used.
-+ Otherwise smtpd will try to read it on startup and the TLS engine won't
-+ start since it is not found.
-+ I didn't note this bug before today, because I could not install this
-+ release in a larger scale on my own servers due to a network failure
-+ of our campus backbone lastring from Dec 31 until today.
-+ - Stepped up to the just released postfix-19991231-pl01.
-+
-+ 2000/01/01 == Released 0.5.0 ==
-+
-+ 2000/01/01
-+ - Upgraded to the new postfix release 19991231.
-+
-+ 1999/12/30
-+ - Enabled support for DSA certificate and key for the server side. One
-+ can have both at the same time, the selected cipher decides which one
-+ is used. OpenSSL clients (like Postfix/TLS) will prefer the RSA cipher
-+ suites, if not especially changed in the cipher selection list.
-+ Netscape will only use the RSA cert.
-+ - The client side can only have one certificate. There is a way out by using
-+ a callback function, that will receive the list of acceptable CAs and
-+ then do some clever selection: SSL_CTX_set_client_cert_cb().
-+ I will however have to figure out, how it has to be prepared, it seems,
-+ that there is no example available.
-+ - I have been able to successfully generate a DSA CA and certificates for
-+ some Postfix hosts and to do authentication and relaying as expected.
-+ So now I have to document how it is done in a practical manner...
-+ - Moved up prerelease 0.5.0pre02 to the download site.
-+
-+ 1999/12/28
-+ - Moved up to SNAPSHOT-19991227.
-+ - Don't forget to check the return value when calling
-+ SSL_CTX_set_cipherlist().
-+ - Add code to load DH-parameters from disk.
-+ - Add configuration information for the new functionality: DH paramter
-+ support, possibility to influence the cipherlist.
-+ - Moved up prerelease 0.5.0pre01 to the download site.
-+
-+ 1999/12/25
-+ - Found some minutes to relax from the christmas business.
-+ - Applied the 0.4.7 patch to SNAPSHOT-19991223 and included the new changes
-+ of 1999/12/19.
-+ Once the new stable release of postfix is out, this minimum state will be
-+ the new Postfix/TLS patch: the new functionality will not influence
-+ stability, so it can stay in even if still unfinished.
-+
-+ 1999/12/23
-+ - Wietse announces SNAPSHOT-19991223: if no severe bugs are found, it will
-+ be promoted as next stable release soon. Good to have kept everything
-+ from yesterday.
-+
-+ 1999/12/22
-+ - Got a query from a Postfix/TLS user: the patch does not apply cleanly to
-+ SNAPSHOT-19991216 and he somehow messed up to integrate the rejected
-+ parts (it later turned out he just forgot on reject).
-+ Applied the patch myself and generated a diff, sent it to the user
-+ and of course kept a copy for myself, since I will have to apply it
-+ myself eventually once the next "stable" release of postfix is out.
-+
-+ 1999/12/19
-+ - Began modifications for 0.5.x:
-+ * Added configuration variables for specifying the cipherlist to be used
-+ smtpd_tls_cipherlist and smtp_tls_cipherlist. For the format, there
-+ is some (however sparse) documentation in the openssl package.
-+ * Call SSL_CTX_set_cipherlist() with these data.
-+ * Added default temporary DH parameters to pfixtls.c (only server side is
-+ necessary) and configuration variables to specify user generated
-+ parameters; they are however not used, yet.
-+ The default parameters were generated using the presumably good
-+ /dev/random source.
-+
-+ 1999/12/13 == Released 0.4.7 ==
-+
-+ 1999/12/13
-+ - Addendum to the last change: do also remove sessions, that could _not_
-+ be reused.
-+ - Updated configuration information:
-+ * As of OpenSSL 0.9.4, certificate chain verification is not sufficient,
-+ since the certificate purpose is not checked, so I recommend to add
-+ all intermediate CAs the the list of CAs and stay with a verification
-+ depth of 1.
-+ Work is in progress for 0.9.5.
-+ - Stepped up to the just released new patchlevel postfix-19990906-pl09.
-+
-+ 1999/12/10 == Released 0.4.6 ==
-+
-+ 1999/12/10
-+ - Realized changes implied below: Removed SSL_CTX_add_session() in the
-+ client startup; remove session on stop with SSL_SESSION_free().
-+ - In the morning there is a mail on the list, that Postfix might be
-+ crashed with a single "\" on the "CC:" line. Hence, we should expect
-+ a new patchlevel soon. Release the actual change anyway.
-+
-+ 1999/12/09
-+ - Read in the "openssl-users" mailing list, that SSL_CTX_add_session()
-+ is only intended for servers. On the client side, SSL_set_session()
-+ is sufficient.
-+ Additionally, the session should be explicitely freed, since
-+ SSL_set_session() will increment the usage count for the session.
-+ Explained by Bodo Moeller.
-+
-+ 1999/12/xx
-+ - Had a discussion (by email) with Bodo Moeller about DH/DSS. It seems
-+ I understand better now (after the discussion) how it works :-).
-+ Implementing it should not be too difficult but might take some more
-+ hours. Mentally scheduled it for Version "0.5.0" whenever this might
-+ be (rough guess: christmas vacation).
-+ Decided to hence not discuss this topic in the docs, since it might
-+ change in the near future anyway.
-+
-+ 1999/11/23
-+ - Discussion with rch@writeme.com (Richard) about implementing DH ciphers
-+ and DSA keys and certificates on the Postfix/TLS list: It does not work
-+ as of now.
-+
-+ 1999/11/15 == Released 0.4.5 ==
-+
-+ 1999/11/15
-+ - Applied patch to postfix-19990906-pl07 without problems. Well, let's
-+ release new version of Postfix/TLS, so that we look up to date.
-+ - Add the "DO NOT EDIT THIS FILE" to conf/sample-tls.cf.
-+
-+ 1999/11/08
-+ - Applied patch to the fresh release of postfix-19990906-pl06 without
-+ problems. Nothing else, so no new release of Postfix/TLS.
-+
-+ 1999/11/07 == Released 0.4.4 ==
-+
-+ 1999/11/07
-+ - Played around some more with the X509_verify_cert() function: when saving
-+ a session, neither the verify_result is saved nor the certificate chain
-+ necessary to re-verify. So there were two possibilities left: do a full
-+ renegotiation negating the benefit of session caching or
-+ - save the verify_result into to the session cache file and set the value
-+ when rereading from disk. This way the positive result of session caching
-+ is kept.
-+ - Make sure, the verify_result value is propagated as pfixtls_peer_verified
-+ and used where needed.
-+ - After experiencing some failures at TLS connection setup, the SSL_sessions
-+ are now freed again when closing. It seems, something is left over in the
-+ session structures, even though SSL_clear() is called.
-+
-+ 1999/11/06
-+ - When not asking for a client certificate, the "Received:" header will show
-+ the protocol and cipher, but silently omit the client CN (because they
-+ where not supplied). Noted by Craig Sanders <craig@taz.net.au>.
-+ The same holds, if a certificate is asked for, but none supplied.
-+ Now, in any case an appropriate information is added in the "Received:"
-+ header.
-+ - Added a hint to remove sessions from the cache during testing, since
-+ old information may still be in the cache. Also proposed by Craig
-+ Sanders <craig@taz.net.au>.
-+ - While at it: client CN and issuer CN are printed, but the verification
-+ state is not, so that the trust value of this data is not known.
-+ * Added (verify OK/not verified) to the Received: header.
-+ * Obtained information using the SSL_get_verify_result(SSL *con) call.
-+ * Learned, that the state is not saved in the session information, so
-+ that a recalled old session will always return "OK" even if the
-+ certificate failed the verification! Call it a bug in OpenSSL.
-+ Still investigating on a good way to work around this problem.
-+ - Fixed a bug in the syslog entries: The client CN is logged, but the
-+ issuer CN is not, because of a missing "%s" in the format string.
-+
-+ 1999/11/03 == Released 0.4.3 ==
-+
-+ 1999/11/03
-+ - Added some hints about security to the html documentation.
-+ - Tested the changes made two weeks ago at home in the large university
-+ setup. I was to a conference in between and didn't want to release
-+ the new version without having done some more tests.
-+
-+ 1999/10/17
-+ - Added another half a ton of comments (this time for the client side),
-+ yielding one ton alltogether...
-+
-+ 1999/10/16
-+ - Rearranged some of the TLS-engine initialization to improve readability.
-+ - Do not "free" the SSL connection, when it is not really necessary. Do only
-+ reset information about the TLS connection, when there was one. This is
-+ the better way instead of the quick fix applied for 0.4.2.
-+ - Added half a ton of comments to the TLS code (server side) to document
-+ what is done when and why, since there is no real documentation about
-+ the OpenSSL library.
-+
-+ 1999/10/11 == Released 0.4.2 ==
-+
-+ 1999/10/11
-+ - Fixed a severe bug introduced in 0.4.0: smtpd and smtp tried to flush
-+ old session from the session cache even when TLS was not enabled. Since
-+ no SSL-context was allocated, smtp would segfault on connection close.
-+
-+ 1999/10/10 == Released 0.4.1 ==
-+
-+ 1999/10/10
-+ - Added a long description of the session cache handling to the top of
-+ global/pfixtls.c.
-+ - There is a race condition when cleaning up the session cache in qmgr, that
-+ might lead to lost sessions in client mode. The worst consequence is an
-+ additional session negotiation, so we can live with it as of now.
-+ Bug described in qmgr/qmgr_tls.c.
-+ - Implemented immediate removal of session cache files with expired sessions
-+ when these are called. No need to first load and then discard them.
-+ - Implemented the requirement from RFC2246 to remove sessions, when
-+ connection failures occure (well actually, when TLS layer failures
-+ occur, but I cannot seperate this from another) for the server side.
-+ the client side is under work.
-+
-+ 1999/10/09
-+ - Set an absolut maximum length of 32 for the IDs used for session caching.
-+ This matches the default in OpenSSL, but I don´t want to see surprises
-+ when somebody sometimes will run into a longer session id.
-+
-+ 1999/10/05 == Released 0.4.0 ==
-+ - The new disk based session cache is a major step, so the minor release
-+ number is pushed to 0.4.
-+ - By now I think all necessary bells and whistles are in the code. What
-+ is left is a big code cleanup and some more testing before calling this
-+ patchkit "1.0.0".
-+ - Initiated Mailing List at
-+ http://www.aet.tu-cottbus.de/mailman/listinfo/postfix_tls
-+
-+ 1999/10/05
-+ - Some code cleanup.
-+ - Added new options to the documentation and the hint to update
-+ "postfix-script", because otherwise qmgr might fail!
-+
-+ 1999/10/03
-+ - Realized disc based session caching also for the Postfix/TLS client.
-+ Must go to real world testing now between hosts.
-+ And, of course, tune up the documentation, because users will have to
-+ install a new postfix-script, too.
-+
-+ 1999/10/02
-+ - The old sessions must be removed once they have timed out, so a process
-+ is needed that will scan through the list of old sessions and remove
-+ once they have expired.
-+ Lucky me: this is what qmgr usually does with deferred messages, so
-+ qmgr is extended only a little bit and will now also clean up the
-+ old sessions from the cache directory.
-+ And hey: it is good to see how easily this thing can be extended and
-+ functions can easily be reused. Postfix is an excellent peace of
-+ software engineering and there is no line of C++ or other "object
-+ oriented modern junk" in it. It should be recommended as an example
-+ to computer sience students.
-+
-+ 1999/09/28
-+ - I cannot use the mod_ssl way for session caching and I don´t want to
-+ spend an extra "gcache" daemon as ApacheSSL does. So I follow Wietse´s
-+ idea realized for his mail queues and create hash level based subdirectory
-+ structures. The good thing: I can cannibalize the mail_queue code.
-+ The bad thing: there is a path length of 100 chars fix coded in Wietse´s
-+ routines. It does hold for 32byte session ideas.
-+ Status: can save sessions to disk and recall them (server side).
-+
-+ 1999/09/26
-+ - Created new call backs for external session caching for the server side.
-+ In a first step, they can print out the session ids for the newly created
-+ session and when recalling a session.
-+ As the OpenSSL documentation on this is pretty sparse, Ben Laurie´s
-+ ApacheSSL code is very helpful, Ralph Engelschall´s Mod_SSL code for
-+ session caching is far more complicated.
-+
-+ 1999/09/23 == Released 0.3.10 ==
-+
-+ 1999/09/23
-+ - Debugging for 0.3.8/0.3.9 would have been so much easier, if the error
-+ messages put onto the error message stack from the OpenSSL library would
-+ have been printed out. The error was clearly stated from the library, I
-+ just didn't print it. Added pfixtls_print_errors() calls where missing
-+ after calls to the OpenSSL library.
-+ Sometimes I feel so old...
-+ - Used opportunity to upgrade to the latest postfix patchlevel 05:
-+ postfix-19990906-pl05.
-+
-+ 1999/09/19 == Released 0.3.9 ==
-+
-+ 1999/09/19
-+ - Added a "smtp_no_tls_sites" table to allow people to enable TLS negotiation
-+ globally and only omit it on a per site basis.
-+
-+ 1999/09/18
-+ - Finally found the bug described for 0.3.8: In the server setup, the
-+ SSL_CTX_set_session_id_context() call was missing. To find this, I
-+ had to trace through the OpenSSL library and when I finally found it
-+ in ssl/ssl_sess.c, there was an appropriate comment about this. I however
-+ have to find out why I didn´t receive the appropriate error message...
-+ - This bug was hidden during the first developing stages, as the shutdown
-+ sequence was not working correct, so the session was not cached.
-+
-+ 1999/09/17 == Released 0.3.8 ==
-+
-+ 1999/09/17
-+ - Something is strange with the session caching in smtpd server mode
-+ with Netscape 4.61 client. The first connection is fine, the next
-+ one hangs after the server fails with errors while reading the
-+ SSLv3 client hello C. (Found by Michael Stroeder <x_mst@propack-data.de>)
-+ Reproducable with OpenSSL 0.9.3a, 0.9.4 and SNAPSHOT 19990915, so
-+ the problem seems to be persistent. I will try to figure out the
-+ problem myself before reporting it to the developers. If I don't find
-+ it, maybe they do :-)
-+ Workaround: the cached session is removed after connection is closed.
-+ This will impose some time penalty on the negotiation. As the caching
-+ is local in the smtp processes and they time out anyway, the penalty
-+ should not be significant.
-+ The problem does not occure with Postfix/TLS clients.
-+
-+ 1999/09/13 == Released 0.3.7 ==
-+
-+ 1999/09/13
-+ - Ran tests, seems no further conflicts between Wietse's changes and my
-+ extensions.
-+
-+ 1999/09/09
-+ - Applied the patchkit 0.3.6 to postfix-19990906-pl02 and worked out
-+ the rejected part of the patch. From this point of view the patch
-+ is included. Now everything has to be retested.
-+
-+ 1999/09/09 == Released 0.3.6 ==
-+
-+ 1999/09/09
-+ - Added a missing ´#ifdef HAS_SSL #endif´ in smtp_connect.c.
-+ Noted by Jeff Johnson <jeff@websitefactory.net>.
-+ - HINT:
-+ On 1999/09/06 a new "stable" version of postfix was released.
-+ Future Postfix/TLS enhancements will be against this new version 19990906.
-+
-+ 1999/08/25 == Released 0.3.5 ==
-+
-+ 1999/08/25
-+ - Added Wietse's patch for postfix-19990601 to prevent crashing smtpd when
-+ VRFY is called without setting the sender with "MAIL FROM:" first.
-+
-+ 1999/08/13
-+ - Small changes to global/pfixtls.[ch]: Since we also support client STARTLS,
-+ we check the peers certificate, which may also be a "server" certificate
-+ (not just client). Hence I renamed "*ccert*" to "*peer*".
-+ - global/pfixtls.c: add some "const" to "char *" for OpenSSL library calls,
-+ to make gcc happy.
-+ - Extended comments in pfixtls.[ch] to better match Wietse's style.
-+
-+ 1999/08/12 == Released 0.3.4 ==
-+
-+ 1999/08/12
-+ - Enabled workarounds for known bugs in SSL-engines.
-+ - Tested with OpenSSL 0.9.4.
-+ - Windows95/NT: Problem with Netscape hanging on first connection when
-+ the client certificate database has to be unlocked cannot be reproduced
-+ anymore.
-+ I am happy, but I am also not sure what caused the problem to go away
-+ and I cannot figure out the security settings manually from the files...
-+
-+ 1999/08/11
-+ - Corrected loglevel handling: At some points smtpd_tls_loglevel was used
-+ instead of smtp_tls_loglevel (only noted at loglevels >= 2).
-+
-+ 1999/08/09 == Released 0.3.3 ==
-+
-+ 1999/08/09
-+ - Removed SSL_CTX_set_quiet_shutdown() as it does prevent the shutdown
-+ from actually being performed. In order to remove the annoying
-+ "SSL3 alert write:warning:close notify" it is now explicitly handled
-+ in apps_ssl_info_callback().
-+ Bug found by Bodo Moeller <bodo@openssl.org>.
-+
-+ 1999/08/06 == Released 0.3.2 ==
-+
-+ 1999/08/06
-+ - Add option "smtp_tls_note_starttls_offer" to collect information about
-+ hosts, that offered the STARTTLS feature without using it.
-+ - Shut up smtpd. Only print information about relaying based on certs
-+ when msg_verbose is true.
-+
-+ 1999/07/20
-+ - Added missing "const" in pfixtls.h (found by Juergen Scheiderer
-+ <jnschei@suse.de>). HP-UX ANSI-C didn't complain.
-+
-+ 1999/07/08 == Released 0.3.1 ==
-+
-+ 1999/07/08
-+ - New config variable "smtpd_tls_received_header". When "true", the protocol
-+ and cipher data as well as subject and issuer CN of the client certificate
-+ are included into the "Received:" header.
-+
-+ 1999/07/07
-+ - "starting TLS engine" message will only be printed when loglevel >=2
-+ to reduce unnecessary noise in the log files.
-+ - Added code to fetch the protocol (e.g. TLSv1) and the cipher used (by name
-+ and bits). Information is printed to the logfile.
-+
-+ 1999/07/01 == Released 0.3.0 ==
-+
-+ 1999/07/01
-+ - (Client mode) Bug fix: Don't try to use STARTTLS if it is not offered. The
-+ server we are connected to might not understand it and respond with a
-+ "500 command not understood", causing the email to bounce back, even
-+ when the lack of STARTTLS is just a temporary problem.
-+ - Updated documentation for the new per recipient/site TLS decisions.
-+
-+ 1999/06/30
-+ - Client mode: Added variables and routines to decide "per recipient" or
-+ "per host/site" whether to use/enforce TLS or not.
-+
-+ 1999/06/18 == Released 0.2.8 ==
-+
-+ 1999/06/18
-+ - In client mode the "use_tls" and "enforce_tls" internal variables were
-+ not initialized correctly, such that the client could try to use the
-+ STARTTLS negotiation even if not wanted. This error was introduced
-+ in 0.2.7.
-+ Noted by "Cerebus" <cerebus@sackheads.org>.
-+
-+ 1999/06/08 == Released 0.2.7 ==
-+
-+ 1999/06/08
-+ - Studied discussions in the IETF-apps-TLS mailing list: MS Exchange
-+ seems to offer STARTTLS even if not configured. Added this info to the
-+ documentation.
-+ - Updated Documentation regarding the changes made.
-+
-+ 1999/06/03
-+ - The subject-CommonName (CN) of the server certificate is extracted when
-+ connecting to a TLS server.
-+ - In "smtp_*_tls" mode, this subject-CommonName is matched against the
-+ hostname of the server. In "enforce" mode, the connection is droppend
-+ when the certified server name and the real hostname differ.
-+ - Added missing dependencies in smtp/Makefile.in (missing pfixtls.h since
-+ 0.2.0).
-+
-+ 1999/06/02 == Released 0.2.6 ==
-+
-+ 1999/06/02
-+ - Adapted patchkit to postfix-19990601.
-+
-+ 1999/06/01 == Released 0.2.5 ==
-+
-+ 1999/06/01
-+ - Updated OpenSSL API to 0.9.3a -> position of include files has changed
-+ from <xxx.h> to <openssl/xxx.h>. No functional changes.
-+ - pkcs12 utility is now part of OpenSSL -> changed documentation
-+ accordingly.
-+
-+ 1999/05/20 == Released 0.2.4 ==
-+
-+ 1999/05/20
-+ - Updated postfix base 19990317 from pl04 to pl05.
-+
-+ 1999/05/14 == Released 0.2.3 ==
-+
-+ 1999/05/14
-+ - Fixed a bug in pfixtls_stop_*(): there was a ";" to much directly
-+ after "if (con);". This check is only done as a safety measure:
-+ When SSL is not started you should not stop it. This case could however
-+ only happen when the code in smtp[d] would be wrong, so it should never
-+ be necessary. (Bug found by Uwe Ohse <uwe@ohse.de>)
-+
-+ 1999/05/11 == Released 0.2.2 ==
-+
-+ 1999/05/11
-+ - Matti Aarnio: Reworked pfixtls_dump() to use fewer strcpy and strcat calls.
-+ - Added information about Matti Aarnio (author/maintainer of ZMailer)
-+ working on RFC2487 for ZMailer.
-+
-+ 1999/05/04 == Released 0.2.1 ==
-+
-+ 1999/05/04
-+ - Stuffed up the documenation to reflect the actual status. No change
-+ in functionality.
-+
-+ 1999/04/30 == Released 0.2.0 ==
-+
-+ 1999/04/30
-+ - Adjusted the changes in smtp*.c to Wietse's indentation style.
-+ - Sorry, the documentation about the client side has by now to be
-+ taken from sample-tls.conf. The documenation has to be rearranged
-+ in a larger scale.
-+
-+ 1999/04/29
-+ - Finished client support for STARTTLS in smtp; some testing done.
-+ - Fixed a race condition in smtpd: When in PIPELINE mode, the connection
-+ was switched back from SSL to normal mode before the buffers were
-+ flashed.
-+ - Adjusted the code in pfixtls.[ch] and additions in smtpd*.c to
-+ Wietse's indentation style.
-+
-+ 1999/04/28
-+ - Incorporated skeleton of STARTTLS support into smtp.
-+ - Introduced variables to control client STARTTLS to configuration.
-+
-+ 1999/04/15 == Released 0.1.5 ==
-+
-+ 1999/04/15
-+ - Adjusted pfixtls.diff to postfix-19990317-pl04.
-+
-+ 1999/04/14
-+ - Ported from OpenSSL the BIO_callback functions to dump out the negotiation
-+ and transmission for debugging purposes. The functions are triggered
-+ by the the new loglevels 3 and 4.
-+ - Call SSL_free() to get rid of the SSL connection structure not used
-+ anymore.
-+
-+ 1999/04/13 == Released 0.1.4 ==
-+
-+ 1999/04/13
-+ - Based on a hint in the openssl-users list added an SSL_set_accept_state()
-+ before the actual SSL_accept(). I don't really understand why, but the
-+ documentation of SSL is a bit short anyway.
-+
-+ 1999/04/11
-+ - Some more comments on certificates in the documentation.
-+
-+ 1999/04/10
-+ - Moved initialization of the pfixtls_server_engine to the pre_jail_init()
-+ section of smtpd, so that it is called with root privileges to read the
-+ key and cert information. The secret key of the server can now be protected
-+ by "chown root secretkey.pem; chmod 400 secretkey.pem".
-+ Additionally, this makes it possible to run smtpd in chroot jail, even
-+ though I didn't test that, yet. All information is read at smtpd startup
-+ time except the CAcerts in tls_CApath, which are checked at runtime.
-+ I have to look into that.
-+ - Updated documentation accordingly.
-+ - Rewrote the documentation with regard to the certificate setup and
-+ explaining the different types of certificates.
-+
-+ 1999/04/09
-+ - Introduced pfixtls_print_errors() which imitates BIO_print_errors()
-+ (the typical way to print error information in OpenSSL) but writes
-+ to syslog instead of a file handle.
-+ Hence we can get more informative error information.
-+
-+ 1999/04/08 == Released 0.1.3 ==
-+
-+ 1999/04/08
-+ - Stuffed up the documentation by reworking the references.
-+ - Added contributed script for automatic addition of fingerprints.
-+ - Added ACKNOWLEDGEMENTS file
-+
-+ 1999/04/06 == Released 0.1.2 ==
-+
-+ 1999/04/06
-+ - Portability: removed call of "snprintf()", as it is not available on
-+ some (older) UNIX versions (in this case Solaris 2.5).
-+ - Removed calls to "select()" when in TLS mode: Even though no new bytes
-+ arrive, there might be bytes left in the SSL buffer -> possible hang.
-+
-+ 1999/03/30 == Released 0.1.1 ==
-+
-+ 1999/03/30
-+ - Added disclaimer about export restrictions.
-+ - Fixed a bug in util/match_ops.c:
-+ When using dictionary lookup the compare was case sensitive by accident.
-+ Effect: Fingerprint matching did not work with databases, only for plain
-+ file.
-+ Bug report submitted to postfix author.
-+
-+ 1999/03/29 == Released first version 0.1.0 ==
-diff -Pcr postfix-2.0.16/pfixtls/INSTALL postfix-2.0.16-ti1.20/pfixtls/INSTALL
-*** postfix-2.0.16/pfixtls/INSTALL Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/INSTALL Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,2 ----
-+ For installation instructions please read the HTML documentation in the
-+ "doc/" subdirectory.
-diff -Pcr postfix-2.0.16/pfixtls/README postfix-2.0.16-ti1.20/pfixtls/README
-*** postfix-2.0.16/pfixtls/README Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/README Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,42 ----
-+ Overview:
-+ =========
-+
-+ - This is an SSL/TLS enhancement package for postfix.
-+ It realizes (well, or at least should, once it is finished) the
-+ STARTTLS extension to SMTP as described in RFC2487 and used
-+ by Netscape 4.5x.
-+ - For instructions on how to install the kit, please read the installation
-+ section in the "html" manual in the "doc/" subdirectory.
-+
-+ License:
-+ ========
-+ - This software is free. You can do with it whatever you want.
-+ I would however kindly ask you to acknowledge the use of this
-+ package, if you are going use it in your software, which you might
-+ be going to distribute. I would also like to receive a note if you
-+ are a satisfied user :-)
-+
-+ Acknowledgements:
-+ =================
-+ - This package is based on the OpenSSL package as provided by the
-+ ``OpenSSL Project''.
-+
-+ Disclaimer:
-+ ===========
-+ - This software is provided ``as is''. You are using it at your own risk.
-+ I will take no liability in any case.
-+ - This software package uses strong cryptography, so even if it is created,
-+ maintained and distributed from liberal countries in Europe (where it is
-+ legal to do this), it falls under certain export/import and/or use
-+ restrictions in some other parts of the world.
-+ - PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG
-+ CRYPTOGRAPHY SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST
-+ COMMUNICATING TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS
-+ ILLEGAL IN SOME PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE
-+ TO YOUR COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL
-+ TECHNICAL SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR
-+ OTHER PEOPLE YOU ARE STRONGLY ADVICED TO PAY CLOSE ATTENTION TO ANY
-+ EXPORT/IMPORT AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHOR OF
-+ PFIXTLS IS NOT LIABLE FOR ANY VIOLATIONS YOU MAKE HERE. SO BE
-+ CAREFULLY YOURSELF, IT IS YOUR RESPONSIBILITY.
-+
-diff -Pcr postfix-2.0.16/pfixtls/TODO postfix-2.0.16-ti1.20/pfixtls/TODO
-*** postfix-2.0.16/pfixtls/TODO Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/TODO Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,36 ----
-+ This list does not really follow priority.
-+
-+ * Implement support of CRL checking. OpenSSL 0.9.7 finally supports CRLs,
-+ so Postfix/TLS should support loading CRLs.
-+
-+ * Cleanup the "pfixtls" special logging, so that it fits Wietses original
-+ "per site" decision to make debugging easier.
-+
-+ * Move TLS based information from separate lines into Postfix's smtpd
-+ logging lines to make logfile analysis easier.
-+
-+ * Check the "info_callback" for sensitive use. I already had to remove the
-+ "warning alert" issued on normal shutdown. Why is a warning issued for
-+ a normal shutdown??
-+
-+ * Allow to specify the protocol used globally: SSLv2, SSLv3, TLSv1.
-+
-+ * Enhance tls_per_site feature, such that not only MAY, MUST, NONE flags
-+ are supported. It should also be possible to influence the behaviour:
-+ choose the SSLv2/SSLv3/TLSv1 protocols.
-+ [A compatible way to upgrad the tls_per_site table would be to add the
-+ keywords:
-+ MUST,SSLv2
-+ MAY,NO_TLSv1
-+ ]
-+
-+ * Introduce new tls_per_client table to achieve the same selective behaviour
-+ for incoming connections.
-+
-+ * Introduce better support for "opportunistic" encryption: collect information
-+ about peers connecting; log warnings when the key changed etc.
-+ [I am not sure that I already have the best answers available.]
-+
-+ * Find a way to use the certificates themselves instead of the fingerprints
-+ to allow certificate based relaying. The maintenance of the fingerprints
-+ is a nightmare.
-diff -Pcr postfix-2.0.16/pfixtls/contributed/00README postfix-2.0.16-ti1.20/pfixtls/contributed/00README
-*** postfix-2.0.16/pfixtls/contributed/00README Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/contributed/00README Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,22 ----
-+ All entries in this directory have been contributed from other sources:
-+
-+ - Frederic J. Hirsch <f.hirsch@opengroup.org>
-+ * loadcacert.pl:
-+ I "took" this one from his excellent introduction
-+ "Introducing SSL and Certificates using SSLeay"
-+ http://www.camb.opengroup.org/RI/www/prism/wwwj/index.html
-+
-+ - Walcir Fontanini <walcir@densis.fee.unicamp.br>
-+ * fp.csh:
-+ add fingerprints to the list of client certs;
-+ be carefull to a adjust filenames and maptype as necessary
-+
-+ - Craig Sanders <cas@taz.net.au>
-+ * make-postfix-cert.sh:
-+ automatically create certificates for postfix usage.
-+
-+ - Justin Davies <justin@palmcoder.net>
-+ * SSL_CA-HOWTO.pdf/sgml
-+ SSL CA howto
-+ * Postfix_SSL-HOWTO.pdf/sgml
-+ Postfix/TLS howto
-diff -Pcr postfix-2.0.16/pfixtls/contributed/fp.csh postfix-2.0.16-ti1.20/pfixtls/contributed/fp.csh
-*** postfix-2.0.16/pfixtls/contributed/fp.csh Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/contributed/fp.csh Mon Jan 5 16:58:04 2004
-***************
-*** 0 ****
---- 1,20 ----
-+ #!/bin/csh -f
-+
-+ ## fp.csh <username>
-+ # Generate a fingerprint from a X509 certificate
-+ # and updates /etc/postfix/relay_clientcerts
-+ # It presumes a user certificate in /etc/postfix/certs/
-+ # with name <username>-cert.pem
-+ # author: walcir fontanini (walcir@densis.fee.unicamp.br) Apr-08-1999
-+
-+ set USER=$1
-+ set FP=`/usr/local/ssl/bin/openssl x509 -fingerprint -in /etc/postfix/certs/$USER-cert.pem | grep Fingerprint | awk -F= '{print $2}' | tr ":" "_"`
-+
-+ cat >> /etc/postfix/relay_clientcerts <<EOT
-+ $FP $USER
-+ EOT
-+
-+ postmap dbm:/etc/postfix/relay_clientcerts
-+
-+ exit
-+ #
-diff -Pcr postfix-2.0.16/pfixtls/contributed/loadCAcert.pl postfix-2.0.16-ti1.20/pfixtls/contributed/loadCAcert.pl
-*** postfix-2.0.16/pfixtls/contributed/loadCAcert.pl Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/contributed/loadCAcert.pl Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,23 ----
-+ #!/usr/local/bin/perl -T
-+
-+ require 5.003;
-+ use strict;
-+ use CGI;
-+
-+ my $cert_dir = "/usr/local/ssl/certs";
-+ my $cert_file = "CAcert.pem";
-+
-+ my $query = new CGI;
-+
-+ my $kind = $query->param('FORMAT');
-+ if($kind eq 'DER') { $cert_file = "CAcert.der"; }
-+
-+ my $cert_path = "$cert_dir/$cert_file";
-+
-+ open(CERT, "<$cert_path");
-+ my $data = join '', <CERT>;
-+ close(CERT);
-+ print "Content-Type: application/x-x509-ca-cert\n";
-+ print "Content-Length: ", length($data), "\n\n$data";
-+
-+ 1;
-diff -Pcr postfix-2.0.16/pfixtls/contributed/make-postfix-cert.sh postfix-2.0.16-ti1.20/pfixtls/contributed/make-postfix-cert.sh
-*** postfix-2.0.16/pfixtls/contributed/make-postfix-cert.sh Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/contributed/make-postfix-cert.sh Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,78 ----
-+ #! /bin/sh
-+
-+ # make-postfix-cert.sh
-+ # by Craig Sanders <cas@taz.net.au> 2000-09-02
-+ # this script is hereby placed in the public domain.
-+
-+ # this script assumes that you already have a CA set up, as the openssl
-+ # default "demoCA" under the current directory. if you haven't done it
-+ # already, run "/usr/lib/ssl/misc/CA.pl -newca" (or where the path to
-+ # openssl's CA.pl script is on your system).
-+ #
-+ # then run this script like so:
-+ #
-+ # ./make-postfix-cert.sh hostname.your.domain.com
-+ #
-+ # it will create the certificate and key files for that host and put
-+ # them into a subdirectory.
-+
-+ site="$1"
-+
-+ # edit these values to suit your site.
-+
-+ COUNTRY="??" # ISO country code
-+ PROVINCE="YOUR STATE OR PROVINCE"
-+ LOCALITY="YOUR CITY"
-+ ORGANISATION="YOUR ORG NAME"
-+ ORG_UNIT=""
-+ COMMON_NAME=$site
-+ EMAIL="someone@your.domain.com"
-+
-+ OPTIONAL_COMPANY_NAME=""
-+
-+ # leave challenge password blank
-+ CHALLENGE_PASSWORD=""
-+
-+ # generate a certificate valid for 10 years
-+ # (probably not a good idea if you care about authentication, but should
-+ # be fine if you only care about encryption of the smtp session)
-+ DAYS="-days 1825"
-+
-+ # alternatively, make one valid for one year
-+ #DAYS="-days 365"
-+
-+ # create the certificate request
-+ cat <<__EOF__ | openssl req -new -nodes -keyout newreq.pem -out newreq.pem $DAYS
-+ $COUNTRY
-+ $PROVINCE
-+ $LOCALITY
-+ $ORGANISATION
-+ $ORG_UNIT
-+ $COMMON_NAME
-+ $EMAIL
-+ $CHALLENGE_PASSWORD
-+ $OPTIONAL_COMPANY_NAME
-+ __EOF__
-+
-+ # sign it
-+ openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
-+
-+ # move it
-+ mkdir -p $site
-+ mv newreq.pem $site/key.pem
-+ chmod 400 $site/key.pem
-+ mv newcert.pem $site/cert.pem
-+ cd $site
-+
-+ # create server.pem for smtpd
-+ cat cert.pem ../demoCA/cacert.pem key.pem >server.pem
-+ chmod 400 server.pem
-+
-+ # create fingerprint file
-+ openssl x509 -fingerprint -in cert.pem -noout > fingerprint
-+
-+ # create pkcs12 certificate for netscape (probably not needed)
-+ #openssl pkcs12 -export -in cert.pem -inkey key.pem \
-+ # -certfile ../demoCA/cacert.pem -name "$site" -out cert.p12
-+
-+ cd ..
-diff -Pcr postfix-2.0.16/pfixtls/doc/conf.html postfix-2.0.16-ti1.20/pfixtls/doc/conf.html
-*** postfix-2.0.16/pfixtls/doc/conf.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/conf.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,604 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Configuring main.cf and master.cf</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Configuring main.cf and master.cf</h1>
-+
-+ To use the TLS extension you need to feed some information to
-+ postfix. Please see also the <code>conf/sample-tls.cf</code> file.
-+
-+ <h2>main.cf: smtpd (server) specific variables</h2>
-+
-+ <pre>
-+ # 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
-+
-+ # 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
-+ </pre>
-+
-+ <h2>main.cf: smtp (client) specific variables</h2>
-+
-+ <pre>
-+ # 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). Checks are performed against
-+ # all names provided as dNSNames in the SubjectAlternativeName. If no
-+ # dNSNames are specified, the CommonName is checked.
-+ # 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
-+ </pre>
-+
-+ <h2>SASL related variables</h2>
-+
-+ <pre>
-+ # The smtpd_sasl_tls_security_options parameter controls what authentication
-+ # mechanism the Postfix SMTP server will offer to the client, in case the
-+ # connection is protected by a TLS encrypted session.
-+ # This parameter allows to provide for example plaintext authentication that
-+ # otherwise would not be allowed without encryption.
-+ # The default is to use the same settings as in the unencrypted case.
-+ #
-+ # Warning: this option only works against passive (eavesdropping) attackes.
-+ # An active attacker (man in the middle) may modify the AUTH options offered
-+ # and/or remove the STARTTLS offer from the EHLO response. Protection against
-+ # active attackers is only possible by enforcing TLS at the client side.
-+ #
-+ #smtpd_sasl_tls_security_options = noanonymous
-+ smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
-+
-+ # 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, if 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 = yes
-+ smtpd_tls_auth_only = no
-+
-+ # The smtp_sasl_tls_security_options parameter controls, what authentication
-+ # mechanisms the local Postfix SMTP client is allowed to use, if the session
-+ # is encrypted via TLS. This provides the option to permit plaintext passwords
-+ # that otherwise could not be used.
-+ #
-+ # The settings allowed are the same as for the non-encrypted sessions
-+ # (smtp_sasl_security_options).
-+ #
-+ # Warning, Warning, Warning: This option only works against passive
-+ # (eavesdropping) attacks. An active attacker (man in the middle) may provide
-+ # a TLS capabable server (proxy) and in such way obtain the password
-+ # information. The only way to prevent a man in the middle attack is to check
-+ # the hostname of the server presented in the certificate. This is assured
-+ # in the (preferrably used) smtp_sasl_tls_verified_security_options case.
-+ #
-+ #smtp_sasl_tls_security_options =
-+ smtp_sasl_tls_security_options = $smtp_sasl_security_options
-+
-+ # The smtp_sasl_tls_verified_security_options parameter controls, what
-+ # authentication mechanisms the local Postfix SMTP client is allowed to use,
-+ # if the session is encrypted via TLS _and_ the server has proven its
-+ # identity (expected hostname matches certificate, verification successfull).
-+ # This provides the option to permit plaintext passwords that otherwise could
-+ # not be used.
-+ #
-+ # The settings allowed are the same as for the non-encrypted sessions
-+ # (smtp_sasl_security_options).
-+ #
-+ #smtp_sasl_tls_verified_security_options =
-+ smtp_sasl_tls_verified_security_options = $smtp_sasl_tls_security_options
-+ </pre>
-+
-+ <h2>main.cf: general variables</h2>
-+
-+ <pre>
-+ # 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
-+ </pre>
-+
-+ <h2>master.cf: tlsmgr daemon</h2>
-+
-+ If you don't have a /dev/urandom device and/or use session caching,
-+ you must run the "tlsmgr" daemon (see conf/master.cf). The tlsmgr
-+ will contact entropy sources on startup and keep the connection open,
-+ so that it can be chrooted and can drop privileges.
-+
-+ <pre>
-+ # ==========================================================================
-+ # service type private unpriv chroot wakeup maxproc command + args
-+ # (yes) (yes) (yes) (never) (50)
-+ # ==========================================================================
-+ tlsmgr fifo - - y 300 1 tlsmgr
-+ </pre>
-+
-+ <h2>master.cf: additional services</h2>
-+
-+ It can be useful to have postfix listen on additional ports, namely
-+ "submission"=587 for email submission as defined in RFC2476; this
-+ is especially useful if you want to allow AUTH with plaintext
-+ passwords (PLAIN, LOGIN) and hence run on a port with encryption
-+ enforcement. Another useful port may be "smtps"=465 which was
-+ intended with TLS-wrapping and is still used by Outlook (Express).
-+
-+ <p>Both example entries already contain the flags to enable SASL
-+ authentication (which may be disabled on the normal port). Since
-+ the actual service names are used, smtps and submission must be
-+ defined in /etc/services (and probably also in
-+ /var/spool/postfix/etc/services if chrooted)!!! (Use the port
-+ numbers otherwise.)</p>
-+
-+ <pre>
-+ # ==========================================================================
-+ # service type private unpriv chroot wakeup maxproc command + args
-+ # (yes) (yes) (yes) (never) (50)
-+ # ==========================================================================
-+ smtps inet n - y - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
-+ submission inet n - y - - smtpd -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes
-+ </pre>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/index.html postfix-2.0.16-ti1.20/pfixtls/doc/index.html
-*** postfix-2.0.16/pfixtls/doc/index.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/index.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,53 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - A TLS extension for POSTFIX</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - A TLS extension for POSTFIX</h1>
-+
-+ <h2>Contents</h2>
-+
-+ <ul>
-+ <li><a href="intro.html">Introduction</a></li>
-+
-+ <li><a href="install.html">Installing the patchkit</a></li>
-+
-+ <li><a href="setup.html">Setting up the certificates</a></li>
-+
-+ <li><a href="conf.html">Configuring main.cf</a></li>
-+
-+ <li><a href="security.html">Security considerations</a></li>
-+
-+ <li><a href="test.html">Testing</a></li>
-+
-+ <li><a href="prng.html">PRNG - Pseudo Random Number
-+ Generator</a></li>
-+
-+ <li><a href="references.html">References</a></li>
-+ </ul>
-+
-+ Please check also the contents of the <tt>contributions</tt> folder
-+ including useful scripts and some <b>HOWTO</b> documents.
-+
-+ <pre>
-+ PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG
-+ CRYPTOGRAPHY SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST
-+ COMMUNICATING TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS
-+ ILLEGAL IN SOME PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE
-+ TO YOUR COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL
-+ TECHNICAL SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR
-+ OTHER PEOPLE YOU ARE STRONGLY ADVICED TO PAY CLOSE ATTENTION TO ANY
-+ EXPORT/IMPORT AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHOR OF
-+ POSTFIX/TLS IS NOT LIABLE FOR ANY VIOLATIONS YOU MAKE HERE. SO BE
-+ CAREFULLY YOURSELF, IT IS YOUR RESPONSIBILITY.
-+ </pre>
-+
-+ Lutz Jänicke, <a href=
-+ "http://www.aet.tu-cottbus.de/personen/jaenicke/">Homepage</a>,
-+ Email: <a href="mailto:Lutz.Jaenicke@aet.TU-Cottbus.DE"><em>
-+ Lutz.Jaenicke@aet.TU-Cottbus.DE</em></a>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/install.html postfix-2.0.16-ti1.20/pfixtls/doc/install.html
-*** postfix-2.0.16/pfixtls/doc/install.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/install.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,93 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Installation</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Installing the patchkit</h1>
-+
-+ <h2>Prerequisits</h2>
-+
-+ This patchkit is prepared for
-+
-+ <ul>
-+ <li>Postfix Version 2.0.15<br>
-+ <a href="http://www.postfix.org/">http://www.postfix.org/</a> [<a
-+ href="references.html#postfix">POSTFIX</a>]<br>
-+ The use of other versions might lead to patch conflicts or silent
-+ failures, as we directly change the source code.</li>
-+
-+ <li>OpenSSL Version 0.9.7b (>=0.9.5)<br>
-+ <a href="http://www.openssl.org/">http://www.openssl.org/</a> [<a
-+ href="references.html#openssl">OPENSSL</a>]<br>
-+ We use OpenSSL as library (and some command line tools to create
-+ the certificates, if necessary). OpenSSL is the successor of
-+ SSLeay.
-+ <p>Postfix/TLS uses properties that are only available starting with
-+ version 0.9.5 of the OpenSSL library. 0.9.5a and 0.9.6x have proven
-+ stability over several months.
-+
-+ The release 0.9.7 contains several enhancemants and bugfixes.
-+
-+ OpenSSL 0.9.7b is the latest release and the recommended version.
-+ </li>
-+ </ul>
-+
-+ You may also need to update your "patch" utility (see below).
-+
-+ <h2>Patching</h2>
-+
-+ The changes to the postfix source code as well as the additional
-+ files are included in the "<code>pfixtls.diff</code>" in the main
-+ directory of the patch kit. It is a unified diff.
-+
-+ <p>To apply the patches, go to the directory one level below the
-+ original postfix source tree (you should see
-+ "<code>postfix-xxxxxxx</code>" or "<code>snapshot-xxxxxxx</code>"
-+ when doing an "<code>ls -al</code>"
-+ at this point. The patch is then applied with:</p>
-+
-+ <pre>
-+ patch -p0 < path-to/pfixtls.diff
-+ </pre>
-+
-+ If you experience problems during the patch process (e.g. with the
-+ HP-UX 10.20 included patch), you might need to update your patch
-+ program, e.g. to an actual GNU-patch.
-+
-+ <p>If you need to apply the patchkit to a different version of
-+ patchlevel of postfix, you might try the following:</p>
-+
-+ <pre>
-+ cd postfix-directory ; patch -p1 < path-to/pfixtls.diff
-+ </pre>
-+
-+ Since the patch is in unified form, it might also apply to a mildly
-+ changed source, as long as no conflicts appear.
-+
-+ <h2>Compiling</h2>
-+
-+ After patching postfix will configure and compile as before. In
-+ order to enable the TLS functions, you must specify the path to the
-+ OpenSSL header files as well as the appropriate libraries, and you
-+ must define <code>USE_SSL</code>. Your command for configuration
-+ might then be:
-+
-+ <pre>
-+ make makefiles CCARGS="-DUSE_SSL -I/usr/local/ssl/include" AUXLIBS="-L/usr/local/ssl/lib -lssl -lcrypto"
-+ </pre>
-+
-+ You might need additional customization e.g. for using Berkeley-DB
-+ as listed in the postfix INSTALL instructions. You can then
-+ continue in the usual way with:
-+
-+ <pre>
-+ make
-+ </pre>
-+
-+ and then follow the instructions in the postfix INSTALL file.
-+
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/intro.html postfix-2.0.16-ti1.20/pfixtls/doc/intro.html
-*** postfix-2.0.16/pfixtls/doc/intro.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/intro.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,194 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Introduction</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Introduction</h1>
-+
-+ Postfix/TLS is an extension of the Postfix [<a href=
-+ "references.html#postfix">POSTFIX</a>] MTA software to support the
-+ TLS protocol.
-+
-+ <h2>A note about the start of the project</h2>
-+
-+ When I started writing this software, I had a sophisticated way to
-+ allow <a href="relaycert.html">relaying for roaming users</a> in
-+ mind. In the meantime, this project is living on its own.
-+
-+ <h2>RFC2246: The TLS (former SSL) protocol</h2>
-+
-+ By default all communication on the Internet is done without
-+ encryption and without strong authentication. That does mean that
-+ everybody with physical access to the communication line along
-+ which a network packet will travel can eavesdrop on your
-+ communication. Even worse, it might be possible to redirect or
-+ alter your communication so that information, that you want to send
-+ to a party can be lost or changed without your notice.
-+
-+ <p>In order to solve these security issues, the SSL protocol
-+ (Secure Socket Layers) was introduced by Netscape, Inc., which now
-+ has evolved into the standardised TLS protocol (Transportation
-+ Layer Security) as <a href="rfc2246.txt">RFC2246</a>. It offers
-+ both encryption of the communication (stopping eavesdropping) and
-+ strong authentication (making sure that both parties of a
-+ communication are correctly identified and that the communication
-+ cannot be altered).</p>
-+
-+ <p>Postfix/TLS does not realize the TLS protocol itself; it rather
-+ uses the OpenSSL package [<a href=
-+ "references.html#openssl">OPENSSL</a>] for this task. At the
-+ OpenSSL WWW-site you can also find links to in-depth documentation
-+ of the protocol and its features, so that it is not necessary to
-+ included them here. (And, of course, there is no use of re-writing
-+ what other people already wrote down, it just introduces additional
-+ errors.)</p>
-+
-+ <h2>RFC2487: Introducing TLS to SMTP</h2>
-+
-+ The integration of the TLS protocol to Internet mail, SMTP (Simple
-+ Mail Transport Protocol) is described in <a href="rfc2487.txt">
-+ RFC2487</a>.
-+
-+ <p>Unlike the first incarnations of SSL as a <em>wrapper</em>
-+ around normal network communications [<a href=
-+ "references.html#stunnel">STUNNEL</a>] [<a href=
-+ "references.html#jonama">JONAMA</a>], the TLS protocol is now
-+ completely <em>integrated</em> into the ESMTP: during the startup
-+ negotiation (EHLO) the server offers the support of TLS by
-+ advertising the <strong>STARTTLS</strong> feature. The client can
-+ now send the <strong>STARTTLS</strong> command to do authentication
-+ and switch to encrypted communication.</p>
-+
-+ <h2>Postfix/TLS: what can it do for you</h2>
-+
-+ The list of features presented here should be understood as a list
-+ of ideas. Not all of them are realized yet, please see the notes at
-+ each feature.
-+
-+ <ul>
-+ <li>Encrypted email transfer from one host to another.<br>
-+ Status: realized.<br>
-+ Comment: Once the STARTTLS negotiation is finished, the
-+ communication between both parties is encrypted.
-+ This also includes the MAIL FROM: and RCPT TO: envelop sender
-+ and recipient negotiation, so that an eavesdropper will not be able
-+ to get these informations.</li>
-+
-+ <li>Authentication of the receiving host to prevent
-+ interception.<br>
-+ Status: realized.<br>
-+ Comment: This is a quite important feature that is not difficult to
-+ implement. The problem lies in the fact, that not all hosts (read
-+ this: by now nearly no one) support this protocol. The sender must
-+ hence maintain a list of receivers which must identify by TLS,
-+ otherwise one could just intercept the communication and not offer
-+ STARTTLS, so that no authentication is done. One must also be
-+ careful to use the correct name of the host (see CNAMEs), but this
-+ problem is the same for http-servers.</li>
-+
-+ <li>Authentication of the sending host to prevent forgery.<br>
-+ Status: Difficult to do.<br>
-+ Comment: The transmission of emails is just a connection to the
-+ SMTP port (25) of the receiving host. This is done by either
-+ another MTA (Mail Transport Agent) or a MUA (Mail User Agent). In
-+ the first case, the sending MTA should present a client certificate
-+ issued on the name of the sending host. In the latter case however,
-+ the user has no access to the host's certificate and will (or not)
-+ present his own personal certificate. At this point I think that a
-+ satisfying <em>and</em> reliable solution is hardly possible (do
-+ you want your users' email bounce without reason?), so it has least
-+ priority.</li>
-+
-+ <li>Authentication of the sending host to allow relaying.<br>
-+ Status: realized.<br>
-+ Comment: This was the intention I had in mind when starting this
-+ project, so it was realized first. Based on the certificate the
-+ client MTA or MUA presents to the server, relaying can be
-+ allowed.</li>
-+
-+ <li>Any more ideas???<br>
-+ Status: Send me an email.</li>
-+ </ul>
-+
-+ <h2>Postfix/TLS: what it cannot do for you</h2>
-+
-+ There is one thing that I explicitly want to point out:
-+
-+ <ul>
-+ <li>Securing the privacy of your email.<br>
-+ Status: Cannot be done.<br>
-+ Comment: RFC2487 only takes care of the transportation between mail
-+ servers. To assure that nobody can eavesdrop on your private email
-+ communication, it would be necessary that
-+
-+ <ul>
-+ <li>all of the mailhubs in between are enforcing TLS.</li>
-+
-+ <li>all mailhubs themselves are trustworthy, as the email is only
-+ encrypted during transport, not when queued or spooled.</li>
-+
-+ <li>the destination is trustworthy, as the mail is spooled in clear
-+ and everybody who can access your mailbox (read this: at least the
-+ superuser) can read your mail!</li>
-+ </ul>
-+
-+ Hence, if you want privacy, you have to <em>send out</em> your
-+ email encrypted, e.g. using S/MIME or the traditional PGP
-+ package.</li>
-+
-+ <li>Authenticate the sender of an email.<br>
-+ Status: Cannot be done.<br>
-+ Comment: A lot of MUAs send out emails by just connecting the SMTP
-+ port of the sending host or nearest mailhub. There is no way to
-+ assure that the sender listed in the email is the real sender of
-+ the email. And even if it would be possible to identify the sender,
-+ the contents of the email might have been altered in between.<br>
-+ To ensure the identity of the sender and the integrity of the
-+ email, you can again use S/MIME or PGP.</li>
-+ </ul>
-+
-+ <h2>Support by Mail User Agents</h2>
-+
-+ The following MUAs are known to work with RFC2487:
-+ <ul>
-+ <li>Netscape >= 4.5 supports STARTTLS and client certificates.
-+ <li>Outlook (Express) >= 5 supports STARTTLS (only on port 25) and traditional
-+ SSL-wrapping style (on all other ports). No support for client certificates.
-+ <li>Eudora >= 5.1 supports STARTTLS. Client certificate status unknown.
-+ </ul>
-+
-+ <h2>Other OpenSource packages</h2>
-+
-+ As of version sendmail-8.11, sendmail includes RFC2487 support [<a
-+ href="references.html#sendmail">SENDMAIL</a>].
-+
-+ <p>Frederik Vermeulen has realized an RFC2487 extension [<a href=
-+ "references.html#qmailtls">QMAILTLS</a>] for the Qmail [<a href=
-+ "references.html#qmail">QMAIL</a>] MTA.</p>
-+
-+ <p>Matti Aarnio has integrated RFC2487 into ZMailer [<a href=
-+ "references.html#zmailer">ZMAILER</a>].</p>
-+
-+ <p>Michal Trojnara is currently integrating basic SMTP support into
-+ his stunnel software, starting with stunnel-3.3 [<a href=
-+ "references.html#stunnel">STUNNEL</a>].</p>
-+
-+ <p>Trey Childs is also working on a "wrapper" solution [<a href=
-+ "references.html#smtps">SMTPS</a>].</p>
-+
-+ <h2>Commercial implementations</h2>
-+
-+ The commercial version of sendmail includes RFC2487 support [<a
-+ href="references.html#sendmail.inc">SENDMAIL.INC</a>].
-+
-+ <p>Netscape Enterprise Server and Microsoft Exchange Server do offer
-+ RFC2487 functionality.</p>
-+
-+ <p>The CommunigatePro mailserver software also supports RFC2487
-+ [<a href="references.html#communigate">COMMUNIGATE</a>].</p>
-+
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/loadCAcert.pl postfix-2.0.16-ti1.20/pfixtls/doc/loadCAcert.pl
-*** postfix-2.0.16/pfixtls/doc/loadCAcert.pl Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/loadCAcert.pl Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,23 ----
-+ #!/usr/local/bin/perl -T
-+
-+ require 5.003;
-+ use strict;
-+ use CGI;
-+
-+ my $cert_dir = "/usr/local/ssl/certs";
-+ my $cert_file = "CAcert.pem";
-+
-+ my $query = new CGI;
-+
-+ my $kind = $query->param('FORMAT');
-+ if($kind eq 'DER') { $cert_file = "CAcert.der"; }
-+
-+ my $cert_path = "$cert_dir/$cert_file";
-+
-+ open(CERT, "<$cert_path");
-+ my $data = join '', <CERT>;
-+ close(CERT);
-+ print "Content-Type: application/x-x509-ca-cert\n";
-+ print "Content-Length: ", length($data), "\n\n$data";
-+
-+ 1;
-diff -Pcr postfix-2.0.16/pfixtls/doc/myownca.html postfix-2.0.16-ti1.20/pfixtls/doc/myownca.html
-*** postfix-2.0.16/pfixtls/doc/myownca.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/myownca.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,175 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Being your on CA</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Lutz's very short course on being your own
-+ CA</h1>
-+
-+ This section is kept quite short as there are already a lot of
-+ pages explaining these things (e.g. [<a href=
-+ "references.html#introcert">INTROCERT</a>]). There are also
-+ projects under way to make this task easier [<a href=
-+ "references.html#openca">OPENCA</a>], so I wont't waste your time
-+ (and mine) by writing a book about it.
-+
-+ <h2>Be your own CA</h2>
-+
-+ If you want to do relaying based on client certificates you may
-+ want to issue your own client certificates; hence you want to be
-+ your own certificate authority (CA). Of course nobody else will
-+ accept your certificates, so the damage you do is not so high (the
-+ requirements for a good "professional" CA are very high, as you
-+ should have the CA key on a private host without network for
-+ security, be strict about checking the identity of requesters etc).
-+
-+
-+ <p>For laziness, we also don't care about the (worthful)
-+ possibility to generate certificates for specific purposes (e.g.
-+ for servers, clients, email-signing) and simply generate "unlimited
-+ general purpose" certificates. So a certificate issued for the
-+ person "John Doe" is also valid for the "John Doe"-server.</p>
-+
-+ <p>Using OpenSSL it is quite simple to become your own CA. Just
-+ run</p>
-+
-+ <pre>
-+ CA.pl -newca
-+ </pre>
-+
-+ and you are done. Just make sure, that you select a useful CN
-+ (Common Name)! By just using your name, you might create a lot of
-+ confusion, as the CA certificate for "Lutz Jaenicke" looks quite
-+ the same as the personal client certificate for "Lutz Jaenicke" (I
-+ can tell you). Of course you can further improve this private CA by
-+ editing the <code>openssl.cnf</code> file, especially the comment.
-+
-+ <p>If you want the full comfort of being your own CA, you must
-+ import your CA certificate to Netscape. Unfortunately Netscape does
-+ not offer an explicit function to perform this task (unlike for
-+ client certificates). If you have an http-server available (and I
-+ think you do), you can add the <a href="loadCAcert.pl">
-+ loadCAcert.pl</a> script to your <code>cgi-bin</code> directory. If
-+ you call it from Netscape (or Internet Explorer), you can load the
-+ certificate! (Taken from [<a href=
-+ "references.html/#introcert">6</a>])</p>
-+
-+ <h2>Create your site certificate</h2>
-+
-+ Ok, you now must create a site certificate for your postfix server.
-+ As your clients will use it for verification, it must contain the
-+ name of your host as common name (CN): host.in.domain.
-+
-+ <p>You want your postfix system to start up at boot time without
-+ trouble? Then your server private key must not be encrypted. So
-+ when you create the key you must add the <code>-nodes</code> option
-+ in <code>CA.pl</code> to the line with the <code>-newcert</code>
-+ and/or <code>-newreq</code> command:</p>
-+
-+ <pre>
-+ *** CA.pl Wed Mar 24 10:30:38 1999
-+ --- CA1.pl Sat Mar 27 19:36:47 1999
-+ ***************
-+ *** 56,67 ****
-+ exit 0;
-+ } elsif (/^-newcert$/) {
-+ # create a certificate
-+ ! system ("$REQ -new -x509 -keyout newreq.pem -out newreq.pem $DAYS");
-+ $RET=$?;
-+ print "Certificate (and private key) is in newreq.pem\n"
-+ } elsif (/^-newreq$/) {
-+ # create a certificate request
-+ ! system ("$REQ -new -keyout newreq.pem -out newreq.pem $DAYS");
-+ $RET=$?;
-+ print "Request (and private key) is in newreq.pem\n";
-+ } elsif (/^-newca$/) {
-+ --- 56,67 ----
-+ exit 0;
-+ } elsif (/^-newcert$/) {
-+ # create a certificate
-+ ! system ("$REQ -new -x509 -nodes -keyout newreq.pem -out newreq.pem $DAYS");
-+ $RET=$?;
-+ print "Certificate (and private key) is in newreq.pem\n"
-+ } elsif (/^-newreq$/) {
-+ # create a certificate request
-+ ! system ("$REQ -new -nodes -keyout newreq.pem -out newreq.pem $DAYS");
-+ $RET=$?;
-+ print "Request (and private key) is in newreq.pem\n";
-+ } elsif (/^-newca$/) {
-+ </pre>
-+
-+ For sslwrap or stunnel the authors propose to use self signed certs
-+ created with <code>-newcert</code>. I rather propose to create an
-+ ordinary certificate request with
-+
-+ <pre>
-+ CA.pl -newreq
-+ </pre>
-+
-+ and then sign it with your CA:
-+
-+ <pre>
-+ CA.pl -sign
-+ </pre>
-+
-+ Now you can install the cert from <code>cacert.pem</code> to <code>
-+ /etc/postfix/CAcert.pem</code>, the created certificate from <code>
-+ newcert.pem</code> to <code>/etc/postfix/cert.pem</code> and the
-+ key part form <code>newreq.pem</code> to <code>
-+ /etc/postfix/key.pem</code>. Please be aware, that the <code>
-+ key.pem</code> is not protected by password, so you have to protect
-+ it by file access privileges. As the information is read before
-+ smtpd changes to chroot jail, it still has root privileges, so you
-+ should
-+
-+ <pre>
-+ chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem
-+ </pre>
-+
-+ <h2>Create a client certificate</h2>
-+
-+ Creating a client certificate is as easy as a site certificate. At
-+ least, if you are doing it as a CA. First you create and sign a
-+ pair of key and certificate. Be sure to add the correct common name
-+ (CN) for the client:
-+
-+ <pre>
-+ CA.pl -newreq
-+ CA.pl -sign
-+ </pre>
-+
-+ If you want to do client certificate based relaying, you do need
-+ the fingerprint of the certificate, which can be obtained with
-+
-+ <pre>
-+ openssl x509 -fingerprint -in newcert.pem
-+ </pre>
-+
-+ Now this certificate must be imported into netscape. Therefore the
-+ data you just created must be converted to a ".p12" file in PKCS#12
-+ format. You do need the <code>pkcs12</code> utility [<a href=
-+ "references.html#pkcs12">PKCS12</a>], which is included in the
-+ OpenSSL package as of version 0.9.3. The necessary command is:
-+
-+ <pre>
-+ pkcs12 -export -in newcert.pem -inkey newreq.pem \
-+ -certfile /usr/local/ssl/CAcert.pem -name "Name" -out newcert.p12
-+ </pre>
-+
-+ Of course your filenames may vary. Please take special care to
-+ supply a good name to your certificate. First: The name will be
-+ listed every time when a client certificate is to be send by
-+ netcape. As a person may have several certificates, the name might
-+ include a hint on the CA (e.g. "Lutz Jaenicke (Lutz CA)"). <strong>
-+ If you want to have a lot of fun, you can just omit the name.
-+ Netscape will happily import the certificate, but you won't see it
-+ in the list of user certificates. And as you don't see it, you
-+ cannot select it. And as Netscape will not overwrite it, if you
-+ offer the same (corrected) certificate with a name, you want to
-+ delete it, but as you cannot select it, you cannot delete it. You
-+ got the point?</strong>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/prng.html postfix-2.0.16-ti1.20/pfixtls/doc/prng.html
-*** postfix-2.0.16/pfixtls/doc/prng.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/prng.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,97 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - PRNG Pseudo Random Number Generator</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - PRNG Pseudo Random Number Generator</h1>
-+
-+ One of the crucial points of encryption is the generation of the
-+ keys, for which random numbers are required. As of OpenSSL 0.9.5,
-+ the seeding of the included PRNG Pseudo Random Number Generator is
-+ checked. Starting with Postfix/TLS 0.5.4, an architecture to
-+ collect entropy is included.
-+
-+ <h2>Included PRNG</h2>
-+
-+ OpenSSL features a quite sophisticated PRNG. In order to generate
-+ random numbers of lengths of more then 1024bit, a 8192bit (=1kB)
-+ pool is kept and used to generate these random numbers. To achieve
-+ full complexity for an attacker, it is necessary to have the full
-+ range of random numbers available and not restrict the search space
-+ used for searching keys, hence an according amount of entropy is
-+ necessary.
-+
-+ <h2>Obtaining Entropy</h2>
-+
-+ To get entropy, unpredictable events are needed. Unfortunately,
-+ computers and software tend to be very predictable, so that a lot
-+ of effort is necessary to collect unpredictable events. The
-+ mathematical techniques are discussed in the excellent book of
-+ Schneier "Applied Cryptography".
-+
-+ <p>We use at least one feature: if you have collected a pool of
-+ data with entropy in it, you can add up more data without losing
-+ the entropy already there, so that we can mix external sources and
-+ internal bits to only increase the entropy.</p>
-+
-+ <h2>External sources</h2>
-+
-+ Only few operating systems provide good entropy collection.
-+
-+ <h3>/dev/random and /dev/urandom</h3>
-+
-+ Linux offers the <tt>/dev/random</tt> and <tt>/dev/urandom</tt>
-+ devices, some BSD derivatives as well.
-+
-+ <p><tt>/dev/random</tt> will provide high quality random data, but
-+ it will block until enough entropy is available, if too much random
-+ data is requested to fast. <tt>/dev/urandom</tt> will fill up the
-+ real entropy data with data from an internal PRNG and will never
-+ block. For a system with automated startup /dev/urandom should be
-+ used. Reading from /dev/urandom will however trigger kernel
-+ activity to satisfy the demands. Imagine starting up postfix with a
-+ large number of emails in the queue. 50 (default) smtp processes
-+ want to start at the same time and access <tt>
-+ /dev/urandom</tt>.</p>
-+
-+ <h3>Entropy Gathering Daemon</h3>
-+
-+ A replacement for operating systems without good random number
-+ collection is the <a href="references.html#egd">EGD</a> Entropy
-+ Gathering Daemon. It will also extract entropy from a lot of
-+ sources.
-+
-+ <p>EGD has a command driven interface, there is a command for
-+ blocking and one for non-blocking read. Unlike <tt>
-+ /dev/urandom</tt> the non-blocking command will not trigger an
-+ internal PRNG to fill up, but will simply return a smaller number
-+ of bytes than requested, even 0 if totally drained.</p>
-+
-+ <p>EGD should hence not be used for direct feeding of smtp[d]
-+ processes. Again, imagine 50 smtp processes starting delivery at
-+ the same time.</p>
-+
-+ <p><em>To circumvent this problem, I have witten my own daemon,
-+ that has a EGD compatible interface but can never run dry, just
-+ like <tt>/dev/urandom</tt>. Check out <a href=
-+ "references.html#prngd">PRNGD</a> for details.</em></p>
-+
-+ <h3>Intermediate File</h3>
-+
-+ Hence, Postfix/TLS maintains its own pool of entropy by means
-+ of the <em>tlsmgr</em> daemon. It will collect entropy from an
-+ external source at startup and periodically during runtime to ever
-+ increase the entropy in the pool. The smtp[d] processes are fed
-+ from an PRNG exchange file that is updated in short periods. Upon
-+ restart, tlsmgr will also read entropy from this file, so that the
-+ large entropy pool is fully utilized.
-+
-+ <p>The single smtp[d] daemons can also access an external source. Their
-+ collected entropy is also stirred into the intermediate file, so that
-+ a significant amount of entropy is available alltogether.
-+
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/references.html postfix-2.0.16-ti1.20/pfixtls/doc/references.html
-*** postfix-2.0.16/pfixtls/doc/references.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/references.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,105 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - References</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - References</h1>
-+
-+ <ol>
-+ <li>[<a name="postfix">POSTFIX] The Postfix (formerly VMailer) Home
-+ Page: <a href="http://www.postfix.org/">
-+ http://www.postfix.org/</a>.</a></li>
-+
-+ <li>[<a name="openssl">OPENSSL</a>] OpenSSL: The Open Source
-+ toolkit for SSL/TLS: <a href="http://www.openssl.org/">
-+ http://www.openssl.org/</a>.</li>
-+
-+ <li>[<a name="pkcs12">PKCS12</a>]OpenSSL PKCS#12 Program FAQ: <a
-+ href="http://www.drh-consultancy.demon.co.uk/pkcs12faq.html">
-+ http://www.drh-consultancy.demon.co.uk/pkcs12faq.html</a>.</li>
-+
-+ <li>[<a name="sslwrap">SSLWRAP</a>] SSLwrap Homepage: <a href=
-+ "http://www.rickk.com/sslwrap/">
-+ http://www.rickk.com/sslwrap/</a>.</li>
-+
-+ <li>[<a name="stunnel">STUNNEL</a>] Stunnel Homepage: <a href=
-+ "http://stunnel.mirt.net/">
-+ http://stunnel.mirt.net/</a>.</li>
-+
-+ <li>[<a name="introcert">INTROCERT</a>] Introducing SSL and
-+ Certificates using SSLeay: <a href=
-+ "http://www.ultranet.com/~fhirsch/Papers/wwwj/">
-+ http://www.ultranet.com/~fhirsch/Papers/wwwj/</a>.</li>
-+
-+ <li>[<a name="imcorg">IMC</a>] Internet Mail Consortium: <a href=
-+ "http://www.imc.org/">http://www.imc.org/</a>.</li>
-+
-+ <li>[<a name="imcorgappstls">IETF-APPS-TLS</a>] ietf-apps-tls
-+ mailing list: <a href="http://www.imc.org/ietf-apps-tls/">
-+ http://www.imc.org/ietf-apps-tls/</a></li>
-+
-+ <li>[<a name="openca">OPENCA</a>] The OpenCA Project: <a href=
-+ "http://www.openca.org/">http://www.openca.org/</a>.</li>
-+
-+ <li>[<a name="dfnpca">DFNPCA</a>] DFN-PCA: <a href=
-+ "http://www.dfn-pca.de/">http://www.dfn-pca.de/</a>.</li>
-+
-+ <li>[<a name="sendmail">SENDMAIL</a>] Sendmail: <a href=
-+ "http://www.sendmail.org/">http://www.sendmail.org/</a>.</li>
-+
-+ <li>[<a name="sendmail.inc">SENDMAIL.INC</a>] Sendmail Inc: <a
-+ href="http://www.sendmail.com/">http://www.sendmail.com/</a>.</li>
-+
-+ <li>[<a name="qmail">QMAIL</a>] Qmail: <a href=
-+ "http://www.qmail.org/">http://www.qmail.org/</a>.</li>
-+
-+ <li>[<a name="qmailtls">QMAILTLS</a>] Qmail/TLS: <a href=
-+ "http://www.esat.kuleuven.ac.be/~vermeule/qmail/tls.patch">
-+ http://www.esat.kuleuven.ac.be/~vermeule/qmail/tls.patch</a>.</li>
-+
-+ <li>[<a name="zmailer">ZMAILER</a>] ZMailer: <a href=
-+ "http://www.zmailer.org/">http://www.zmailer.org/</a>.</li>
-+
-+ <li>[<a name="jonama">JONAMA</a>] Jonama: <a href=
-+ "http://www.multimania.com/jonama/">
-+ http://www.multimania.com/jonama/</a>.</li>
-+
-+ <li>[<a name="smtps">SMTPS</a>] Trey Child's STARTTLS wrapper: <a
-+ href="http://blueice.shopkeeper.de/~tchilds/">
-+ http://blueice.shopkeeper.de/~tchilds/</a>.</li>
-+
-+ <li>[<a name="safegossip">SAFEGOSSIP</a>] Safegossip universal
-+ TLS-wrapper: <a href="http://www.skygate.co.uk/safegossip/">
-+ http://www.skygate.co.uk/safegossip/</a>.</li>
-+
-+ <li>[<a name="sendmailtls">SENDMAIL-TLS</a>] Jeremy Beker's
-+ sendmail-tls wrapper: <a href="http://opensource.3gi.com/">
-+ http://opensource.3gi.com/</a>.</li>
-+
-+ <li>[<a name="communigate">COMMUNIGATE</a>] Stalker Software's
-+ CommunigatePro mailserver product: <a href="http://www.stalker.com/">
-+ http://www.stalker.com/</a>.</li>
-+
-+ <li>[<a name="egd">EGD</a>] Entropy Gathering Daemon: <a href=
-+ "http://www.lothar.com/tech/crypto/">
-+ http://www.lothar.com/tech/crypto/</a>.</li>
-+
-+ <li>[<a name="prngd">PRNGD</a>] Pseudo Random Number Generator
-+ Daemon: <a href=
-+ "http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html">
-+ http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html</a>.</li>
-+
-+ <li>[<a name="oe_ssl">Outlook/SSL</a>] Outlook (Express) and
-+ STARTTLS info: <a href=
-+ "http://support.microsoft.com/support/kb/articles/Q218/4/30.ASP">
-+ http://support.microsoft.com/support/kb/articles/Q218/4/30.ASP</a>.</li>
-+
-+ <li>[<a name="justinhowto">TLS/CA Howto</a>] Justin Davis TLS and CA Howtos:
-+ <a href="http://palmcoder.net/files/howtos/">
-+ http://palmcoder.net/files/howtos/</a>.</li>
-+ </ol>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/relaycert.html postfix-2.0.16-ti1.20/pfixtls/doc/relaycert.html
-*** postfix-2.0.16/pfixtls/doc/relaycert.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/relaycert.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,124 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Initial Motivation</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Initial Motivation</h1>
-+
-+ This introduction shall point out the motivation, why I spend my
-+ time writing this TLS extension for postfix.
-+
-+ <h2>Roaming users problem</h2>
-+
-+ It quite often happens that my users want to access their mailboxes
-+ and to send emails from hosts outside our network. The main reasons
-+ are the access from home via Internet service providers (ISP) or
-+ from abroad during business trips (in our case typically to other
-+ universities around the world). Sending and accessing leads to two
-+ loosely coupled problems.
-+
-+ <h2>UCE control</h2>
-+
-+ One problem is sending emails, because from abroad it is seldom
-+ possible to predict the sending hostname we will have and when
-+ using an ISP the assigned hostname is typically random. As we of
-+ course must have UCE control in effect, I either must open up
-+ relaying complete ISP domains on my users request (Arrgghh!) or
-+ must introduce an authentication beside the hostname or IP address.
-+
-+
-+ <h2>Passwords and insecure networks</h2>
-+
-+ This directly leads to the second problem. Recent versions of
-+ Netscape do offer password based authentication. This solves the
-+ UCE problem but introduces another one, which I consider far more
-+ severe: The users have to send a password in plain text over the
-+ network. Of course I could solve this problem by issuing special
-+ passwords just for this reasons, but some of my users don't have a
-+ clue of what is going on between the keyboard and the screen, so
-+ they would happily try their real password.
-+
-+ <p>The same problem of course also applies to the POP and IMAP
-+ services. I tackled them first, because they are typically attacked
-+ by port scanners, so I closed them down by tcpwrappers (Hi Wietse!)
-+ to only allow my local hosts to access them.</p>
-+
-+ <h2>Encryption via SSL</h2>
-+
-+ The solution to the plain text password problem was easily found
-+ with the use of SSL. You just tunnel the POP or IMAP connection
-+ through SSL, using either <strong>SSLwrap</strong> [<a href=
-+ "references.html#sslwrap">SSLWRAP</a>] or <strong>stunnel</strong>
-+ [<a href="references.html#stunnel">STUNNEL</a>].
-+
-+ <p>Netscape supports IMAP with SSL tunneling since version 4, I
-+ have one user with Outlook Express, who uses POP3 with SSL
-+ tunneling, so this solves the plain text password problem by
-+ encryption.</p>
-+
-+ <h2>Netscape 4.5</h2>
-+
-+ Starting with Netscape 4.5, also sending with SSL encryption is
-+ supported. As Netscape also supports client certificates, this
-+ seemed to be an easy solution for the UCE control problem. So I
-+ happily added an "smtps" service with SSL wrapper and client
-+ certificate verification. Unfortunately it didn't work and the
-+ connection just hung! After some digging around I found out, that
-+ Netscape 4.5 seems to realize the protocol described in <a href=
-+ "rfc2487.txt">RFC 2487</a> [<a href=
-+ "references.html#imcorg">IMC</a>].
-+
-+ <h2>RFC 2487 - SMTP Service Extension for Secure SMTP over TLS</h2>
-+
-+ RFC 2487 describes how to include TLS (the successor of SSL) into
-+ the normal Extended SMTP protocol. During the normal EHLO start
-+ negotiation the server offers the STARTTLS option to the client,
-+ which then issues the STARTTLS command. After the server accepts
-+ the command (220), the normal SSL handshake will start.
-+
-+ <p>Unfortunately it is impossible to handle this situation with a
-+ normal tunneling software, as they are not prepared to do clear
-+ text negotiation before running SSL and don't have the slightest
-+ idea on the SMTP protocol. Therefore the way to go was to extend a
-+ given mail server software. The first candidate was sendmail-8.9.3,
-+ as I was a long term sendmail user. After digging around some I
-+ came to the conclusion, that even though possible, the source code
-+ was quite difficult to understand and adding the necessary
-+ configuration options didn't look inviting.</p>
-+
-+ <h2>Postfix</h2>
-+
-+ At this point (February 1999) I checked other mail servers and was
-+ immedideately fascinated by postfix source. It was very good to
-+ read and understand, so I decided that if I would take the time,
-+ then postfix would be the way to go.
-+
-+ <p>I then started to first change our site to postfix. It took some
-+ hours to do this, because our mail system is running on a common
-+ network I administrate for several chairs, each of them with its
-+ own mail server and domain, but a common user base, so a lot of
-+ rewriting takes place, we need virtual services for symbolic names
-+ like "webmaster" etc.</p>
-+
-+ <h2>Postfix/TLS</h2>
-+
-+ Some time after having done this I finally found the time to write
-+ my TLS extensions for postfix. I took the source of the <code>
-+ s_server</code> of the OpenSSL package and added a simplified
-+ version of it to postfix, so that by now we can run the SMTP
-+ protocol encrypted on the server side. This would also allow us to
-+ use plain text password authentication, but as it is available
-+ without cost, I rather decided to go with client certificates. If
-+ you can offer a client certificate to our server, that is included
-+ in a list on our server, you can relay your emails through our
-+ server!
-+
-+ <h2>Summary</h2>
-+
-+ Postfix/TLS is an addition to the smtpd server, which implements the RFC 2487
-+ TLS Service Extension and allows UCE control based on client certificates.
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/rfc2246.txt postfix-2.0.16-ti1.20/pfixtls/doc/rfc2246.txt
-*** postfix-2.0.16/pfixtls/doc/rfc2246.txt Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/rfc2246.txt Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,4483 ----
-+
-+
-+
-+
-+
-+
-+ Network Working Group T. Dierks
-+ Request for Comments: 2246 Certicom
-+ Category: Standards Track C. Allen
-+ Certicom
-+ January 1999
-+
-+
-+ The TLS Protocol
-+ Version 1.0
-+
-+ Status of this Memo
-+
-+ This document specifies an Internet standards track protocol for the
-+ Internet community, and requests discussion and suggestions for
-+ improvements. Please refer to the current edition of the "Internet
-+ Official Protocol Standards" (STD 1) for the standardization state
-+ and status of this protocol. Distribution of this memo is unlimited.
-+
-+ Copyright Notice
-+
-+ Copyright (C) The Internet Society (1999). All Rights Reserved.
-+
-+ Abstract
-+
-+ This document specifies Version 1.0 of the Transport Layer Security
-+ (TLS) protocol. The TLS protocol provides communications privacy over
-+ the Internet. The protocol allows client/server applications to
-+ communicate in a way that is designed to prevent eavesdropping,
-+ tampering, or message forgery.
-+
-+ Table of Contents
-+
-+ 1. Introduction 3
-+ 2. Goals 4
-+ 3. Goals of this document 5
-+ 4. Presentation language 5
-+ 4.1. Basic block size 6
-+ 4.2. Miscellaneous 6
-+ 4.3. Vectors 6
-+ 4.4. Numbers 7
-+ 4.5. Enumerateds 7
-+ 4.6. Constructed types 8
-+ 4.6.1. Variants 9
-+ 4.7. Cryptographic attributes 10
-+ 4.8. Constants 11
-+ 5. HMAC and the pseudorandom function 11
-+ 6. The TLS Record Protocol 13
-+ 6.1. Connection states 14
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 1]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 6.2. Record layer 16
-+ 6.2.1. Fragmentation 16
-+ 6.2.2. Record compression and decompression 17
-+ 6.2.3. Record payload protection 18
-+ 6.2.3.1. Null or standard stream cipher 19
-+ 6.2.3.2. CBC block cipher 19
-+ 6.3. Key calculation 21
-+ 6.3.1. Export key generation example 22
-+ 7. The TLS Handshake Protocol 23
-+ 7.1. Change cipher spec protocol 24
-+ 7.2. Alert protocol 24
-+ 7.2.1. Closure alerts 25
-+ 7.2.2. Error alerts 26
-+ 7.3. Handshake Protocol overview 29
-+ 7.4. Handshake protocol 32
-+ 7.4.1. Hello messages 33
-+ 7.4.1.1. Hello request 33
-+ 7.4.1.2. Client hello 34
-+ 7.4.1.3. Server hello 36
-+ 7.4.2. Server certificate 37
-+ 7.4.3. Server key exchange message 39
-+ 7.4.4. Certificate request 41
-+ 7.4.5. Server hello done 42
-+ 7.4.6. Client certificate 43
-+ 7.4.7. Client key exchange message 43
-+ 7.4.7.1. RSA encrypted premaster secret message 44
-+ 7.4.7.2. Client Diffie-Hellman public value 45
-+ 7.4.8. Certificate verify 45
-+ 7.4.9. Finished 46
-+ 8. Cryptographic computations 47
-+ 8.1. Computing the master secret 47
-+ 8.1.1. RSA 48
-+ 8.1.2. Diffie-Hellman 48
-+ 9. Mandatory Cipher Suites 48
-+ 10. Application data protocol 48
-+ A. Protocol constant values 49
-+ A.1. Record layer 49
-+ A.2. Change cipher specs message 50
-+ A.3. Alert messages 50
-+ A.4. Handshake protocol 51
-+ A.4.1. Hello messages 51
-+ A.4.2. Server authentication and key exchange messages 52
-+ A.4.3. Client authentication and key exchange messages 53
-+ A.4.4. Handshake finalization message 54
-+ A.5. The CipherSuite 54
-+ A.6. The Security Parameters 56
-+ B. Glossary 57
-+ C. CipherSuite definitions 61
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 2]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ D. Implementation Notes 64
-+ D.1. Temporary RSA keys 64
-+ D.2. Random Number Generation and Seeding 64
-+ D.3. Certificates and authentication 65
-+ D.4. CipherSuites 65
-+ E. Backward Compatibility With SSL 66
-+ E.1. Version 2 client hello 67
-+ E.2. Avoiding man-in-the-middle version rollback 68
-+ F. Security analysis 69
-+ F.1. Handshake protocol 69
-+ F.1.1. Authentication and key exchange 69
-+ F.1.1.1. Anonymous key exchange 69
-+ F.1.1.2. RSA key exchange and authentication 70
-+ F.1.1.3. Diffie-Hellman key exchange with authentication 71
-+ F.1.2. Version rollback attacks 71
-+ F.1.3. Detecting attacks against the handshake protocol 72
-+ F.1.4. Resuming sessions 72
-+ F.1.5. MD5 and SHA 72
-+ F.2. Protecting application data 72
-+ F.3. Final notes 73
-+ G. Patent Statement 74
-+ Security Considerations 75
-+ References 75
-+ Credits 77
-+ Comments 78
-+ Full Copyright Statement 80
-+
-+ 1. Introduction
-+
-+ The primary goal of the TLS Protocol is to provide privacy and data
-+ integrity between two communicating applications. The protocol is
-+ composed of two layers: the TLS Record Protocol and the TLS Handshake
-+ Protocol. At the lowest level, layered on top of some reliable
-+ transport protocol (e.g., TCP[TCP]), is the TLS Record Protocol. The
-+ TLS Record Protocol provides connection security that has two basic
-+ properties:
-+
-+ - The connection is private. Symmetric cryptography is used for
-+ data encryption (e.g., DES [DES], RC4 [RC4], etc.) The keys for
-+ this symmetric encryption are generated uniquely for each
-+ connection and are based on a secret negotiated by another
-+ protocol (such as the TLS Handshake Protocol). The Record
-+ Protocol can also be used without encryption.
-+
-+ - The connection is reliable. Message transport includes a message
-+ integrity check using a keyed MAC. Secure hash functions (e.g.,
-+ SHA, MD5, etc.) are used for MAC computations. The Record
-+ Protocol can operate without a MAC, but is generally only used in
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 3]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ this mode while another protocol is using the Record Protocol as
-+ a transport for negotiating security parameters.
-+
-+ The TLS Record Protocol is used for encapsulation of various higher
-+ level protocols. One such encapsulated protocol, the TLS Handshake
-+ Protocol, allows the server and client to authenticate each other and
-+ to negotiate an encryption algorithm and cryptographic keys before
-+ the application protocol transmits or receives its first byte of
-+ data. The TLS Handshake Protocol provides connection security that
-+ has three basic properties:
-+
-+ - The peer's identity can be authenticated using asymmetric, or
-+ public key, cryptography (e.g., RSA [RSA], DSS [DSS], etc.). This
-+ authentication can be made optional, but is generally required
-+ for at least one of the peers.
-+
-+ - The negotiation of a shared secret is secure: the negotiated
-+ secret is unavailable to eavesdroppers, and for any authenticated
-+ connection the secret cannot be obtained, even by an attacker who
-+ can place himself in the middle of the connection.
-+
-+ - The negotiation is reliable: no attacker can modify the
-+ negotiation communication without being detected by the parties
-+ to the communication.
-+
-+ One advantage of TLS is that it is application protocol independent.
-+ Higher level protocols can layer on top of the TLS Protocol
-+ transparently. The TLS standard, however, does not specify how
-+ protocols add security with TLS; the decisions on how to initiate TLS
-+ handshaking and how to interpret the authentication certificates
-+ exchanged are left up to the judgment of the designers and
-+ implementors of protocols which run on top of TLS.
-+
-+ 2. Goals
-+
-+ The goals of TLS Protocol, in order of their priority, are:
-+
-+ 1. Cryptographic security: TLS should be used to establish a secure
-+ connection between two parties.
-+
-+ 2. Interoperability: Independent programmers should be able to
-+ develop applications utilizing TLS that will then be able to
-+ successfully exchange cryptographic parameters without knowledge
-+ of one another's code.
-+
-+ 3. Extensibility: TLS seeks to provide a framework into which new
-+ public key and bulk encryption methods can be incorporated as
-+ necessary. This will also accomplish two sub-goals: to prevent
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 4]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ the need to create a new protocol (and risking the introduction
-+ of possible new weaknesses) and to avoid the need to implement an
-+ entire new security library.
-+
-+ 4. Relative efficiency: Cryptographic operations tend to be highly
-+ CPU intensive, particularly public key operations. For this
-+ reason, the TLS protocol has incorporated an optional session
-+ caching scheme to reduce the number of connections that need to
-+ be established from scratch. Additionally, care has been taken to
-+ reduce network activity.
-+
-+ 3. Goals of this document
-+
-+ This document and the TLS protocol itself are based on the SSL 3.0
-+ Protocol Specification as published by Netscape. The differences
-+ between this protocol and SSL 3.0 are not dramatic, but they are
-+ significant enough that TLS 1.0 and SSL 3.0 do not interoperate
-+ (although TLS 1.0 does incorporate a mechanism by which a TLS
-+ implementation can back down to SSL 3.0). This document is intended
-+ primarily for readers who will be implementing the protocol and those
-+ doing cryptographic analysis of it. The specification has been
-+ written with this in mind, and it is intended to reflect the needs of
-+ those two groups. For that reason, many of the algorithm-dependent
-+ data structures and rules are included in the body of the text (as
-+ opposed to in an appendix), providing easier access to them.
-+
-+ This document is not intended to supply any details of service
-+ definition nor interface definition, although it does cover select
-+ areas of policy as they are required for the maintenance of solid
-+ security.
-+
-+ 4. Presentation language
-+
-+ This document deals with the formatting of data in an external
-+ representation. The following very basic and somewhat casually
-+ defined presentation syntax will be used. The syntax draws from
-+ several sources in its structure. Although it resembles the
-+ programming language "C" in its syntax and XDR [XDR] in both its
-+ syntax and intent, it would be risky to draw too many parallels. The
-+ purpose of this presentation language is to document TLS only, not to
-+ have general application beyond that particular goal.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 5]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 4.1. Basic block size
-+
-+ The representation of all data items is explicitly specified. The
-+ basic data block size is one byte (i.e. 8 bits). Multiple byte data
-+ items are concatenations of bytes, from left to right, from top to
-+ bottom. From the bytestream a multi-byte item (a numeric in the
-+ example) is formed (using C notation) by:
-+
-+ value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
-+ ... | byte[n-1];
-+
-+ This byte ordering for multi-byte values is the commonplace network
-+ byte order or big endian format.
-+
-+ 4.2. Miscellaneous
-+
-+ Comments begin with "/*" and end with "*/".
-+
-+ Optional components are denoted by enclosing them in "[[ ]]" double
-+ brackets.
-+
-+ Single byte entities containing uninterpreted data are of type
-+ opaque.
-+
-+ 4.3. Vectors
-+
-+ A vector (single dimensioned array) is a stream of homogeneous data
-+ elements. The size of the vector may be specified at documentation
-+ time or left unspecified until runtime. In either case the length
-+ declares the number of bytes, not the number of elements, in the
-+ vector. The syntax for specifying a new type T' that is a fixed
-+ length vector of type T is
-+
-+ T T'[n];
-+
-+ Here T' occupies n bytes in the data stream, where n is a multiple of
-+ the size of T. The length of the vector is not included in the
-+ encoded stream.
-+
-+ In the following example, Datum is defined to be three consecutive
-+ bytes that the protocol does not interpret, while Data is three
-+ consecutive Datum, consuming a total of nine bytes.
-+
-+ opaque Datum[3]; /* three uninterpreted bytes */
-+ Datum Data[9]; /* 3 consecutive 3 byte vectors */
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 6]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Variable length vectors are defined by specifying a subrange of legal
-+ lengths, inclusively, using the notation <floor..ceiling>. When
-+ encoded, the actual length precedes the vector's contents in the byte
-+ stream. The length will be in the form of a number consuming as many
-+ bytes as required to hold the vector's specified maximum (ceiling)
-+ length. A variable length vector with an actual length field of zero
-+ is referred to as an empty vector.
-+
-+ T T'<floor..ceiling>;
-+
-+ In the following example, mandatory is a vector that must contain
-+ between 300 and 400 bytes of type opaque. It can never be empty. The
-+ actual length field consumes two bytes, a uint16, sufficient to
-+ represent the value 400 (see Section 4.4). On the other hand, longer
-+ can represent up to 800 bytes of data, or 400 uint16 elements, and it
-+ may be empty. Its encoding will include a two byte actual length
-+ field prepended to the vector. The length of an encoded vector must
-+ be an even multiple of the length of a single element (for example, a
-+ 17 byte vector of uint16 would be illegal).
-+
-+ opaque mandatory<300..400>;
-+ /* length field is 2 bytes, cannot be empty */
-+ uint16 longer<0..800>;
-+ /* zero to 400 16-bit unsigned integers */
-+
-+ 4.4. Numbers
-+
-+ The basic numeric data type is an unsigned byte (uint8). All larger
-+ numeric data types are formed from fixed length series of bytes
-+ concatenated as described in Section 4.1 and are also unsigned. The
-+ following numeric types are predefined.
-+
-+ uint8 uint16[2];
-+ uint8 uint24[3];
-+ uint8 uint32[4];
-+ uint8 uint64[8];
-+
-+ All values, here and elsewhere in the specification, are stored in
-+ "network" or "big-endian" order; the uint32 represented by the hex
-+ bytes 01 02 03 04 is equivalent to the decimal value 16909060.
-+
-+ 4.5. Enumerateds
-+
-+ An additional sparse data type is available called enum. A field of
-+ type enum can only assume the values declared in the definition.
-+ Each definition is a different type. Only enumerateds of the same
-+ type may be assigned or compared. Every element of an enumerated must
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 7]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ be assigned a value, as demonstrated in the following example. Since
-+ the elements of the enumerated are not ordered, they can be assigned
-+ any unique value, in any order.
-+
-+ enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;
-+
-+ Enumerateds occupy as much space in the byte stream as would its
-+ maximal defined ordinal value. The following definition would cause
-+ one byte to be used to carry fields of type Color.
-+
-+ enum { red(3), blue(5), white(7) } Color;
-+
-+ One may optionally specify a value without its associated tag to
-+ force the width definition without defining a superfluous element.
-+ In the following example, Taste will consume two bytes in the data
-+ stream but can only assume the values 1, 2 or 4.
-+
-+ enum { sweet(1), sour(2), bitter(4), (32000) } Taste;
-+
-+ The names of the elements of an enumeration are scoped within the
-+ defined type. In the first example, a fully qualified reference to
-+ the second element of the enumeration would be Color.blue. Such
-+ qualification is not required if the target of the assignment is well
-+ specified.
-+
-+ Color color = Color.blue; /* overspecified, legal */
-+ Color color = blue; /* correct, type implicit */
-+
-+ For enumerateds that are never converted to external representation,
-+ the numerical information may be omitted.
-+
-+ enum { low, medium, high } Amount;
-+
-+ 4.6. Constructed types
-+
-+ Structure types may be constructed from primitive types for
-+ convenience. Each specification declares a new, unique type. The
-+ syntax for definition is much like that of C.
-+
-+ struct {
-+ T1 f1;
-+ T2 f2;
-+ ...
-+ Tn fn;
-+ } [[T]];
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 8]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ The fields within a structure may be qualified using the type's name
-+ using a syntax much like that available for enumerateds. For example,
-+ T.f2 refers to the second field of the previous declaration.
-+ Structure definitions may be embedded.
-+
-+ 4.6.1. Variants
-+
-+ Defined structures may have variants based on some knowledge that is
-+ available within the environment. The selector must be an enumerated
-+ type that defines the possible variants the structure defines. There
-+ must be a case arm for every element of the enumeration declared in
-+ the select. The body of the variant structure may be given a label
-+ for reference. The mechanism by which the variant is selected at
-+ runtime is not prescribed by the presentation language.
-+
-+ struct {
-+ T1 f1;
-+ T2 f2;
-+ ....
-+ Tn fn;
-+ select (E) {
-+ case e1: Te1;
-+ case e2: Te2;
-+ ....
-+ case en: Ten;
-+ } [[fv]];
-+ } [[Tv]];
-+
-+ For example:
-+
-+ enum { apple, orange } VariantTag;
-+ struct {
-+ uint16 number;
-+ opaque string<0..10>; /* variable length */
-+ } V1;
-+ struct {
-+ uint32 number;
-+ opaque string[10]; /* fixed length */
-+ } V2;
-+ struct {
-+ select (VariantTag) { /* value of selector is implicit */
-+ case apple: V1; /* VariantBody, tag = apple */
-+ case orange: V2; /* VariantBody, tag = orange */
-+ } variant_body; /* optional label on variant */
-+ } VariantRecord;
-+
-+ Variant structures may be qualified (narrowed) by specifying a value
-+ for the selector prior to the type. For example, a
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 9]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ orange VariantRecord
-+
-+ is a narrowed type of a VariantRecord containing a variant_body of
-+ type V2.
-+
-+ 4.7. Cryptographic attributes
-+
-+ The four cryptographic operations digital signing, stream cipher
-+ encryption, block cipher encryption, and public key encryption are
-+ designated digitally-signed, stream-ciphered, block-ciphered, and
-+ public-key-encrypted, respectively. A field's cryptographic
-+ processing is specified by prepending an appropriate key word
-+ designation before the field's type specification. Cryptographic keys
-+ are implied by the current session state (see Section 6.1).
-+
-+ In digital signing, one-way hash functions are used as input for a
-+ signing algorithm. A digitally-signed element is encoded as an opaque
-+ vector <0..2^16-1>, where the length is specified by the signing
-+ algorithm and key.
-+
-+ In RSA signing, a 36-byte structure of two hashes (one SHA and one
-+ MD5) is signed (encrypted with the private key). It is encoded with
-+ PKCS #1 block type 0 or type 1 as described in [PKCS1].
-+
-+ In DSS, the 20 bytes of the SHA hash are run directly through the
-+ Digital Signing Algorithm with no additional hashing. This produces
-+ two values, r and s. The DSS signature is an opaque vector, as above,
-+ the contents of which are the DER encoding of:
-+
-+ Dss-Sig-Value ::= SEQUENCE {
-+ r INTEGER,
-+ s INTEGER
-+ }
-+
-+ In stream cipher encryption, the plaintext is exclusive-ORed with an
-+ identical amount of output generated from a cryptographically-secure
-+ keyed pseudorandom number generator.
-+
-+ In block cipher encryption, every block of plaintext encrypts to a
-+ block of ciphertext. All block cipher encryption is done in CBC
-+ (Cipher Block Chaining) mode, and all items which are block-ciphered
-+ will be an exact multiple of the cipher block length.
-+
-+ In public key encryption, a public key algorithm is used to encrypt
-+ data in such a way that it can be decrypted only with the matching
-+ private key. A public-key-encrypted element is encoded as an opaque
-+ vector <0..2^16-1>, where the length is specified by the signing
-+ algorithm and key.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 10]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ An RSA encrypted value is encoded with PKCS #1 block type 2 as
-+ described in [PKCS1].
-+
-+ In the following example:
-+
-+ stream-ciphered struct {
-+ uint8 field1;
-+ uint8 field2;
-+ digitally-signed opaque hash[20];
-+ } UserType;
-+
-+ The contents of hash are used as input for the signing algorithm,
-+ then the entire structure is encrypted with a stream cipher. The
-+ length of this structure, in bytes would be equal to 2 bytes for
-+ field1 and field2, plus two bytes for the length of the signature,
-+ plus the length of the output of the signing algorithm. This is known
-+ due to the fact that the algorithm and key used for the signing are
-+ known prior to encoding or decoding this structure.
-+
-+ 4.8. Constants
-+
-+ Typed constants can be defined for purposes of specification by
-+ declaring a symbol of the desired type and assigning values to it.
-+ Under-specified types (opaque, variable length vectors, and
-+ structures that contain opaque) cannot be assigned values. No fields
-+ of a multi-element structure or vector may be elided.
-+
-+ For example,
-+
-+ struct {
-+ uint8 f1;
-+ uint8 f2;
-+ } Example1;
-+
-+ Example1 ex1 = {1, 4}; /* assigns f1 = 1, f2 = 4 */
-+
-+ 5. HMAC and the pseudorandom function
-+
-+ A number of operations in the TLS record and handshake layer required
-+ a keyed MAC; this is a secure digest of some data protected by a
-+ secret. Forging the MAC is infeasible without knowledge of the MAC
-+ secret. The construction we use for this operation is known as HMAC,
-+ described in [HMAC].
-+
-+ HMAC can be used with a variety of different hash algorithms. TLS
-+ uses it in the handshake with two different algorithms: MD5 and SHA-
-+ 1, denoting these as HMAC_MD5(secret, data) and HMAC_SHA(secret,
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 11]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ data). Additional hash algorithms can be defined by cipher suites and
-+ used to protect record data, but MD5 and SHA-1 are hard coded into
-+ the description of the handshaking for this version of the protocol.
-+
-+ In addition, a construction is required to do expansion of secrets
-+ into blocks of data for the purposes of key generation or validation.
-+ This pseudo-random function (PRF) takes as input a secret, a seed,
-+ and an identifying label and produces an output of arbitrary length.
-+
-+ In order to make the PRF as secure as possible, it uses two hash
-+ algorithms in a way which should guarantee its security if either
-+ algorithm remains secure.
-+
-+ First, we define a data expansion function, P_hash(secret, data)
-+ which uses a single hash function to expand a secret and seed into an
-+ arbitrary quantity of output:
-+
-+ P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
-+ HMAC_hash(secret, A(2) + seed) +
-+ HMAC_hash(secret, A(3) + seed) + ...
-+
-+ Where + indicates concatenation.
-+
-+ A() is defined as:
-+ A(0) = seed
-+ A(i) = HMAC_hash(secret, A(i-1))
-+
-+ P_hash can be iterated as many times as is necessary to produce the
-+ required quantity of data. For example, if P_SHA-1 was being used to
-+ create 64 bytes of data, it would have to be iterated 4 times
-+ (through A(4)), creating 80 bytes of output data; the last 16 bytes
-+ of the final iteration would then be discarded, leaving 64 bytes of
-+ output data.
-+
-+ TLS's PRF is created by splitting the secret into two halves and
-+ using one half to generate data with P_MD5 and the other half to
-+ generate data with P_SHA-1, then exclusive-or'ing the outputs of
-+ these two expansion functions together.
-+
-+ S1 and S2 are the two halves of the secret and each is the same
-+ length. S1 is taken from the first half of the secret, S2 from the
-+ second half. Their length is created by rounding up the length of the
-+ overall secret divided by two; thus, if the original secret is an odd
-+ number of bytes long, the last byte of S1 will be the same as the
-+ first byte of S2.
-+
-+ L_S = length in bytes of secret;
-+ L_S1 = L_S2 = ceil(L_S / 2);
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 12]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ The secret is partitioned into two halves (with the possibility of
-+ one shared byte) as described above, S1 taking the first L_S1 bytes
-+ and S2 the last L_S2 bytes.
-+
-+ The PRF is then defined as the result of mixing the two pseudorandom
-+ streams by exclusive-or'ing them together.
-+
-+ PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
-+ P_SHA-1(S2, label + seed);
-+
-+ The label is an ASCII string. It should be included in the exact form
-+ it is given without a length byte or trailing null character. For
-+ example, the label "slithy toves" would be processed by hashing the
-+ following bytes:
-+
-+ 73 6C 69 74 68 79 20 74 6F 76 65 73
-+
-+ Note that because MD5 produces 16 byte outputs and SHA-1 produces 20
-+ byte outputs, the boundaries of their internal iterations will not be
-+ aligned; to generate a 80 byte output will involve P_MD5 being
-+ iterated through A(5), while P_SHA-1 will only iterate through A(4).
-+
-+ 6. The TLS Record Protocol
-+
-+ The TLS Record Protocol is a layered protocol. At each layer,
-+ messages may include fields for length, description, and content.
-+ The Record Protocol takes messages to be transmitted, fragments the
-+ data into manageable blocks, optionally compresses the data, applies
-+ a MAC, encrypts, and transmits the result. Received data is
-+ decrypted, verified, decompressed, and reassembled, then delivered to
-+ higher level clients.
-+
-+ Four record protocol clients are described in this document: the
-+ handshake protocol, the alert protocol, the change cipher spec
-+ protocol, and the application data protocol. In order to allow
-+ extension of the TLS protocol, additional record types can be
-+ supported by the record protocol. Any new record types should
-+ allocate type values immediately beyond the ContentType values for
-+ the four record types described here (see Appendix A.2). If a TLS
-+ implementation receives a record type it does not understand, it
-+ should just ignore it. Any protocol designed for use over TLS must be
-+ carefully designed to deal with all possible attacks against it.
-+ Note that because the type and length of a record are not protected
-+ by encryption, care should be take to minimize the value of traffic
-+ analysis of these values.
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 13]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 6.1. Connection states
-+
-+ A TLS connection state is the operating environment of the TLS Record
-+ Protocol. It specifies a compression algorithm, encryption algorithm,
-+ and MAC algorithm. In addition, the parameters for these algorithms
-+ are known: the MAC secret and the bulk encryption keys and IVs for
-+ the connection in both the read and the write directions. Logically,
-+ there are always four connection states outstanding: the current read
-+ and write states, and the pending read and write states. All records
-+ are processed under the current read and write states. The security
-+ parameters for the pending states can be set by the TLS Handshake
-+ Protocol, and the Handshake Protocol can selectively make either of
-+ the pending states current, in which case the appropriate current
-+ state is disposed of and replaced with the pending state; the pending
-+ state is then reinitialized to an empty state. It is illegal to make
-+ a state which has not been initialized with security parameters a
-+ current state. The initial current state always specifies that no
-+ encryption, compression, or MAC will be used.
-+
-+ The security parameters for a TLS Connection read and write state are
-+ set by providing the following values:
-+
-+ connection end
-+ Whether this entity is considered the "client" or the "server" in
-+ this connection.
-+
-+ bulk encryption algorithm
-+ An algorithm to be used for bulk encryption. This specification
-+ includes the key size of this algorithm, how much of that key is
-+ secret, whether it is a block or stream cipher, the block size of
-+ the cipher (if appropriate), and whether it is considered an
-+ "export" cipher.
-+
-+ MAC algorithm
-+ An algorithm to be used for message authentication. This
-+ specification includes the size of the hash which is returned by
-+ the MAC algorithm.
-+
-+ compression algorithm
-+ An algorithm to be used for data compression. This specification
-+ must include all information the algorithm requires to do
-+ compression.
-+
-+ master secret
-+ A 48 byte secret shared between the two peers in the connection.
-+
-+ client random
-+ A 32 byte value provided by the client.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 14]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ server random
-+ A 32 byte value provided by the server.
-+
-+ These parameters are defined in the presentation language as:
-+
-+ enum { server, client } ConnectionEnd;
-+
-+ enum { null, rc4, rc2, des, 3des, des40 } BulkCipherAlgorithm;
-+
-+ enum { stream, block } CipherType;
-+
-+ enum { true, false } IsExportable;
-+
-+ enum { null, md5, sha } MACAlgorithm;
-+
-+ enum { null(0), (255) } CompressionMethod;
-+
-+ /* The algorithms specified in CompressionMethod,
-+ BulkCipherAlgorithm, and MACAlgorithm may be added to. */
-+
-+ struct {
-+ ConnectionEnd entity;
-+ BulkCipherAlgorithm bulk_cipher_algorithm;
-+ CipherType cipher_type;
-+ uint8 key_size;
-+ uint8 key_material_length;
-+ IsExportable is_exportable;
-+ MACAlgorithm mac_algorithm;
-+ uint8 hash_size;
-+ CompressionMethod compression_algorithm;
-+ opaque master_secret[48];
-+ opaque client_random[32];
-+ opaque server_random[32];
-+ } SecurityParameters;
-+
-+ The record layer will use the security parameters to generate the
-+ following six items:
-+
-+ client write MAC secret
-+ server write MAC secret
-+ client write key
-+ server write key
-+ client write IV (for block ciphers only)
-+ server write IV (for block ciphers only)
-+
-+ The client write parameters are used by the server when receiving and
-+ processing records and vice-versa. The algorithm used for generating
-+ these items from the security parameters is described in section 6.3.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 15]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Once the security parameters have been set and the keys have been
-+ generated, the connection states can be instantiated by making them
-+ the current states. These current states must be updated for each
-+ record processed. Each connection state includes the following
-+ elements:
-+
-+ compression state
-+ The current state of the compression algorithm.
-+
-+ cipher state
-+ The current state of the encryption algorithm. This will consist
-+ of the scheduled key for that connection. In addition, for block
-+ ciphers running in CBC mode (the only mode specified for TLS),
-+ this will initially contain the IV for that connection state and
-+ be updated to contain the ciphertext of the last block encrypted
-+ or decrypted as records are processed. For stream ciphers, this
-+ will contain whatever the necessary state information is to allow
-+ the stream to continue to encrypt or decrypt data.
-+
-+ MAC secret
-+ The MAC secret for this connection as generated above.
-+
-+ sequence number
-+ Each connection state contains a sequence number, which is
-+ maintained separately for read and write states. The sequence
-+ number must be set to zero whenever a connection state is made
-+ the active state. Sequence numbers are of type uint64 and may not
-+ exceed 2^64-1. A sequence number is incremented after each
-+ record: specifically, the first record which is transmitted under
-+ a particular connection state should use sequence number 0.
-+
-+ 6.2. Record layer
-+
-+ The TLS Record Layer receives uninterpreted data from higher layers
-+ in non-empty blocks of arbitrary size.
-+
-+ 6.2.1. Fragmentation
-+
-+ The record layer fragments information blocks into TLSPlaintext
-+ records carrying data in chunks of 2^14 bytes or less. Client message
-+ boundaries are not preserved in the record layer (i.e., multiple
-+ client messages of the same ContentType may be coalesced into a
-+ single TLSPlaintext record, or a single message may be fragmented
-+ across several records).
-+
-+ struct {
-+ uint8 major, minor;
-+ } ProtocolVersion;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 16]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ enum {
-+ change_cipher_spec(20), alert(21), handshake(22),
-+ application_data(23), (255)
-+ } ContentType;
-+
-+ struct {
-+ ContentType type;
-+ ProtocolVersion version;
-+ uint16 length;
-+ opaque fragment[TLSPlaintext.length];
-+ } TLSPlaintext;
-+
-+ type
-+ The higher level protocol used to process the enclosed fragment.
-+
-+ version
-+ The version of the protocol being employed. This document
-+ describes TLS Version 1.0, which uses the version { 3, 1 }. The
-+ version value 3.1 is historical: TLS version 1.0 is a minor
-+ modification to the SSL 3.0 protocol, which bears the version
-+ value 3.0. (See Appendix A.1).
-+
-+ length
-+ The length (in bytes) of the following TLSPlaintext.fragment.
-+ The length should not exceed 2^14.
-+
-+ fragment
-+ The application data. This data is transparent and treated as an
-+ independent block to be dealt with by the higher level protocol
-+ specified by the type field.
-+
-+ Note: Data of different TLS Record layer content types may be
-+ interleaved. Application data is generally of lower precedence
-+ for transmission than other content types.
-+
-+ 6.2.2. Record compression and decompression
-+
-+ All records are compressed using the compression algorithm defined in
-+ the current session state. There is always an active compression
-+ algorithm; however, initially it is defined as
-+ CompressionMethod.null. The compression algorithm translates a
-+ TLSPlaintext structure into a TLSCompressed structure. Compression
-+ functions are initialized with default state information whenever a
-+ connection state is made active.
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 17]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Compression must be lossless and may not increase the content length
-+ by more than 1024 bytes. If the decompression function encounters a
-+ TLSCompressed.fragment that would decompress to a length in excess of
-+ 2^14 bytes, it should report a fatal decompression failure error.
-+
-+ struct {
-+ ContentType type; /* same as TLSPlaintext.type */
-+ ProtocolVersion version;/* same as TLSPlaintext.version */
-+ uint16 length;
-+ opaque fragment[TLSCompressed.length];
-+ } TLSCompressed;
-+
-+ length
-+ The length (in bytes) of the following TLSCompressed.fragment.
-+ The length should not exceed 2^14 + 1024.
-+
-+ fragment
-+ The compressed form of TLSPlaintext.fragment.
-+
-+ Note: A CompressionMethod.null operation is an identity operation; no
-+ fields are altered.
-+
-+ Implementation note:
-+ Decompression functions are responsible for ensuring that
-+ messages cannot cause internal buffer overflows.
-+
-+ 6.2.3. Record payload protection
-+
-+ The encryption and MAC functions translate a TLSCompressed structure
-+ into a TLSCiphertext. The decryption functions reverse the process.
-+ The MAC of the record also includes a sequence number so that
-+ missing, extra or repeated messages are detectable.
-+
-+ struct {
-+ ContentType type;
-+ ProtocolVersion version;
-+ uint16 length;
-+ select (CipherSpec.cipher_type) {
-+ case stream: GenericStreamCipher;
-+ case block: GenericBlockCipher;
-+ } fragment;
-+ } TLSCiphertext;
-+
-+ type
-+ The type field is identical to TLSCompressed.type.
-+
-+ version
-+ The version field is identical to TLSCompressed.version.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 18]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ length
-+ The length (in bytes) of the following TLSCiphertext.fragment.
-+ The length may not exceed 2^14 + 2048.
-+
-+ fragment
-+ The encrypted form of TLSCompressed.fragment, with the MAC.
-+
-+ 6.2.3.1. Null or standard stream cipher
-+
-+ Stream ciphers (including BulkCipherAlgorithm.null - see Appendix
-+ A.6) convert TLSCompressed.fragment structures to and from stream
-+ TLSCiphertext.fragment structures.
-+
-+ stream-ciphered struct {
-+ opaque content[TLSCompressed.length];
-+ opaque MAC[CipherSpec.hash_size];
-+ } GenericStreamCipher;
-+
-+ The MAC is generated as:
-+
-+ HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
-+ TLSCompressed.version + TLSCompressed.length +
-+ TLSCompressed.fragment));
-+
-+ where "+" denotes concatenation.
-+
-+ seq_num
-+ The sequence number for this record.
-+
-+ hash
-+ The hashing algorithm specified by
-+ SecurityParameters.mac_algorithm.
-+
-+ Note that the MAC is computed before encryption. The stream cipher
-+ encrypts the entire block, including the MAC. For stream ciphers that
-+ do not use a synchronization vector (such as RC4), the stream cipher
-+ state from the end of one record is simply used on the subsequent
-+ packet. If the CipherSuite is TLS_NULL_WITH_NULL_NULL, encryption
-+ consists of the identity operation (i.e., the data is not encrypted
-+ and the MAC size is zero implying that no MAC is used).
-+ TLSCiphertext.length is TLSCompressed.length plus
-+ CipherSpec.hash_size.
-+
-+ 6.2.3.2. CBC block cipher
-+
-+ For block ciphers (such as RC2 or DES), the encryption and MAC
-+ functions convert TLSCompressed.fragment structures to and from block
-+ TLSCiphertext.fragment structures.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 19]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ block-ciphered struct {
-+ opaque content[TLSCompressed.length];
-+ opaque MAC[CipherSpec.hash_size];
-+ uint8 padding[GenericBlockCipher.padding_length];
-+ uint8 padding_length;
-+ } GenericBlockCipher;
-+
-+ The MAC is generated as described in Section 6.2.3.1.
-+
-+ padding
-+ Padding that is added to force the length of the plaintext to be
-+ an integral multiple of the block cipher's block length. The
-+ padding may be any length up to 255 bytes long, as long as it
-+ results in the TLSCiphertext.length being an integral multiple of
-+ the block length. Lengths longer than necessary might be
-+ desirable to frustrate attacks on a protocol based on analysis of
-+ the lengths of exchanged messages. Each uint8 in the padding data
-+ vector must be filled with the padding length value.
-+
-+ padding_length
-+ The padding length should be such that the total size of the
-+ GenericBlockCipher structure is a multiple of the cipher's block
-+ length. Legal values range from zero to 255, inclusive. This
-+ length specifies the length of the padding field exclusive of the
-+ padding_length field itself.
-+
-+ The encrypted data length (TLSCiphertext.length) is one more than the
-+ sum of TLSCompressed.length, CipherSpec.hash_size, and
-+ padding_length.
-+
-+ Example: If the block length is 8 bytes, the content length
-+ (TLSCompressed.length) is 61 bytes, and the MAC length is 20
-+ bytes, the length before padding is 82 bytes. Thus, the
-+ padding length modulo 8 must be equal to 6 in order to make
-+ the total length an even multiple of 8 bytes (the block
-+ length). The padding length can be 6, 14, 22, and so on,
-+ through 254. If the padding length were the minimum necessary,
-+ 6, the padding would be 6 bytes, each containing the value 6.
-+ Thus, the last 8 octets of the GenericBlockCipher before block
-+ encryption would be xx 06 06 06 06 06 06 06, where xx is the
-+ last octet of the MAC.
-+
-+ Note: With block ciphers in CBC mode (Cipher Block Chaining) the
-+ initialization vector (IV) for the first record is generated with
-+ the other keys and secrets when the security parameters are set.
-+ The IV for subsequent records is the last ciphertext block from
-+ the previous record.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 20]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 6.3. Key calculation
-+
-+ The Record Protocol requires an algorithm to generate keys, IVs, and
-+ MAC secrets from the security parameters provided by the handshake
-+ protocol.
-+
-+ The master secret is hashed into a sequence of secure bytes, which
-+ are assigned to the MAC secrets, keys, and non-export IVs required by
-+ the current connection state (see Appendix A.6). CipherSpecs require
-+ a client write MAC secret, a server write MAC secret, a client write
-+ key, a server write key, a client write IV, and a server write IV,
-+ which are generated from the master secret in that order. Unused
-+ values are empty.
-+
-+ When generating keys and MAC secrets, the master secret is used as an
-+ entropy source, and the random values provide unencrypted salt
-+ material and IVs for exportable ciphers.
-+
-+ To generate the key material, compute
-+
-+ key_block = PRF(SecurityParameters.master_secret,
-+ "key expansion",
-+ SecurityParameters.server_random +
-+ SecurityParameters.client_random);
-+
-+ until enough output has been generated. Then the key_block is
-+ partitioned as follows:
-+
-+ client_write_MAC_secret[SecurityParameters.hash_size]
-+ server_write_MAC_secret[SecurityParameters.hash_size]
-+ client_write_key[SecurityParameters.key_material_length]
-+ server_write_key[SecurityParameters.key_material_length]
-+ client_write_IV[SecurityParameters.IV_size]
-+ server_write_IV[SecurityParameters.IV_size]
-+
-+ The client_write_IV and server_write_IV are only generated for non-
-+ export block ciphers. For exportable block ciphers, the
-+ initialization vectors are generated later, as described below. Any
-+ extra key_block material is discarded.
-+
-+ Implementation note:
-+ The cipher spec which is defined in this document which requires
-+ the most material is 3DES_EDE_CBC_SHA: it requires 2 x 24 byte
-+ keys, 2 x 20 byte MAC secrets, and 2 x 8 byte IVs, for a total of
-+ 104 bytes of key material.
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 21]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Exportable encryption algorithms (for which CipherSpec.is_exportable
-+ is true) require additional processing as follows to derive their
-+ final write keys:
-+
-+ final_client_write_key =
-+ PRF(SecurityParameters.client_write_key,
-+ "client write key",
-+ SecurityParameters.client_random +
-+ SecurityParameters.server_random);
-+ final_server_write_key =
-+ PRF(SecurityParameters.server_write_key,
-+ "server write key",
-+ SecurityParameters.client_random +
-+ SecurityParameters.server_random);
-+
-+ Exportable encryption algorithms derive their IVs solely from the
-+ random values from the hello messages:
-+
-+ iv_block = PRF("", "IV block", SecurityParameters.client_random +
-+ SecurityParameters.server_random);
-+
-+ The iv_block is partitioned into two initialization vectors as the
-+ key_block was above:
-+
-+ client_write_IV[SecurityParameters.IV_size]
-+ server_write_IV[SecurityParameters.IV_size]
-+
-+ Note that the PRF is used without a secret in this case: this just
-+ means that the secret has a length of zero bytes and contributes
-+ nothing to the hashing in the PRF.
-+
-+ 6.3.1. Export key generation example
-+
-+ TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 requires five random bytes for
-+ each of the two encryption keys and 16 bytes for each of the MAC
-+ keys, for a total of 42 bytes of key material. The PRF output is
-+ stored in the key_block. The key_block is partitioned, and the write
-+ keys are salted because this is an exportable encryption algorithm.
-+
-+ key_block = PRF(master_secret,
-+ "key expansion",
-+ server_random +
-+ client_random)[0..41]
-+ client_write_MAC_secret = key_block[0..15]
-+ server_write_MAC_secret = key_block[16..31]
-+ client_write_key = key_block[32..36]
-+ server_write_key = key_block[37..41]
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 22]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ final_client_write_key = PRF(client_write_key,
-+ "client write key",
-+ client_random +
-+ server_random)[0..15]
-+ final_server_write_key = PRF(server_write_key,
-+ "server write key",
-+ client_random +
-+ server_random)[0..15]
-+
-+ iv_block = PRF("", "IV block", client_random +
-+ server_random)[0..15]
-+ client_write_IV = iv_block[0..7]
-+ server_write_IV = iv_block[8..15]
-+
-+ 7. The TLS Handshake Protocol
-+
-+ The TLS Handshake Protocol consists of a suite of three sub-protocols
-+ which are used to allow peers to agree upon security parameters for
-+ the record layer, authenticate themselves, instantiate negotiated
-+ security parameters, and report error conditions to each other.
-+
-+ The Handshake Protocol is responsible for negotiating a session,
-+ which consists of the following items:
-+
-+ session identifier
-+ An arbitrary byte sequence chosen by the server to identify an
-+ active or resumable session state.
-+
-+ peer certificate
-+ X509v3 [X509] certificate of the peer. This element of the state
-+ may be null.
-+
-+ compression method
-+ The algorithm used to compress data prior to encryption.
-+
-+ cipher spec
-+ Specifies the bulk data encryption algorithm (such as null, DES,
-+ etc.) and a MAC algorithm (such as MD5 or SHA). It also defines
-+ cryptographic attributes such as the hash_size. (See Appendix A.6
-+ for formal definition)
-+
-+ master secret
-+ 48-byte secret shared between the client and server.
-+
-+ is resumable
-+ A flag indicating whether the session can be used to initiate new
-+ connections.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 23]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ These items are then used to create security parameters for use by
-+ the Record Layer when protecting application data. Many connections
-+ can be instantiated using the same session through the resumption
-+ feature of the TLS Handshake Protocol.
-+
-+ 7.1. Change cipher spec protocol
-+
-+ The change cipher spec protocol exists to signal transitions in
-+ ciphering strategies. The protocol consists of a single message,
-+ which is encrypted and compressed under the current (not the pending)
-+ connection state. The message consists of a single byte of value 1.
-+
-+ struct {
-+ enum { change_cipher_spec(1), (255) } type;
-+ } ChangeCipherSpec;
-+
-+ The change cipher spec message is sent by both the client and server
-+ to notify the receiving party that subsequent records will be
-+ protected under the newly negotiated CipherSpec and keys. Reception
-+ of this message causes the receiver to instruct the Record Layer to
-+ immediately copy the read pending state into the read current state.
-+ Immediately after sending this message, the sender should instruct
-+ the record layer to make the write pending state the write active
-+ state. (See section 6.1.) The change cipher spec message is sent
-+ during the handshake after the security parameters have been agreed
-+ upon, but before the verifying finished message is sent (see section
-+ 7.4.9).
-+
-+ 7.2. Alert protocol
-+
-+ One of the content types supported by the TLS Record layer is the
-+ alert type. Alert messages convey the severity of the message and a
-+ description of the alert. Alert messages with a level of fatal result
-+ in the immediate termination of the connection. In this case, other
-+ connections corresponding to the session may continue, but the
-+ session identifier must be invalidated, preventing the failed session
-+ from being used to establish new connections. Like other messages,
-+ alert messages are encrypted and compressed, as specified by the
-+ current connection state.
-+
-+ enum { warning(1), fatal(2), (255) } AlertLevel;
-+
-+ enum {
-+ close_notify(0),
-+ unexpected_message(10),
-+ bad_record_mac(20),
-+ decryption_failed(21),
-+ record_overflow(22),
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 24]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ decompression_failure(30),
-+ handshake_failure(40),
-+ bad_certificate(42),
-+ unsupported_certificate(43),
-+ certificate_revoked(44),
-+ certificate_expired(45),
-+ certificate_unknown(46),
-+ illegal_parameter(47),
-+ unknown_ca(48),
-+ access_denied(49),
-+ decode_error(50),
-+ decrypt_error(51),
-+ export_restriction(60),
-+ protocol_version(70),
-+ insufficient_security(71),
-+ internal_error(80),
-+ user_canceled(90),
-+ no_renegotiation(100),
-+ (255)
-+ } AlertDescription;
-+
-+ struct {
-+ AlertLevel level;
-+ AlertDescription description;
-+ } Alert;
-+
-+ 7.2.1. Closure alerts
-+
-+ The client and the server must share knowledge that the connection is
-+ ending in order to avoid a truncation attack. Either party may
-+ initiate the exchange of closing messages.
-+
-+ close_notify
-+ This message notifies the recipient that the sender will not send
-+ any more messages on this connection. The session becomes
-+ unresumable if any connection is terminated without proper
-+ close_notify messages with level equal to warning.
-+
-+ Either party may initiate a close by sending a close_notify alert.
-+ Any data received after a closure alert is ignored.
-+
-+ Each party is required to send a close_notify alert before closing
-+ the write side of the connection. It is required that the other party
-+ respond with a close_notify alert of its own and close down the
-+ connection immediately, discarding any pending writes. It is not
-+ required for the initiator of the close to wait for the responding
-+ close_notify alert before closing the read side of the connection.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 25]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ If the application protocol using TLS provides that any data may be
-+ carried over the underlying transport after the TLS connection is
-+ closed, the TLS implementation must receive the responding
-+ close_notify alert before indicating to the application layer that
-+ the TLS connection has ended. If the application protocol will not
-+ transfer any additional data, but will only close the underlying
-+ transport connection, then the implementation may choose to close the
-+ transport without waiting for the responding close_notify. No part of
-+ this standard should be taken to dictate the manner in which a usage
-+ profile for TLS manages its data transport, including when
-+ connections are opened or closed.
-+
-+ NB: It is assumed that closing a connection reliably delivers
-+ pending data before destroying the transport.
-+
-+ 7.2.2. Error alerts
-+
-+ Error handling in the TLS Handshake protocol is very simple. When an
-+ error is detected, the detecting party sends a message to the other
-+ party. Upon transmission or receipt of an fatal alert message, both
-+ parties immediately close the connection. Servers and clients are
-+ required to forget any session-identifiers, keys, and secrets
-+ associated with a failed connection. The following error alerts are
-+ defined:
-+
-+ unexpected_message
-+ An inappropriate message was received. This alert is always fatal
-+ and should never be observed in communication between proper
-+ implementations.
-+
-+ bad_record_mac
-+ This alert is returned if a record is received with an incorrect
-+ MAC. This message is always fatal.
-+
-+ decryption_failed
-+ A TLSCiphertext decrypted in an invalid way: either it wasn`t an
-+ even multiple of the block length or its padding values, when
-+ checked, weren`t correct. This message is always fatal.
-+
-+ record_overflow
-+ A TLSCiphertext record was received which had a length more than
-+ 2^14+2048 bytes, or a record decrypted to a TLSCompressed record
-+ with more than 2^14+1024 bytes. This message is always fatal.
-+
-+ decompression_failure
-+ The decompression function received improper input (e.g. data
-+ that would expand to excessive length). This message is always
-+ fatal.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 26]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ handshake_failure
-+ Reception of a handshake_failure alert message indicates that the
-+ sender was unable to negotiate an acceptable set of security
-+ parameters given the options available. This is a fatal error.
-+
-+ bad_certificate
-+ A certificate was corrupt, contained signatures that did not
-+ verify correctly, etc.
-+
-+ unsupported_certificate
-+ A certificate was of an unsupported type.
-+
-+ certificate_revoked
-+ A certificate was revoked by its signer.
-+
-+ certificate_expired
-+ A certificate has expired or is not currently valid.
-+
-+ certificate_unknown
-+ Some other (unspecified) issue arose in processing the
-+ certificate, rendering it unacceptable.
-+
-+ illegal_parameter
-+ A field in the handshake was out of range or inconsistent with
-+ other fields. This is always fatal.
-+
-+ unknown_ca
-+ A valid certificate chain or partial chain was received, but the
-+ certificate was not accepted because the CA certificate could not
-+ be located or couldn`t be matched with a known, trusted CA. This
-+ message is always fatal.
-+
-+ access_denied
-+ A valid certificate was received, but when access control was
-+ applied, the sender decided not to proceed with negotiation.
-+ This message is always fatal.
-+
-+ decode_error
-+ A message could not be decoded because some field was out of the
-+ specified range or the length of the message was incorrect. This
-+ message is always fatal.
-+
-+ decrypt_error
-+ A handshake cryptographic operation failed, including being
-+ unable to correctly verify a signature, decrypt a key exchange,
-+ or validate a finished message.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 27]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ export_restriction
-+ A negotiation not in compliance with export restrictions was
-+ detected; for example, attempting to transfer a 1024 bit
-+ ephemeral RSA key for the RSA_EXPORT handshake method. This
-+ message is always fatal.
-+
-+ protocol_version
-+ The protocol version the client has attempted to negotiate is
-+ recognized, but not supported. (For example, old protocol
-+ versions might be avoided for security reasons). This message is
-+ always fatal.
-+
-+ insufficient_security
-+ Returned instead of handshake_failure when a negotiation has
-+ failed specifically because the server requires ciphers more
-+ secure than those supported by the client. This message is always
-+ fatal.
-+
-+ internal_error
-+ An internal error unrelated to the peer or the correctness of the
-+ protocol makes it impossible to continue (such as a memory
-+ allocation failure). This message is always fatal.
-+
-+ user_canceled
-+ This handshake is being canceled for some reason unrelated to a
-+ protocol failure. If the user cancels an operation after the
-+ handshake is complete, just closing the connection by sending a
-+ close_notify is more appropriate. This alert should be followed
-+ by a close_notify. This message is generally a warning.
-+
-+ no_renegotiation
-+ Sent by the client in response to a hello request or by the
-+ server in response to a client hello after initial handshaking.
-+ Either of these would normally lead to renegotiation; when that
-+ is not appropriate, the recipient should respond with this alert;
-+ at that point, the original requester can decide whether to
-+ proceed with the connection. One case where this would be
-+ appropriate would be where a server has spawned a process to
-+ satisfy a request; the process might receive security parameters
-+ (key length, authentication, etc.) at startup and it might be
-+ difficult to communicate changes to these parameters after that
-+ point. This message is always a warning.
-+
-+ For all errors where an alert level is not explicitly specified, the
-+ sending party may determine at its discretion whether this is a fatal
-+ error or not; if an alert with a level of warning is received, the
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 28]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ receiving party may decide at its discretion whether to treat this as
-+ a fatal error or not. However, all messages which are transmitted
-+ with a level of fatal must be treated as fatal messages.
-+
-+ 7.3. Handshake Protocol overview
-+
-+ The cryptographic parameters of the session state are produced by the
-+ TLS Handshake Protocol, which operates on top of the TLS Record
-+ Layer. When a TLS client and server first start communicating, they
-+ agree on a protocol version, select cryptographic algorithms,
-+ optionally authenticate each other, and use public-key encryption
-+ techniques to generate shared secrets.
-+
-+ The TLS Handshake Protocol involves the following steps:
-+
-+ - Exchange hello messages to agree on algorithms, exchange random
-+ values, and check for session resumption.
-+
-+ - Exchange the necessary cryptographic parameters to allow the
-+ client and server to agree on a premaster secret.
-+
-+ - Exchange certificates and cryptographic information to allow the
-+ client and server to authenticate themselves.
-+
-+ - Generate a master secret from the premaster secret and exchanged
-+ random values.
-+
-+ - Provide security parameters to the record layer.
-+
-+ - Allow the client and server to verify that their peer has
-+ calculated the same security parameters and that the handshake
-+ occurred without tampering by an attacker.
-+
-+ Note that higher layers should not be overly reliant on TLS always
-+ negotiating the strongest possible connection between two peers:
-+ there are a number of ways a man in the middle attacker can attempt
-+ to make two entities drop down to the least secure method they
-+ support. The protocol has been designed to minimize this risk, but
-+ there are still attacks available: for example, an attacker could
-+ block access to the port a secure service runs on, or attempt to get
-+ the peers to negotiate an unauthenticated connection. The fundamental
-+ rule is that higher levels must be cognizant of what their security
-+ requirements are and never transmit information over a channel less
-+ secure than what they require. The TLS protocol is secure, in that
-+ any cipher suite offers its promised level of security: if you
-+ negotiate 3DES with a 1024 bit RSA key exchange with a host whose
-+ certificate you have verified, you can expect to be that secure.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 29]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ However, you should never send data over a link encrypted with 40 bit
-+ security unless you feel that data is worth no more than the effort
-+ required to break that encryption.
-+
-+ These goals are achieved by the handshake protocol, which can be
-+ summarized as follows: The client sends a client hello message to
-+ which the server must respond with a server hello message, or else a
-+ fatal error will occur and the connection will fail. The client hello
-+ and server hello are used to establish security enhancement
-+ capabilities between client and server. The client hello and server
-+ hello establish the following attributes: Protocol Version, Session
-+ ID, Cipher Suite, and Compression Method. Additionally, two random
-+ values are generated and exchanged: ClientHello.random and
-+ ServerHello.random.
-+
-+ The actual key exchange uses up to four messages: the server
-+ certificate, the server key exchange, the client certificate, and the
-+ client key exchange. New key exchange methods can be created by
-+ specifying a format for these messages and defining the use of the
-+ messages to allow the client and server to agree upon a shared
-+ secret. This secret should be quite long; currently defined key
-+ exchange methods exchange secrets which range from 48 to 128 bytes in
-+ length.
-+
-+ Following the hello messages, the server will send its certificate,
-+ if it is to be authenticated. Additionally, a server key exchange
-+ message may be sent, if it is required (e.g. if their server has no
-+ certificate, or if its certificate is for signing only). If the
-+ server is authenticated, it may request a certificate from the
-+ client, if that is appropriate to the cipher suite selected. Now the
-+ server will send the server hello done message, indicating that the
-+ hello-message phase of the handshake is complete. The server will
-+ then wait for a client response. If the server has sent a certificate
-+ request message, the client must send the certificate message. The
-+ client key exchange message is now sent, and the content of that
-+ message will depend on the public key algorithm selected between the
-+ client hello and the server hello. If the client has sent a
-+ certificate with signing ability, a digitally-signed certificate
-+ verify message is sent to explicitly verify the certificate.
-+
-+ At this point, a change cipher spec message is sent by the client,
-+ and the client copies the pending Cipher Spec into the current Cipher
-+ Spec. The client then immediately sends the finished message under
-+ the new algorithms, keys, and secrets. In response, the server will
-+ send its own change cipher spec message, transfer the pending to the
-+ current Cipher Spec, and send its finished message under the new
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 30]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Cipher Spec. At this point, the handshake is complete and the client
-+ and server may begin to exchange application layer data. (See flow
-+ chart below.)
-+
-+ Client Server
-+
-+ ClientHello -------->
-+ ServerHello
-+ Certificate*
-+ ServerKeyExchange*
-+ CertificateRequest*
-+ <-------- ServerHelloDone
-+ Certificate*
-+ ClientKeyExchange
-+ CertificateVerify*
-+ [ChangeCipherSpec]
-+ Finished -------->
-+ [ChangeCipherSpec]
-+ <-------- Finished
-+ Application Data <-------> Application Data
-+
-+ Fig. 1 - Message flow for a full handshake
-+
-+ * Indicates optional or situation-dependent messages that are not
-+ always sent.
-+
-+ Note: To help avoid pipeline stalls, ChangeCipherSpec is an
-+ independent TLS Protocol content type, and is not actually a TLS
-+ handshake message.
-+
-+ When the client and server decide to resume a previous session or
-+ duplicate an existing session (instead of negotiating new security
-+ parameters) the message flow is as follows:
-+
-+ The client sends a ClientHello using the Session ID of the session to
-+ be resumed. The server then checks its session cache for a match. If
-+ a match is found, and the server is willing to re-establish the
-+ connection under the specified session state, it will send a
-+ ServerHello with the same Session ID value. At this point, both
-+ client and server must send change cipher spec messages and proceed
-+ directly to finished messages. Once the re-establishment is complete,
-+ the client and server may begin to exchange application layer data.
-+ (See flow chart below.) If a Session ID match is not found, the
-+ server generates a new session ID and the TLS client and server
-+ perform a full handshake.
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 31]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Client Server
-+
-+ ClientHello -------->
-+ ServerHello
-+ [ChangeCipherSpec]
-+ <-------- Finished
-+ [ChangeCipherSpec]
-+ Finished -------->
-+ Application Data <-------> Application Data
-+
-+ Fig. 2 - Message flow for an abbreviated handshake
-+
-+ The contents and significance of each message will be presented in
-+ detail in the following sections.
-+
-+ 7.4. Handshake protocol
-+
-+ The TLS Handshake Protocol is one of the defined higher level clients
-+ of the TLS Record Protocol. This protocol is used to negotiate the
-+ secure attributes of a session. Handshake messages are supplied to
-+ the TLS Record Layer, where they are encapsulated within one or more
-+ TLSPlaintext structures, which are processed and transmitted as
-+ specified by the current active session state.
-+
-+ enum {
-+ hello_request(0), client_hello(1), server_hello(2),
-+ certificate(11), server_key_exchange (12),
-+ certificate_request(13), server_hello_done(14),
-+ certificate_verify(15), client_key_exchange(16),
-+ finished(20), (255)
-+ } HandshakeType;
-+
-+ struct {
-+ HandshakeType msg_type; /* handshake type */
-+ uint24 length; /* bytes in message */
-+ select (HandshakeType) {
-+ case hello_request: HelloRequest;
-+ case client_hello: ClientHello;
-+ case server_hello: ServerHello;
-+ case certificate: Certificate;
-+ case server_key_exchange: ServerKeyExchange;
-+ case certificate_request: CertificateRequest;
-+ case server_hello_done: ServerHelloDone;
-+ case certificate_verify: CertificateVerify;
-+ case client_key_exchange: ClientKeyExchange;
-+ case finished: Finished;
-+ } body;
-+ } Handshake;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 32]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ The handshake protocol messages are presented below in the order they
-+ must be sent; sending handshake messages in an unexpected order
-+ results in a fatal error. Unneeded handshake messages can be omitted,
-+ however. Note one exception to the ordering: the Certificate message
-+ is used twice in the handshake (from server to client, then from
-+ client to server), but described only in its first position. The one
-+ message which is not bound by these ordering rules in the Hello
-+ Request message, which can be sent at any time, but which should be
-+ ignored by the client if it arrives in the middle of a handshake.
-+
-+ 7.4.1. Hello messages
-+
-+ The hello phase messages are used to exchange security enhancement
-+ capabilities between the client and server. When a new session
-+ begins, the Record Layer's connection state encryption, hash, and
-+ compression algorithms are initialized to null. The current
-+ connection state is used for renegotiation messages.
-+
-+ 7.4.1.1. Hello request
-+
-+ When this message will be sent:
-+ The hello request message may be sent by the server at any time.
-+
-+ Meaning of this message:
-+ Hello request is a simple notification that the client should
-+ begin the negotiation process anew by sending a client hello
-+ message when convenient. This message will be ignored by the
-+ client if the client is currently negotiating a session. This
-+ message may be ignored by the client if it does not wish to
-+ renegotiate a session, or the client may, if it wishes, respond
-+ with a no_renegotiation alert. Since handshake messages are
-+ intended to have transmission precedence over application data,
-+ it is expected that the negotiation will begin before no more
-+ than a few records are received from the client. If the server
-+ sends a hello request but does not receive a client hello in
-+ response, it may close the connection with a fatal alert.
-+
-+ After sending a hello request, servers should not repeat the request
-+ until the subsequent handshake negotiation is complete.
-+
-+ Structure of this message:
-+ struct { } HelloRequest;
-+
-+ Note: This message should never be included in the message hashes which
-+ are maintained throughout the handshake and used in the finished
-+ messages and the certificate verify message.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 33]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 7.4.1.2. Client hello
-+
-+ When this message will be sent:
-+ When a client first connects to a server it is required to send
-+ the client hello as its first message. The client can also send a
-+ client hello in response to a hello request or on its own
-+ initiative in order to renegotiate the security parameters in an
-+ existing connection.
-+
-+ Structure of this message:
-+ The client hello message includes a random structure, which is
-+ used later in the protocol.
-+
-+ struct {
-+ uint32 gmt_unix_time;
-+ opaque random_bytes[28];
-+ } Random;
-+
-+ gmt_unix_time
-+ The current time and date in standard UNIX 32-bit format (seconds
-+ since the midnight starting Jan 1, 1970, GMT) according to the
-+ sender's internal clock. Clocks are not required to be set
-+ correctly by the basic TLS Protocol; higher level or application
-+ protocols may define additional requirements.
-+
-+ random_bytes
-+ 28 bytes generated by a secure random number generator.
-+
-+ The client hello message includes a variable length session
-+ identifier. If not empty, the value identifies a session between the
-+ same client and server whose security parameters the client wishes to
-+ reuse. The session identifier may be from an earlier connection, this
-+ connection, or another currently active connection. The second option
-+ is useful if the client only wishes to update the random structures
-+ and derived values of a connection, while the third option makes it
-+ possible to establish several independent secure connections without
-+ repeating the full handshake protocol. These independent connections
-+ may occur sequentially or simultaneously; a SessionID becomes valid
-+ when the handshake negotiating it completes with the exchange of
-+ Finished messages and persists until removed due to aging or because
-+ a fatal error was encountered on a connection associated with the
-+ session. The actual contents of the SessionID are defined by the
-+ server.
-+
-+ opaque SessionID<0..32>;
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 34]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Warning:
-+ Because the SessionID is transmitted without encryption or
-+ immediate MAC protection, servers must not place confidential
-+ information in session identifiers or let the contents of fake
-+ session identifiers cause any breach of security. (Note that the
-+ content of the handshake as a whole, including the SessionID, is
-+ protected by the Finished messages exchanged at the end of the
-+ handshake.)
-+
-+ The CipherSuite list, passed from the client to the server in the
-+ client hello message, contains the combinations of cryptographic
-+ algorithms supported by the client in order of the client's
-+ preference (favorite choice first). Each CipherSuite defines a key
-+ exchange algorithm, a bulk encryption algorithm (including secret key
-+ length) and a MAC algorithm. The server will select a cipher suite
-+ or, if no acceptable choices are presented, return a handshake
-+ failure alert and close the connection.
-+
-+ uint8 CipherSuite[2]; /* Cryptographic suite selector */
-+
-+ The client hello includes a list of compression algorithms supported
-+ by the client, ordered according to the client's preference.
-+
-+ enum { null(0), (255) } CompressionMethod;
-+
-+ struct {
-+ ProtocolVersion client_version;
-+ Random random;
-+ SessionID session_id;
-+ CipherSuite cipher_suites<2..2^16-1>;
-+ CompressionMethod compression_methods<1..2^8-1>;
-+ } ClientHello;
-+
-+ client_version
-+ The version of the TLS protocol by which the client wishes to
-+ communicate during this session. This should be the latest
-+ (highest valued) version supported by the client. For this
-+ version of the specification, the version will be 3.1 (See
-+ Appendix E for details about backward compatibility).
-+
-+ random
-+ A client-generated random structure.
-+
-+ session_id
-+ The ID of a session the client wishes to use for this connection.
-+ This field should be empty if no session_id is available or the
-+ client wishes to generate new security parameters.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 35]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ cipher_suites
-+ This is a list of the cryptographic options supported by the
-+ client, with the client's first preference first. If the
-+ session_id field is not empty (implying a session resumption
-+ request) this vector must include at least the cipher_suite from
-+ that session. Values are defined in Appendix A.5.
-+
-+ compression_methods
-+ This is a list of the compression methods supported by the
-+ client, sorted by client preference. If the session_id field is
-+ not empty (implying a session resumption request) it must include
-+ the compression_method from that session. This vector must
-+ contain, and all implementations must support,
-+ CompressionMethod.null. Thus, a client and server will always be
-+ able to agree on a compression method.
-+
-+ After sending the client hello message, the client waits for a server
-+ hello message. Any other handshake message returned by the server
-+ except for a hello request is treated as a fatal error.
-+
-+ Forward compatibility note:
-+ In the interests of forward compatibility, it is permitted for a
-+ client hello message to include extra data after the compression
-+ methods. This data must be included in the handshake hashes, but
-+ must otherwise be ignored. This is the only handshake message for
-+ which this is legal; for all other messages, the amount of data
-+ in the message must match the description of the message
-+ precisely.
-+
-+ 7.4.1.3. Server hello
-+
-+ When this message will be sent:
-+ The server will send this message in response to a client hello
-+ message when it was able to find an acceptable set of algorithms.
-+ If it cannot find such a match, it will respond with a handshake
-+ failure alert.
-+
-+ Structure of this message:
-+ struct {
-+ ProtocolVersion server_version;
-+ Random random;
-+ SessionID session_id;
-+ CipherSuite cipher_suite;
-+ CompressionMethod compression_method;
-+ } ServerHello;
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 36]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ server_version
-+ This field will contain the lower of that suggested by the client
-+ in the client hello and the highest supported by the server. For
-+ this version of the specification, the version is 3.1 (See
-+ Appendix E for details about backward compatibility).
-+
-+ random
-+ This structure is generated by the server and must be different
-+ from (and independent of) ClientHello.random.
-+
-+ session_id
-+ This is the identity of the session corresponding to this
-+ connection. If the ClientHello.session_id was non-empty, the
-+ server will look in its session cache for a match. If a match is
-+ found and the server is willing to establish the new connection
-+ using the specified session state, the server will respond with
-+ the same value as was supplied by the client. This indicates a
-+ resumed session and dictates that the parties must proceed
-+ directly to the finished messages. Otherwise this field will
-+ contain a different value identifying the new session. The server
-+ may return an empty session_id to indicate that the session will
-+ not be cached and therefore cannot be resumed. If a session is
-+ resumed, it must be resumed using the same cipher suite it was
-+ originally negotiated with.
-+
-+ cipher_suite
-+ The single cipher suite selected by the server from the list in
-+ ClientHello.cipher_suites. For resumed sessions this field is the
-+ value from the state of the session being resumed.
-+
-+ compression_method
-+ The single compression algorithm selected by the server from the
-+ list in ClientHello.compression_methods. For resumed sessions
-+ this field is the value from the resumed session state.
-+
-+ 7.4.2. Server certificate
-+
-+ When this message will be sent:
-+ The server must send a certificate whenever the agreed-upon key
-+ exchange method is not an anonymous one. This message will always
-+ immediately follow the server hello message.
-+
-+ Meaning of this message:
-+ The certificate type must be appropriate for the selected cipher
-+ suite's key exchange algorithm, and is generally an X.509v3
-+ certificate. It must contain a key which matches the key exchange
-+ method, as follows. Unless otherwise specified, the signing
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 37]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ algorithm for the certificate must be the same as the algorithm
-+ for the certificate key. Unless otherwise specified, the public
-+ key may be of any length.
-+
-+ Key Exchange Algorithm Certificate Key Type
-+
-+ RSA RSA public key; the certificate must
-+ allow the key to be used for encryption.
-+
-+ RSA_EXPORT RSA public key of length greater than
-+ 512 bits which can be used for signing,
-+ or a key of 512 bits or shorter which
-+ can be used for either encryption or
-+ signing.
-+
-+ DHE_DSS DSS public key.
-+
-+ DHE_DSS_EXPORT DSS public key.
-+
-+ DHE_RSA RSA public key which can be used for
-+ signing.
-+
-+ DHE_RSA_EXPORT RSA public key which can be used for
-+ signing.
-+
-+ DH_DSS Diffie-Hellman key. The algorithm used
-+ to sign the certificate should be DSS.
-+
-+ DH_RSA Diffie-Hellman key. The algorithm used
-+ to sign the certificate should be RSA.
-+
-+ All certificate profiles, key and cryptographic formats are defined
-+ by the IETF PKIX working group [PKIX]. When a key usage extension is
-+ present, the digitalSignature bit must be set for the key to be
-+ eligible for signing, as described above, and the keyEncipherment bit
-+ must be present to allow encryption, as described above. The
-+ keyAgreement bit must be set on Diffie-Hellman certificates.
-+
-+ As CipherSuites which specify new key exchange methods are specified
-+ for the TLS Protocol, they will imply certificate format and the
-+ required encoded keying information.
-+
-+ Structure of this message:
-+ opaque ASN.1Cert<1..2^24-1>;
-+
-+ struct {
-+ ASN.1Cert certificate_list<0..2^24-1>;
-+ } Certificate;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 38]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ certificate_list
-+ This is a sequence (chain) of X.509v3 certificates. The sender's
-+ certificate must come first in the list. Each following
-+ certificate must directly certify the one preceding it. Because
-+ certificate validation requires that root keys be distributed
-+ independently, the self-signed certificate which specifies the
-+ root certificate authority may optionally be omitted from the
-+ chain, under the assumption that the remote end must already
-+ possess it in order to validate it in any case.
-+
-+ The same message type and structure will be used for the client's
-+ response to a certificate request message. Note that a client may
-+ send no certificates if it does not have an appropriate certificate
-+ to send in response to the server's authentication request.
-+
-+ Note: PKCS #7 [PKCS7] is not used as the format for the certificate
-+ vector because PKCS #6 [PKCS6] extended certificates are not
-+ used. Also PKCS #7 defines a SET rather than a SEQUENCE, making
-+ the task of parsing the list more difficult.
-+
-+ 7.4.3. Server key exchange message
-+
-+ When this message will be sent:
-+ This message will be sent immediately after the server
-+ certificate message (or the server hello message, if this is an
-+ anonymous negotiation).
-+
-+ The server key exchange message is sent by the server only when
-+ the server certificate message (if sent) does not contain enough
-+ data to allow the client to exchange a premaster secret. This is
-+ true for the following key exchange methods:
-+
-+ RSA_EXPORT (if the public key in the server certificate is
-+ longer than 512 bits)
-+ DHE_DSS
-+ DHE_DSS_EXPORT
-+ DHE_RSA
-+ DHE_RSA_EXPORT
-+ DH_anon
-+
-+ It is not legal to send the server key exchange message for the
-+ following key exchange methods:
-+
-+ RSA
-+ RSA_EXPORT (when the public key in the server certificate is
-+ less than or equal to 512 bits in length)
-+ DH_DSS
-+ DH_RSA
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 39]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Meaning of this message:
-+ This message conveys cryptographic information to allow the
-+ client to communicate the premaster secret: either an RSA public
-+ key to encrypt the premaster secret with, or a Diffie-Hellman
-+ public key with which the client can complete a key exchange
-+ (with the result being the premaster secret.)
-+
-+ As additional CipherSuites are defined for TLS which include new key
-+ exchange algorithms, the server key exchange message will be sent if
-+ and only if the certificate type associated with the key exchange
-+ algorithm does not provide enough information for the client to
-+ exchange a premaster secret.
-+
-+ Note: According to current US export law, RSA moduli larger than 512
-+ bits may not be used for key exchange in software exported from
-+ the US. With this message, the larger RSA keys encoded in
-+ certificates may be used to sign temporary shorter RSA keys for
-+ the RSA_EXPORT key exchange method.
-+
-+ Structure of this message:
-+ enum { rsa, diffie_hellman } KeyExchangeAlgorithm;
-+
-+ struct {
-+ opaque rsa_modulus<1..2^16-1>;
-+ opaque rsa_exponent<1..2^16-1>;
-+ } ServerRSAParams;
-+
-+ rsa_modulus
-+ The modulus of the server's temporary RSA key.
-+
-+ rsa_exponent
-+ The public exponent of the server's temporary RSA key.
-+
-+ struct {
-+ opaque dh_p<1..2^16-1>;
-+ opaque dh_g<1..2^16-1>;
-+ opaque dh_Ys<1..2^16-1>;
-+ } ServerDHParams; /* Ephemeral DH parameters */
-+
-+ dh_p
-+ The prime modulus used for the Diffie-Hellman operation.
-+
-+ dh_g
-+ The generator used for the Diffie-Hellman operation.
-+
-+ dh_Ys
-+ The server's Diffie-Hellman public value (g^X mod p).
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 40]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ struct {
-+ select (KeyExchangeAlgorithm) {
-+ case diffie_hellman:
-+ ServerDHParams params;
-+ Signature signed_params;
-+ case rsa:
-+ ServerRSAParams params;
-+ Signature signed_params;
-+ };
-+ } ServerKeyExchange;
-+
-+ params
-+ The server's key exchange parameters.
-+
-+ signed_params
-+ For non-anonymous key exchanges, a hash of the corresponding
-+ params value, with the signature appropriate to that hash
-+ applied.
-+
-+ md5_hash
-+ MD5(ClientHello.random + ServerHello.random + ServerParams);
-+
-+ sha_hash
-+ SHA(ClientHello.random + ServerHello.random + ServerParams);
-+
-+ enum { anonymous, rsa, dsa } SignatureAlgorithm;
-+
-+ select (SignatureAlgorithm)
-+ { case anonymous: struct { };
-+ case rsa:
-+ digitally-signed struct {
-+ opaque md5_hash[16];
-+ opaque sha_hash[20];
-+ };
-+ case dsa:
-+ digitally-signed struct {
-+ opaque sha_hash[20];
-+ };
-+ } Signature;
-+
-+ 7.4.4. Certificate request
-+
-+ When this message will be sent:
-+ A non-anonymous server can optionally request a certificate from
-+ the client, if appropriate for the selected cipher suite. This
-+ message, if sent, will immediately follow the Server Key Exchange
-+ message (if it is sent; otherwise, the Server Certificate
-+ message).
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 41]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Structure of this message:
-+ enum {
-+ rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
-+ (255)
-+ } ClientCertificateType;
-+
-+ opaque DistinguishedName<1..2^16-1>;
-+
-+ struct {
-+ ClientCertificateType certificate_types<1..2^8-1>;
-+ DistinguishedName certificate_authorities<3..2^16-1>;
-+ } CertificateRequest;
-+
-+ certificate_types
-+ This field is a list of the types of certificates requested,
-+ sorted in order of the server's preference.
-+
-+ certificate_authorities
-+ A list of the distinguished names of acceptable certificate
-+ authorities. These distinguished names may specify a desired
-+ distinguished name for a root CA or for a subordinate CA;
-+ thus, this message can be used both to describe known roots
-+ and a desired authorization space.
-+
-+ Note: DistinguishedName is derived from [X509].
-+
-+ Note: It is a fatal handshake_failure alert for an anonymous server to
-+ request client identification.
-+
-+ 7.4.5. Server hello done
-+
-+ When this message will be sent:
-+ The server hello done message is sent by the server to indicate
-+ the end of the server hello and associated messages. After
-+ sending this message the server will wait for a client response.
-+
-+ Meaning of this message:
-+ This message means that the server is done sending messages to
-+ support the key exchange, and the client can proceed with its
-+ phase of the key exchange.
-+
-+ Upon receipt of the server hello done message the client should
-+ verify that the server provided a valid certificate if required
-+ and check that the server hello parameters are acceptable.
-+
-+ Structure of this message:
-+ struct { } ServerHelloDone;
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 42]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 7.4.6. Client certificate
-+
-+ When this message will be sent:
-+ This is the first message the client can send after receiving a
-+ server hello done message. This message is only sent if the
-+ server requests a certificate. If no suitable certificate is
-+ available, the client should send a certificate message
-+ containing no certificates. If client authentication is required
-+ by the server for the handshake to continue, it may respond with
-+ a fatal handshake failure alert. Client certificates are sent
-+ using the Certificate structure defined in Section 7.4.2.
-+
-+ Note: When using a static Diffie-Hellman based key exchange method
-+ (DH_DSS or DH_RSA), if client authentication is requested, the
-+ Diffie-Hellman group and generator encoded in the client's
-+ certificate must match the server specified Diffie-Hellman
-+ parameters if the client's parameters are to be used for the key
-+ exchange.
-+
-+ 7.4.7. Client key exchange message
-+
-+ When this message will be sent:
-+ This message is always sent by the client. It will immediately
-+ follow the client certificate message, if it is sent. Otherwise
-+ it will be the first message sent by the client after it receives
-+ the server hello done message.
-+
-+ Meaning of this message:
-+ With this message, the premaster secret is set, either though
-+ direct transmission of the RSA-encrypted secret, or by the
-+ transmission of Diffie-Hellman parameters which will allow each
-+ side to agree upon the same premaster secret. When the key
-+ exchange method is DH_RSA or DH_DSS, client certification has
-+ been requested, and the client was able to respond with a
-+ certificate which contained a Diffie-Hellman public key whose
-+ parameters (group and generator) matched those specified by the
-+ server in its certificate, this message will not contain any
-+ data.
-+
-+ Structure of this message:
-+ The choice of messages depends on which key exchange method has
-+ been selected. See Section 7.4.3 for the KeyExchangeAlgorithm
-+ definition.
-+
-+ struct {
-+ select (KeyExchangeAlgorithm) {
-+ case rsa: EncryptedPreMasterSecret;
-+ case diffie_hellman: ClientDiffieHellmanPublic;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 43]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ } exchange_keys;
-+ } ClientKeyExchange;
-+
-+ 7.4.7.1. RSA encrypted premaster secret message
-+
-+ Meaning of this message:
-+ If RSA is being used for key agreement and authentication, the
-+ client generates a 48-byte premaster secret, encrypts it using
-+ the public key from the server's certificate or the temporary RSA
-+ key provided in a server key exchange message, and sends the
-+ result in an encrypted premaster secret message. This structure
-+ is a variant of the client key exchange message, not a message in
-+ itself.
-+
-+ Structure of this message:
-+ struct {
-+ ProtocolVersion client_version;
-+ opaque random[46];
-+ } PreMasterSecret;
-+
-+ client_version
-+ The latest (newest) version supported by the client. This is
-+ used to detect version roll-back attacks. Upon receiving the
-+ premaster secret, the server should check that this value
-+ matches the value transmitted by the client in the client
-+ hello message.
-+
-+ random
-+ 46 securely-generated random bytes.
-+
-+ struct {
-+ public-key-encrypted PreMasterSecret pre_master_secret;
-+ } EncryptedPreMasterSecret;
-+
-+ Note: An attack discovered by Daniel Bleichenbacher [BLEI] can be used
-+ to attack a TLS server which is using PKCS#1 encoded RSA. The
-+ attack takes advantage of the fact that by failing in different
-+ ways, a TLS server can be coerced into revealing whether a
-+ particular message, when decrypted, is properly PKCS#1 formatted
-+ or not.
-+
-+ The best way to avoid vulnerability to this attack is to treat
-+ incorrectly formatted messages in a manner indistinguishable from
-+ correctly formatted RSA blocks. Thus, when it receives an
-+ incorrectly formatted RSA block, a server should generate a
-+ random 48-byte value and proceed using it as the premaster
-+ secret. Thus, the server will act identically whether the
-+ received RSA block is correctly encoded or not.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 44]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ pre_master_secret
-+ This random value is generated by the client and is used to
-+ generate the master secret, as specified in Section 8.1.
-+
-+ 7.4.7.2. Client Diffie-Hellman public value
-+
-+ Meaning of this message:
-+ This structure conveys the client's Diffie-Hellman public value
-+ (Yc) if it was not already included in the client's certificate.
-+ The encoding used for Yc is determined by the enumerated
-+ PublicValueEncoding. This structure is a variant of the client
-+ key exchange message, not a message in itself.
-+
-+ Structure of this message:
-+ enum { implicit, explicit } PublicValueEncoding;
-+
-+ implicit
-+ If the client certificate already contains a suitable
-+ Diffie-Hellman key, then Yc is implicit and does not need to
-+ be sent again. In this case, the Client Key Exchange message
-+ will be sent, but will be empty.
-+
-+ explicit
-+ Yc needs to be sent.
-+
-+ struct {
-+ select (PublicValueEncoding) {
-+ case implicit: struct { };
-+ case explicit: opaque dh_Yc<1..2^16-1>;
-+ } dh_public;
-+ } ClientDiffieHellmanPublic;
-+
-+ dh_Yc
-+ The client's Diffie-Hellman public value (Yc).
-+
-+ 7.4.8. Certificate verify
-+
-+ When this message will be sent:
-+ This message is used to provide explicit verification of a client
-+ certificate. This message is only sent following a client
-+ certificate that has signing capability (i.e. all certificates
-+ except those containing fixed Diffie-Hellman parameters). When
-+ sent, it will immediately follow the client key exchange message.
-+
-+ Structure of this message:
-+ struct {
-+ Signature signature;
-+ } CertificateVerify;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 45]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ The Signature type is defined in 7.4.3.
-+
-+ CertificateVerify.signature.md5_hash
-+ MD5(handshake_messages);
-+
-+ Certificate.signature.sha_hash
-+ SHA(handshake_messages);
-+
-+ Here handshake_messages refers to all handshake messages sent or
-+ received starting at client hello up to but not including this
-+ message, including the type and length fields of the handshake
-+ messages. This is the concatenation of all the Handshake structures
-+ as defined in 7.4 exchanged thus far.
-+
-+ 7.4.9. Finished
-+
-+ When this message will be sent:
-+ A finished message is always sent immediately after a change
-+ cipher spec message to verify that the key exchange and
-+ authentication processes were successful. It is essential that a
-+ change cipher spec message be received between the other
-+ handshake messages and the Finished message.
-+
-+ Meaning of this message:
-+ The finished message is the first protected with the just-
-+ negotiated algorithms, keys, and secrets. Recipients of finished
-+ messages must verify that the contents are correct. Once a side
-+ has sent its Finished message and received and validated the
-+ Finished message from its peer, it may begin to send and receive
-+ application data over the connection.
-+
-+ struct {
-+ opaque verify_data[12];
-+ } Finished;
-+
-+ verify_data
-+ PRF(master_secret, finished_label, MD5(handshake_messages) +
-+ SHA-1(handshake_messages)) [0..11];
-+
-+ finished_label
-+ For Finished messages sent by the client, the string "client
-+ finished". For Finished messages sent by the server, the
-+ string "server finished".
-+
-+ handshake_messages
-+ All of the data from all handshake messages up to but not
-+ including this message. This is only data visible at the
-+ handshake layer and does not include record layer headers.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 46]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ This is the concatenation of all the Handshake structures as
-+ defined in 7.4 exchanged thus far.
-+
-+ It is a fatal error if a finished message is not preceded by a change
-+ cipher spec message at the appropriate point in the handshake.
-+
-+ The hash contained in finished messages sent by the server
-+ incorporate Sender.server; those sent by the client incorporate
-+ Sender.client. The value handshake_messages includes all handshake
-+ messages starting at client hello up to, but not including, this
-+ finished message. This may be different from handshake_messages in
-+ Section 7.4.8 because it would include the certificate verify message
-+ (if sent). Also, the handshake_messages for the finished message sent
-+ by the client will be different from that for the finished message
-+ sent by the server, because the one which is sent second will include
-+ the prior one.
-+
-+ Note: Change cipher spec messages, alerts and any other record types
-+ are not handshake messages and are not included in the hash
-+ computations. Also, Hello Request messages are omitted from
-+ handshake hashes.
-+
-+ 8. Cryptographic computations
-+
-+ In order to begin connection protection, the TLS Record Protocol
-+ requires specification of a suite of algorithms, a master secret, and
-+ the client and server random values. The authentication, encryption,
-+ and MAC algorithms are determined by the cipher_suite selected by the
-+ server and revealed in the server hello message. The compression
-+ algorithm is negotiated in the hello messages, and the random values
-+ are exchanged in the hello messages. All that remains is to calculate
-+ the master secret.
-+
-+ 8.1. Computing the master secret
-+
-+ For all key exchange methods, the same algorithm is used to convert
-+ the pre_master_secret into the master_secret. The pre_master_secret
-+ should be deleted from memory once the master_secret has been
-+ computed.
-+
-+ master_secret = PRF(pre_master_secret, "master secret",
-+ ClientHello.random + ServerHello.random)
-+ [0..47];
-+
-+ The master secret is always exactly 48 bytes in length. The length of
-+ the premaster secret will vary depending on key exchange method.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 47]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ 8.1.1. RSA
-+
-+ When RSA is used for server authentication and key exchange, a 48-
-+ byte pre_master_secret is generated by the client, encrypted under
-+ the server's public key, and sent to the server. The server uses its
-+ private key to decrypt the pre_master_secret. Both parties then
-+ convert the pre_master_secret into the master_secret, as specified
-+ above.
-+
-+ RSA digital signatures are performed using PKCS #1 [PKCS1] block type
-+ 1. RSA public key encryption is performed using PKCS #1 block type 2.
-+
-+ 8.1.2. Diffie-Hellman
-+
-+ A conventional Diffie-Hellman computation is performed. The
-+ negotiated key (Z) is used as the pre_master_secret, and is converted
-+ into the master_secret, as specified above.
-+
-+ Note: Diffie-Hellman parameters are specified by the server, and may
-+ be either ephemeral or contained within the server's certificate.
-+
-+ 9. Mandatory Cipher Suites
-+
-+ In the absence of an application profile standard specifying
-+ otherwise, a TLS compliant application MUST implement the cipher
-+ suite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.
-+
-+ 10. Application data protocol
-+
-+ Application data messages are carried by the Record Layer and are
-+ fragmented, compressed and encrypted based on the current connection
-+ state. The messages are treated as transparent data to the record
-+ layer.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 48]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ A. Protocol constant values
-+
-+ This section describes protocol types and constants.
-+
-+ A.1. Record layer
-+
-+ struct {
-+ uint8 major, minor;
-+ } ProtocolVersion;
-+
-+ ProtocolVersion version = { 3, 1 }; /* TLS v1.0 */
-+
-+ enum {
-+ change_cipher_spec(20), alert(21), handshake(22),
-+ application_data(23), (255)
-+ } ContentType;
-+
-+ struct {
-+ ContentType type;
-+ ProtocolVersion version;
-+ uint16 length;
-+ opaque fragment[TLSPlaintext.length];
-+ } TLSPlaintext;
-+
-+ struct {
-+ ContentType type;
-+ ProtocolVersion version;
-+ uint16 length;
-+ opaque fragment[TLSCompressed.length];
-+ } TLSCompressed;
-+
-+ struct {
-+ ContentType type;
-+ ProtocolVersion version;
-+ uint16 length;
-+ select (CipherSpec.cipher_type) {
-+ case stream: GenericStreamCipher;
-+ case block: GenericBlockCipher;
-+ } fragment;
-+ } TLSCiphertext;
-+
-+ stream-ciphered struct {
-+ opaque content[TLSCompressed.length];
-+ opaque MAC[CipherSpec.hash_size];
-+ } GenericStreamCipher;
-+
-+ block-ciphered struct {
-+ opaque content[TLSCompressed.length];
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 49]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ opaque MAC[CipherSpec.hash_size];
-+ uint8 padding[GenericBlockCipher.padding_length];
-+ uint8 padding_length;
-+ } GenericBlockCipher;
-+
-+ A.2. Change cipher specs message
-+
-+ struct {
-+ enum { change_cipher_spec(1), (255) } type;
-+ } ChangeCipherSpec;
-+
-+ A.3. Alert messages
-+
-+ enum { warning(1), fatal(2), (255) } AlertLevel;
-+
-+ enum {
-+ close_notify(0),
-+ unexpected_message(10),
-+ bad_record_mac(20),
-+ decryption_failed(21),
-+ record_overflow(22),
-+ decompression_failure(30),
-+ handshake_failure(40),
-+ bad_certificate(42),
-+ unsupported_certificate(43),
-+ certificate_revoked(44),
-+ certificate_expired(45),
-+ certificate_unknown(46),
-+ illegal_parameter(47),
-+ unknown_ca(48),
-+ access_denied(49),
-+ decode_error(50),
-+ decrypt_error(51),
-+ export_restriction(60),
-+ protocol_version(70),
-+ insufficient_security(71),
-+ internal_error(80),
-+ user_canceled(90),
-+ no_renegotiation(100),
-+ (255)
-+ } AlertDescription;
-+
-+ struct {
-+ AlertLevel level;
-+ AlertDescription description;
-+ } Alert;
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 50]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ A.4. Handshake protocol
-+
-+ enum {
-+ hello_request(0), client_hello(1), server_hello(2),
-+ certificate(11), server_key_exchange (12),
-+ certificate_request(13), server_hello_done(14),
-+ certificate_verify(15), client_key_exchange(16),
-+ finished(20), (255)
-+ } HandshakeType;
-+
-+ struct {
-+ HandshakeType msg_type;
-+ uint24 length;
-+ select (HandshakeType) {
-+ case hello_request: HelloRequest;
-+ case client_hello: ClientHello;
-+ case server_hello: ServerHello;
-+ case certificate: Certificate;
-+ case server_key_exchange: ServerKeyExchange;
-+ case certificate_request: CertificateRequest;
-+ case server_hello_done: ServerHelloDone;
-+ case certificate_verify: CertificateVerify;
-+ case client_key_exchange: ClientKeyExchange;
-+ case finished: Finished;
-+ } body;
-+ } Handshake;
-+
-+ A.4.1. Hello messages
-+
-+ struct { } HelloRequest;
-+
-+ struct {
-+ uint32 gmt_unix_time;
-+ opaque random_bytes[28];
-+ } Random;
-+
-+ opaque SessionID<0..32>;
-+
-+ uint8 CipherSuite[2];
-+
-+ enum { null(0), (255) } CompressionMethod;
-+
-+ struct {
-+ ProtocolVersion client_version;
-+ Random random;
-+ SessionID session_id;
-+ CipherSuite cipher_suites<2..2^16-1>;
-+ CompressionMethod compression_methods<1..2^8-1>;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 51]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ } ClientHello;
-+
-+ struct {
-+ ProtocolVersion server_version;
-+ Random random;
-+ SessionID session_id;
-+ CipherSuite cipher_suite;
-+ CompressionMethod compression_method;
-+ } ServerHello;
-+
-+ A.4.2. Server authentication and key exchange messages
-+
-+ opaque ASN.1Cert<2^24-1>;
-+
-+ struct {
-+ ASN.1Cert certificate_list<1..2^24-1>;
-+ } Certificate;
-+
-+ enum { rsa, diffie_hellman } KeyExchangeAlgorithm;
-+
-+ struct {
-+ opaque RSA_modulus<1..2^16-1>;
-+ opaque RSA_exponent<1..2^16-1>;
-+ } ServerRSAParams;
-+
-+ struct {
-+ opaque DH_p<1..2^16-1>;
-+ opaque DH_g<1..2^16-1>;
-+ opaque DH_Ys<1..2^16-1>;
-+ } ServerDHParams;
-+
-+ struct {
-+ select (KeyExchangeAlgorithm) {
-+ case diffie_hellman:
-+ ServerDHParams params;
-+ Signature signed_params;
-+ case rsa:
-+ ServerRSAParams params;
-+ Signature signed_params;
-+ };
-+ } ServerKeyExchange;
-+
-+ enum { anonymous, rsa, dsa } SignatureAlgorithm;
-+
-+ select (SignatureAlgorithm)
-+ { case anonymous: struct { };
-+ case rsa:
-+ digitally-signed struct {
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 52]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ opaque md5_hash[16];
-+ opaque sha_hash[20];
-+ };
-+ case dsa:
-+ digitally-signed struct {
-+ opaque sha_hash[20];
-+ };
-+ } Signature;
-+
-+ enum {
-+ rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
-+ (255)
-+ } ClientCertificateType;
-+
-+ opaque DistinguishedName<1..2^16-1>;
-+
-+ struct {
-+ ClientCertificateType certificate_types<1..2^8-1>;
-+ DistinguishedName certificate_authorities<3..2^16-1>;
-+ } CertificateRequest;
-+
-+ struct { } ServerHelloDone;
-+
-+ A.4.3. Client authentication and key exchange messages
-+
-+ struct {
-+ select (KeyExchangeAlgorithm) {
-+ case rsa: EncryptedPreMasterSecret;
-+ case diffie_hellman: DiffieHellmanClientPublicValue;
-+ } exchange_keys;
-+ } ClientKeyExchange;
-+
-+ struct {
-+ ProtocolVersion client_version;
-+ opaque random[46];
-+
-+ } PreMasterSecret;
-+
-+ struct {
-+ public-key-encrypted PreMasterSecret pre_master_secret;
-+ } EncryptedPreMasterSecret;
-+
-+ enum { implicit, explicit } PublicValueEncoding;
-+
-+ struct {
-+ select (PublicValueEncoding) {
-+ case implicit: struct {};
-+ case explicit: opaque DH_Yc<1..2^16-1>;
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 53]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ } dh_public;
-+ } ClientDiffieHellmanPublic;
-+
-+ struct {
-+ Signature signature;
-+ } CertificateVerify;
-+
-+ A.4.4. Handshake finalization message
-+
-+ struct {
-+ opaque verify_data[12];
-+ } Finished;
-+
-+ A.5. The CipherSuite
-+
-+ The following values define the CipherSuite codes used in the client
-+ hello and server hello messages.
-+
-+ A CipherSuite defines a cipher specification supported in TLS Version
-+ 1.0.
-+
-+ TLS_NULL_WITH_NULL_NULL is specified and is the initial state of a
-+ TLS connection during the first handshake on that channel, but must
-+ not be negotiated, as it provides no more protection than an
-+ unsecured connection.
-+
-+ CipherSuite TLS_NULL_WITH_NULL_NULL = { 0x00,0x00 };
-+
-+ The following CipherSuite definitions require that the server provide
-+ an RSA certificate that can be used for key exchange. The server may
-+ request either an RSA or a DSS signature-capable certificate in the
-+ certificate request message.
-+
-+ CipherSuite TLS_RSA_WITH_NULL_MD5 = { 0x00,0x01 };
-+ CipherSuite TLS_RSA_WITH_NULL_SHA = { 0x00,0x02 };
-+ CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x03 };
-+ CipherSuite TLS_RSA_WITH_RC4_128_MD5 = { 0x00,0x04 };
-+ CipherSuite TLS_RSA_WITH_RC4_128_SHA = { 0x00,0x05 };
-+ CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00,0x06 };
-+ CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = { 0x00,0x07 };
-+ CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x08 };
-+ CipherSuite TLS_RSA_WITH_DES_CBC_SHA = { 0x00,0x09 };
-+ CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0A };
-+
-+ The following CipherSuite definitions are used for server-
-+ authenticated (and optionally client-authenticated) Diffie-Hellman.
-+ DH denotes cipher suites in which the server's certificate contains
-+ the Diffie-Hellman parameters signed by the certificate authority
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 54]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ (CA). DHE denotes ephemeral Diffie-Hellman, where the Diffie-Hellman
-+ parameters are signed by a DSS or RSA certificate, which has been
-+ signed by the CA. The signing algorithm used is specified after the
-+ DH or DHE parameter. The server can request an RSA or DSS signature-
-+ capable certificate from the client for client authentication or it
-+ may request a Diffie-Hellman certificate. Any Diffie-Hellman
-+ certificate provided by the client must use the parameters (group and
-+ generator) described by the server.
-+
-+ CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0B };
-+ CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = { 0x00,0x0C };
-+ CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0D };
-+ CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0E };
-+ CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = { 0x00,0x0F };
-+ CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x10 };
-+ CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x11 };
-+ CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA = { 0x00,0x12 };
-+ CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x13 };
-+ CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x14 };
-+ CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA = { 0x00,0x15 };
-+ CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x16 };
-+
-+ The following cipher suites are used for completely anonymous
-+ Diffie-Hellman communications in which neither party is
-+ authenticated. Note that this mode is vulnerable to man-in-the-middle
-+ attacks and is therefore deprecated.
-+
-+ CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x17 };
-+ CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 = { 0x00,0x18 };
-+ CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x19 };
-+ CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA = { 0x00,0x1A };
-+ CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = { 0x00,0x1B };
-+
-+ Note: All cipher suites whose first byte is 0xFF are considered
-+ private and can be used for defining local/experimental
-+ algorithms. Interoperability of such types is a local matter.
-+
-+ Note: Additional cipher suites can be registered by publishing an RFC
-+ which specifies the cipher suites, including the necessary TLS
-+ protocol information, including message encoding, premaster
-+ secret derivation, symmetric encryption and MAC calculation and
-+ appropriate reference information for the algorithms involved.
-+ The RFC editor's office may, at its discretion, choose to publish
-+ specifications for cipher suites which are not completely
-+ described (e.g., for classified algorithms) if it finds the
-+ specification to be of technical interest and completely
-+ specified.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 55]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are
-+ reserved to avoid collision with Fortezza-based cipher suites in
-+ SSL 3.
-+
-+ A.6. The Security Parameters
-+
-+ These security parameters are determined by the TLS Handshake
-+ Protocol and provided as parameters to the TLS Record Layer in order
-+ to initialize a connection state. SecurityParameters includes:
-+
-+ enum { null(0), (255) } CompressionMethod;
-+
-+ enum { server, client } ConnectionEnd;
-+
-+ enum { null, rc4, rc2, des, 3des, des40, idea }
-+ BulkCipherAlgorithm;
-+
-+ enum { stream, block } CipherType;
-+
-+ enum { true, false } IsExportable;
-+
-+ enum { null, md5, sha } MACAlgorithm;
-+
-+ /* The algorithms specified in CompressionMethod,
-+ BulkCipherAlgorithm, and MACAlgorithm may be added to. */
-+
-+ struct {
-+ ConnectionEnd entity;
-+ BulkCipherAlgorithm bulk_cipher_algorithm;
-+ CipherType cipher_type;
-+ uint8 key_size;
-+ uint8 key_material_length;
-+ IsExportable is_exportable;
-+ MACAlgorithm mac_algorithm;
-+ uint8 hash_size;
-+ CompressionMethod compression_algorithm;
-+ opaque master_secret[48];
-+ opaque client_random[32];
-+ opaque server_random[32];
-+ } SecurityParameters;
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 56]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ B. Glossary
-+
-+ application protocol
-+ An application protocol is a protocol that normally layers
-+ directly on top of the transport layer (e.g., TCP/IP). Examples
-+ include HTTP, TELNET, FTP, and SMTP.
-+
-+ asymmetric cipher
-+ See public key cryptography.
-+
-+ authentication
-+ Authentication is the ability of one entity to determine the
-+ identity of another entity.
-+
-+ block cipher
-+ A block cipher is an algorithm that operates on plaintext in
-+ groups of bits, called blocks. 64 bits is a common block size.
-+
-+ bulk cipher
-+ A symmetric encryption algorithm used to encrypt large quantities
-+ of data.
-+
-+ cipher block chaining (CBC)
-+ CBC is a mode in which every plaintext block encrypted with a
-+ block cipher is first exclusive-ORed with the previous ciphertext
-+ block (or, in the case of the first block, with the
-+ initialization vector). For decryption, every block is first
-+ decrypted, then exclusive-ORed with the previous ciphertext block
-+ (or IV).
-+
-+ certificate
-+ As part of the X.509 protocol (a.k.a. ISO Authentication
-+ framework), certificates are assigned by a trusted Certificate
-+ Authority and provide a strong binding between a party's identity
-+ or some other attributes and its public key.
-+
-+ client
-+ The application entity that initiates a TLS connection to a
-+ server. This may or may not imply that the client initiated the
-+ underlying transport connection. The primary operational
-+ difference between the server and client is that the server is
-+ generally authenticated, while the client is only optionally
-+ authenticated.
-+
-+ client write key
-+ The key used to encrypt data written by the client.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 57]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ client write MAC secret
-+ The secret data used to authenticate data written by the client.
-+
-+ connection
-+ A connection is a transport (in the OSI layering model
-+ definition) that provides a suitable type of service. For TLS,
-+ such connections are peer to peer relationships. The connections
-+ are transient. Every connection is associated with one session.
-+
-+ Data Encryption Standard
-+ DES is a very widely used symmetric encryption algorithm. DES is
-+ a block cipher with a 56 bit key and an 8 byte block size. Note
-+ that in TLS, for key generation purposes, DES is treated as
-+ having an 8 byte key length (64 bits), but it still only provides
-+ 56 bits of protection. (The low bit of each key byte is presumed
-+ to be set to produce odd parity in that key byte.) DES can also
-+ be operated in a mode where three independent keys and three
-+ encryptions are used for each block of data; this uses 168 bits
-+ of key (24 bytes in the TLS key generation method) and provides
-+ the equivalent of 112 bits of security. [DES], [3DES]
-+
-+ Digital Signature Standard (DSS)
-+ A standard for digital signing, including the Digital Signing
-+ Algorithm, approved by the National Institute of Standards and
-+ Technology, defined in NIST FIPS PUB 186, "Digital Signature
-+ Standard," published May, 1994 by the U.S. Dept. of Commerce.
-+ [DSS]
-+
-+ digital signatures
-+ Digital signatures utilize public key cryptography and one-way
-+ hash functions to produce a signature of the data that can be
-+ authenticated, and is difficult to forge or repudiate.
-+
-+ handshake
-+ An initial negotiation between client and server that establishes
-+ the parameters of their transactions.
-+
-+ Initialization Vector (IV)
-+ When a block cipher is used in CBC mode, the initialization
-+ vector is exclusive-ORed with the first plaintext block prior to
-+ encryption.
-+
-+ IDEA
-+ A 64-bit block cipher designed by Xuejia Lai and James Massey.
-+ [IDEA]
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 58]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Message Authentication Code (MAC)
-+ A Message Authentication Code is a one-way hash computed from a
-+ message and some secret data. It is difficult to forge without
-+ knowing the secret data. Its purpose is to detect if the message
-+ has been altered.
-+
-+ master secret
-+ Secure secret data used for generating encryption keys, MAC
-+ secrets, and IVs.
-+
-+ MD5
-+ MD5 is a secure hashing function that converts an arbitrarily
-+ long data stream into a digest of fixed size (16 bytes). [MD5]
-+
-+ public key cryptography
-+ A class of cryptographic techniques employing two-key ciphers.
-+ Messages encrypted with the public key can only be decrypted with
-+ the associated private key. Conversely, messages signed with the
-+ private key can be verified with the public key.
-+
-+ one-way hash function
-+ A one-way transformation that converts an arbitrary amount of
-+ data into a fixed-length hash. It is computationally hard to
-+ reverse the transformation or to find collisions. MD5 and SHA are
-+ examples of one-way hash functions.
-+
-+ RC2
-+ A block cipher developed by Ron Rivest at RSA Data Security, Inc.
-+ [RSADSI] described in [RC2].
-+
-+ RC4
-+ A stream cipher licensed by RSA Data Security [RSADSI]. A
-+ compatible cipher is described in [RC4].
-+
-+ RSA
-+ A very widely used public-key algorithm that can be used for
-+ either encryption or digital signing. [RSA]
-+
-+ salt
-+ Non-secret random data used to make export encryption keys resist
-+ precomputation attacks.
-+
-+ server
-+ The server is the application entity that responds to requests
-+ for connections from clients. See also under client.
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 59]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ session
-+ A TLS session is an association between a client and a server.
-+ Sessions are created by the handshake protocol. Sessions define a
-+ set of cryptographic security parameters, which can be shared
-+ among multiple connections. Sessions are used to avoid the
-+ expensive negotiation of new security parameters for each
-+ connection.
-+
-+ session identifier
-+ A session identifier is a value generated by a server that
-+ identifies a particular session.
-+
-+ server write key
-+ The key used to encrypt data written by the server.
-+
-+ server write MAC secret
-+ The secret data used to authenticate data written by the server.
-+
-+ SHA
-+ The Secure Hash Algorithm is defined in FIPS PUB 180-1. It
-+ produces a 20-byte output. Note that all references to SHA
-+ actually use the modified SHA-1 algorithm. [SHA]
-+
-+ SSL
-+ Netscape's Secure Socket Layer protocol [SSL3]. TLS is based on
-+ SSL Version 3.0
-+
-+ stream cipher
-+ An encryption algorithm that converts a key into a
-+ cryptographically-strong keystream, which is then exclusive-ORed
-+ with the plaintext.
-+
-+ symmetric cipher
-+ See bulk cipher.
-+
-+ Transport Layer Security (TLS)
-+ This protocol; also, the Transport Layer Security working group
-+ of the Internet Engineering Task Force (IETF). See "Comments" at
-+ the end of this document.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 60]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ C. CipherSuite definitions
-+
-+ CipherSuite Is Key Cipher Hash
-+ Exportable Exchange
-+
-+ TLS_NULL_WITH_NULL_NULL * NULL NULL NULL
-+ TLS_RSA_WITH_NULL_MD5 * RSA NULL MD5
-+ TLS_RSA_WITH_NULL_SHA * RSA NULL SHA
-+ TLS_RSA_EXPORT_WITH_RC4_40_MD5 * RSA_EXPORT RC4_40 MD5
-+ TLS_RSA_WITH_RC4_128_MD5 RSA RC4_128 MD5
-+ TLS_RSA_WITH_RC4_128_SHA RSA RC4_128 SHA
-+ TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * RSA_EXPORT RC2_CBC_40 MD5
-+ TLS_RSA_WITH_IDEA_CBC_SHA RSA IDEA_CBC SHA
-+ TLS_RSA_EXPORT_WITH_DES40_CBC_SHA * RSA_EXPORT DES40_CBC SHA
-+ TLS_RSA_WITH_DES_CBC_SHA RSA DES_CBC SHA
-+ TLS_RSA_WITH_3DES_EDE_CBC_SHA RSA 3DES_EDE_CBC SHA
-+ TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA * DH_DSS_EXPORT DES40_CBC SHA
-+ TLS_DH_DSS_WITH_DES_CBC_SHA DH_DSS DES_CBC SHA
-+ TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA DH_DSS 3DES_EDE_CBC SHA
-+ TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA * DH_RSA_EXPORT DES40_CBC SHA
-+ TLS_DH_RSA_WITH_DES_CBC_SHA DH_RSA DES_CBC SHA
-+ TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA DH_RSA 3DES_EDE_CBC SHA
-+ TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA * DHE_DSS_EXPORT DES40_CBC SHA
-+ TLS_DHE_DSS_WITH_DES_CBC_SHA DHE_DSS DES_CBC SHA
-+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE_DSS 3DES_EDE_CBC SHA
-+ TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA * DHE_RSA_EXPORT DES40_CBC SHA
-+ TLS_DHE_RSA_WITH_DES_CBC_SHA DHE_RSA DES_CBC SHA
-+ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE_RSA 3DES_EDE_CBC SHA
-+ TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 * DH_anon_EXPORT RC4_40 MD5
-+ TLS_DH_anon_WITH_RC4_128_MD5 DH_anon RC4_128 MD5
-+ TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA DH_anon DES40_CBC SHA
-+ TLS_DH_anon_WITH_DES_CBC_SHA DH_anon DES_CBC SHA
-+ TLS_DH_anon_WITH_3DES_EDE_CBC_SHA DH_anon 3DES_EDE_CBC SHA
-+
-+
-+ * Indicates IsExportable is True
-+
-+ Key
-+ Exchange
-+ Algorithm Description Key size limit
-+
-+ DHE_DSS Ephemeral DH with DSS signatures None
-+ DHE_DSS_EXPORT Ephemeral DH with DSS signatures DH = 512 bits
-+ DHE_RSA Ephemeral DH with RSA signatures None
-+ DHE_RSA_EXPORT Ephemeral DH with RSA signatures DH = 512 bits,
-+ RSA = none
-+ DH_anon Anonymous DH, no signatures None
-+ DH_anon_EXPORT Anonymous DH, no signatures DH = 512 bits
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 61]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ DH_DSS DH with DSS-based certificates None
-+ DH_DSS_EXPORT DH with DSS-based certificates DH = 512 bits
-+ DH_RSA DH with RSA-based certificates None
-+ DH_RSA_EXPORT DH with RSA-based certificates DH = 512 bits,
-+ RSA = none
-+ NULL No key exchange N/A
-+ RSA RSA key exchange None
-+ RSA_EXPORT RSA key exchange RSA = 512 bits
-+
-+ Key size limit
-+ The key size limit gives the size of the largest public key that
-+ can be legally used for encryption in cipher suites that are
-+ exportable.
-+
-+ Key Expanded Effective IV Block
-+ Cipher Type Material Key Material Key Bits Size Size
-+
-+ NULL * Stream 0 0 0 0 N/A
-+ IDEA_CBC Block 16 16 128 8 8
-+ RC2_CBC_40 * Block 5 16 40 8 8
-+ RC4_40 * Stream 5 16 40 0 N/A
-+ RC4_128 Stream 16 16 128 0 N/A
-+ DES40_CBC * Block 5 8 40 8 8
-+ DES_CBC Block 8 8 56 8 8
-+ 3DES_EDE_CBC Block 24 24 168 8 8
-+
-+ * Indicates IsExportable is true.
-+
-+ Type
-+ Indicates whether this is a stream cipher or a block cipher
-+ running in CBC mode.
-+
-+ Key Material
-+ The number of bytes from the key_block that are used for
-+ generating the write keys.
-+
-+ Expanded Key Material
-+ The number of bytes actually fed into the encryption algorithm
-+
-+ Effective Key Bits
-+ How much entropy material is in the key material being fed into
-+ the encryption routines.
-+
-+ IV Size
-+ How much data needs to be generated for the initialization
-+ vector. Zero for stream ciphers; equal to the block size for
-+ block ciphers.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 62]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Block Size
-+ The amount of data a block cipher enciphers in one chunk; a
-+ block cipher running in CBC mode can only encrypt an even
-+ multiple of its block size.
-+
-+ Hash Hash Padding
-+ function Size Size
-+ NULL 0 0
-+ MD5 16 48
-+ SHA 20 40
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 63]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ D. Implementation Notes
-+
-+ The TLS protocol cannot prevent many common security mistakes. This
-+ section provides several recommendations to assist implementors.
-+
-+ D.1. Temporary RSA keys
-+
-+ US Export restrictions limit RSA keys used for encryption to 512
-+ bits, but do not place any limit on lengths of RSA keys used for
-+ signing operations. Certificates often need to be larger than 512
-+ bits, since 512-bit RSA keys are not secure enough for high-value
-+ transactions or for applications requiring long-term security. Some
-+ certificates are also designated signing-only, in which case they
-+ cannot be used for key exchange.
-+
-+ When the public key in the certificate cannot be used for encryption,
-+ the server signs a temporary RSA key, which is then exchanged. In
-+ exportable applications, the temporary RSA key should be the maximum
-+ allowable length (i.e., 512 bits). Because 512-bit RSA keys are
-+ relatively insecure, they should be changed often. For typical
-+ electronic commerce applications, it is suggested that keys be
-+ changed daily or every 500 transactions, and more often if possible.
-+ Note that while it is acceptable to use the same temporary key for
-+ multiple transactions, it must be signed each time it is used.
-+
-+ RSA key generation is a time-consuming process. In many cases, a
-+ low-priority process can be assigned the task of key generation.
-+
-+ Whenever a new key is completed, the existing temporary key can be
-+ replaced with the new one.
-+
-+ D.2. Random Number Generation and Seeding
-+
-+ TLS requires a cryptographically-secure pseudorandom number generator
-+ (PRNG). Care must be taken in designing and seeding PRNGs. PRNGs
-+ based on secure hash operations, most notably MD5 and/or SHA, are
-+ acceptable, but cannot provide more security than the size of the
-+ random number generator state. (For example, MD5-based PRNGs usually
-+ provide 128 bits of state.)
-+
-+ To estimate the amount of seed material being produced, add the
-+ number of bits of unpredictable information in each seed byte. For
-+ example, keystroke timing values taken from a PC compatible's 18.2 Hz
-+ timer provide 1 or 2 secure bits each, even though the total size of
-+ the counter value is 16 bits or more. To seed a 128-bit PRNG, one
-+ would thus require approximately 100 such timer values.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 64]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Warning: The seeding functions in RSAREF and versions of BSAFE prior to
-+ 3.0 are order-independent. For example, if 1000 seed bits are
-+ supplied, one at a time, in 1000 separate calls to the seed
-+ function, the PRNG will end up in a state which depends only
-+ on the number of 0 or 1 seed bits in the seed data (i.e.,
-+ there are 1001 possible final states). Applications using
-+ BSAFE or RSAREF must take extra care to ensure proper seeding.
-+ This may be accomplished by accumulating seed bits into a
-+ buffer and processing them all at once or by processing an
-+ incrementing counter with every seed bit; either method will
-+ reintroduce order dependence into the seeding process.
-+
-+ D.3. Certificates and authentication
-+
-+ Implementations are responsible for verifying the integrity of
-+ certificates and should generally support certificate revocation
-+ messages. Certificates should always be verified to ensure proper
-+ signing by a trusted Certificate Authority (CA). The selection and
-+ addition of trusted CAs should be done very carefully. Users should
-+ be able to view information about the certificate and root CA.
-+
-+ D.4. CipherSuites
-+
-+ TLS supports a range of key sizes and security levels, including some
-+ which provide no or minimal security. A proper implementation will
-+ probably not support many cipher suites. For example, 40-bit
-+ encryption is easily broken, so implementations requiring strong
-+ security should not allow 40-bit keys. Similarly, anonymous Diffie-
-+ Hellman is strongly discouraged because it cannot prevent man-in-
-+ the-middle attacks. Applications should also enforce minimum and
-+ maximum key sizes. For example, certificate chains containing 512-bit
-+ RSA keys or signatures are not appropriate for high-security
-+ applications.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 65]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ E. Backward Compatibility With SSL
-+
-+ For historical reasons and in order to avoid a profligate consumption
-+ of reserved port numbers, application protocols which are secured by
-+ TLS 1.0, SSL 3.0, and SSL 2.0 all frequently share the same
-+ connection port: for example, the https protocol (HTTP secured by SSL
-+ or TLS) uses port 443 regardless of which security protocol it is
-+ using. Thus, some mechanism must be determined to distinguish and
-+ negotiate among the various protocols.
-+
-+ TLS version 1.0 and SSL 3.0 are very similar; thus, supporting both
-+ is easy. TLS clients who wish to negotiate with SSL 3.0 servers
-+ should send client hello messages using the SSL 3.0 record format and
-+ client hello structure, sending {3, 1} for the version field to note
-+ that they support TLS 1.0. If the server supports only SSL 3.0, it
-+ will respond with an SSL 3.0 server hello; if it supports TLS, with a
-+ TLS server hello. The negotiation then proceeds as appropriate for
-+ the negotiated protocol.
-+
-+ Similarly, a TLS server which wishes to interoperate with SSL 3.0
-+ clients should accept SSL 3.0 client hello messages and respond with
-+ an SSL 3.0 server hello if an SSL 3.0 client hello is received which
-+ has a version field of {3, 0}, denoting that this client does not
-+ support TLS.
-+
-+ Whenever a client already knows the highest protocol known to a
-+ server (for example, when resuming a session), it should initiate the
-+ connection in that native protocol.
-+
-+ TLS 1.0 clients that support SSL Version 2.0 servers must send SSL
-+ Version 2.0 client hello messages [SSL2]. TLS servers should accept
-+ either client hello format if they wish to support SSL 2.0 clients on
-+ the same connection port. The only deviations from the Version 2.0
-+ specification are the ability to specify a version with a value of
-+ three and the support for more ciphering types in the CipherSpec.
-+
-+ Warning: The ability to send Version 2.0 client hello messages will be
-+ phased out with all due haste. Implementors should make every
-+ effort to move forward as quickly as possible. Version 3.0
-+ provides better mechanisms for moving to newer versions.
-+
-+ The following cipher specifications are carryovers from SSL Version
-+ 2.0. These are assumed to use RSA for key exchange and
-+ authentication.
-+
-+ V2CipherSpec TLS_RC4_128_WITH_MD5 = { 0x01,0x00,0x80 };
-+ V2CipherSpec TLS_RC4_128_EXPORT40_WITH_MD5 = { 0x02,0x00,0x80 };
-+ V2CipherSpec TLS_RC2_CBC_128_CBC_WITH_MD5 = { 0x03,0x00,0x80 };
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 66]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ V2CipherSpec TLS_RC2_CBC_128_CBC_EXPORT40_WITH_MD5
-+ = { 0x04,0x00,0x80 };
-+ V2CipherSpec TLS_IDEA_128_CBC_WITH_MD5 = { 0x05,0x00,0x80 };
-+ V2CipherSpec TLS_DES_64_CBC_WITH_MD5 = { 0x06,0x00,0x40 };
-+ V2CipherSpec TLS_DES_192_EDE3_CBC_WITH_MD5 = { 0x07,0x00,0xC0 };
-+
-+ Cipher specifications native to TLS can be included in Version 2.0
-+ client hello messages using the syntax below. Any V2CipherSpec
-+ element with its first byte equal to zero will be ignored by Version
-+ 2.0 servers. Clients sending any of the above V2CipherSpecs should
-+ also include the TLS equivalent (see Appendix A.5):
-+
-+ V2CipherSpec (see TLS name) = { 0x00, CipherSuite };
-+
-+ E.1. Version 2 client hello
-+
-+ The Version 2.0 client hello message is presented below using this
-+ document's presentation model. The true definition is still assumed
-+ to be the SSL Version 2.0 specification.
-+
-+ uint8 V2CipherSpec[3];
-+
-+ struct {
-+ uint8 msg_type;
-+ Version version;
-+ uint16 cipher_spec_length;
-+ uint16 session_id_length;
-+ uint16 challenge_length;
-+ V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
-+ opaque session_id[V2ClientHello.session_id_length];
-+ Random challenge;
-+ } V2ClientHello;
-+
-+ msg_type
-+ This field, in conjunction with the version field, identifies a
-+ version 2 client hello message. The value should be one (1).
-+
-+ version
-+ The highest version of the protocol supported by the client
-+ (equals ProtocolVersion.version, see Appendix A.1).
-+
-+ cipher_spec_length
-+ This field is the total length of the field cipher_specs. It
-+ cannot be zero and must be a multiple of the V2CipherSpec length
-+ (3).
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 67]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ session_id_length
-+ This field must have a value of either zero or 16. If zero, the
-+ client is creating a new session. If 16, the session_id field
-+ will contain the 16 bytes of session identification.
-+
-+ challenge_length
-+ The length in bytes of the client's challenge to the server to
-+ authenticate itself. This value must be 32.
-+
-+ cipher_specs
-+ This is a list of all CipherSpecs the client is willing and able
-+ to use. There must be at least one CipherSpec acceptable to the
-+ server.
-+
-+ session_id
-+ If this field's length is not zero, it will contain the
-+ identification for a session that the client wishes to resume.
-+
-+ challenge
-+ The client challenge to the server for the server to identify
-+ itself is a (nearly) arbitrary length random. The TLS server will
-+ right justify the challenge data to become the ClientHello.random
-+ data (padded with leading zeroes, if necessary), as specified in
-+ this protocol specification. If the length of the challenge is
-+ greater than 32 bytes, only the last 32 bytes are used. It is
-+ legitimate (but not necessary) for a V3 server to reject a V2
-+ ClientHello that has fewer than 16 bytes of challenge data.
-+
-+ Note: Requests to resume a TLS session should use a TLS client hello.
-+
-+ E.2. Avoiding man-in-the-middle version rollback
-+
-+ When TLS clients fall back to Version 2.0 compatibility mode, they
-+ should use special PKCS #1 block formatting. This is done so that TLS
-+ servers will reject Version 2.0 sessions with TLS-capable clients.
-+
-+ When TLS clients are in Version 2.0 compatibility mode, they set the
-+ right-hand (least-significant) 8 random bytes of the PKCS padding
-+ (not including the terminal null of the padding) for the RSA
-+ encryption of the ENCRYPTED-KEY-DATA field of the CLIENT-MASTER-KEY
-+ to 0x03 (the other padding bytes are random). After decrypting the
-+ ENCRYPTED-KEY-DATA field, servers that support TLS should issue an
-+ error if these eight padding bytes are 0x03. Version 2.0 servers
-+ receiving blocks padded in this manner will proceed normally.
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 68]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ F. Security analysis
-+
-+ The TLS protocol is designed to establish a secure connection between
-+ a client and a server communicating over an insecure channel. This
-+ document makes several traditional assumptions, including that
-+ attackers have substantial computational resources and cannot obtain
-+ secret information from sources outside the protocol. Attackers are
-+ assumed to have the ability to capture, modify, delete, replay, and
-+ otherwise tamper with messages sent over the communication channel.
-+ This appendix outlines how TLS has been designed to resist a variety
-+ of attacks.
-+
-+ F.1. Handshake protocol
-+
-+ The handshake protocol is responsible for selecting a CipherSpec and
-+ generating a Master Secret, which together comprise the primary
-+ cryptographic parameters associated with a secure session. The
-+ handshake protocol can also optionally authenticate parties who have
-+ certificates signed by a trusted certificate authority.
-+
-+ F.1.1. Authentication and key exchange
-+
-+ TLS supports three authentication modes: authentication of both
-+ parties, server authentication with an unauthenticated client, and
-+ total anonymity. Whenever the server is authenticated, the channel is
-+ secure against man-in-the-middle attacks, but completely anonymous
-+ sessions are inherently vulnerable to such attacks. Anonymous
-+ servers cannot authenticate clients. If the server is authenticated,
-+ its certificate message must provide a valid certificate chain
-+ leading to an acceptable certificate authority. Similarly,
-+ authenticated clients must supply an acceptable certificate to the
-+ server. Each party is responsible for verifying that the other's
-+ certificate is valid and has not expired or been revoked.
-+
-+ The general goal of the key exchange process is to create a
-+ pre_master_secret known to the communicating parties and not to
-+ attackers. The pre_master_secret will be used to generate the
-+ master_secret (see Section 8.1). The master_secret is required to
-+ generate the certificate verify and finished messages, encryption
-+ keys, and MAC secrets (see Sections 7.4.8, 7.4.9 and 6.3). By sending
-+ a correct finished message, parties thus prove that they know the
-+ correct pre_master_secret.
-+
-+ F.1.1.1. Anonymous key exchange
-+
-+ Completely anonymous sessions can be established using RSA or
-+ Diffie-Hellman for key exchange. With anonymous RSA, the client
-+ encrypts a pre_master_secret with the server's uncertified public key
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 69]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ extracted from the server key exchange message. The result is sent in
-+ a client key exchange message. Since eavesdroppers do not know the
-+ server's private key, it will be infeasible for them to decode the
-+ pre_master_secret. (Note that no anonymous RSA Cipher Suites are
-+ defined in this document).
-+
-+ With Diffie-Hellman, the server's public parameters are contained in
-+ the server key exchange message and the client's are sent in the
-+ client key exchange message. Eavesdroppers who do not know the
-+ private values should not be able to find the Diffie-Hellman result
-+ (i.e. the pre_master_secret).
-+
-+ Warning: Completely anonymous connections only provide protection
-+ against passive eavesdropping. Unless an independent tamper-
-+ proof channel is used to verify that the finished messages
-+ were not replaced by an attacker, server authentication is
-+ required in environments where active man-in-the-middle
-+ attacks are a concern.
-+
-+ F.1.1.2. RSA key exchange and authentication
-+
-+ With RSA, key exchange and server authentication are combined. The
-+ public key may be either contained in the server's certificate or may
-+ be a temporary RSA key sent in a server key exchange message. When
-+ temporary RSA keys are used, they are signed by the server's RSA or
-+ DSS certificate. The signature includes the current
-+ ClientHello.random, so old signatures and temporary keys cannot be
-+ replayed. Servers may use a single temporary RSA key for multiple
-+ negotiation sessions.
-+
-+ Note: The temporary RSA key option is useful if servers need large
-+ certificates but must comply with government-imposed size limits
-+ on keys used for key exchange.
-+
-+ After verifying the server's certificate, the client encrypts a
-+ pre_master_secret with the server's public key. By successfully
-+ decoding the pre_master_secret and producing a correct finished
-+ message, the server demonstrates that it knows the private key
-+ corresponding to the server certificate.
-+
-+ When RSA is used for key exchange, clients are authenticated using
-+ the certificate verify message (see Section 7.4.8). The client signs
-+ a value derived from the master_secret and all preceding handshake
-+ messages. These handshake messages include the server certificate,
-+ which binds the signature to the server, and ServerHello.random,
-+ which binds the signature to the current handshake process.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 70]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ F.1.1.3. Diffie-Hellman key exchange with authentication
-+
-+ When Diffie-Hellman key exchange is used, the server can either
-+ supply a certificate containing fixed Diffie-Hellman parameters or
-+ can use the server key exchange message to send a set of temporary
-+ Diffie-Hellman parameters signed with a DSS or RSA certificate.
-+ Temporary parameters are hashed with the hello.random values before
-+ signing to ensure that attackers do not replay old parameters. In
-+ either case, the client can verify the certificate or signature to
-+ ensure that the parameters belong to the server.
-+
-+ If the client has a certificate containing fixed Diffie-Hellman
-+ parameters, its certificate contains the information required to
-+ complete the key exchange. Note that in this case the client and
-+ server will generate the same Diffie-Hellman result (i.e.,
-+ pre_master_secret) every time they communicate. To prevent the
-+ pre_master_secret from staying in memory any longer than necessary,
-+ it should be converted into the master_secret as soon as possible.
-+ Client Diffie-Hellman parameters must be compatible with those
-+ supplied by the server for the key exchange to work.
-+
-+ If the client has a standard DSS or RSA certificate or is
-+ unauthenticated, it sends a set of temporary parameters to the server
-+ in the client key exchange message, then optionally uses a
-+ certificate verify message to authenticate itself.
-+
-+ F.1.2. Version rollback attacks
-+
-+ Because TLS includes substantial improvements over SSL Version 2.0,
-+ attackers may try to make TLS-capable clients and servers fall back
-+ to Version 2.0. This attack can occur if (and only if) two TLS-
-+ capable parties use an SSL 2.0 handshake.
-+
-+ Although the solution using non-random PKCS #1 block type 2 message
-+ padding is inelegant, it provides a reasonably secure way for Version
-+ 3.0 servers to detect the attack. This solution is not secure against
-+ attackers who can brute force the key and substitute a new
-+ ENCRYPTED-KEY-DATA message containing the same key (but with normal
-+ padding) before the application specified wait threshold has expired.
-+ Parties concerned about attacks of this scale should not be using
-+ 40-bit encryption keys anyway. Altering the padding of the least-
-+ significant 8 bytes of the PKCS padding does not impact security for
-+ the size of the signed hashes and RSA key lengths used in the
-+ protocol, since this is essentially equivalent to increasing the
-+ input block size by 8 bytes.
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 71]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ F.1.3. Detecting attacks against the handshake protocol
-+
-+ An attacker might try to influence the handshake exchange to make the
-+ parties select different encryption algorithms than they would
-+ normally choose. Because many implementations will support 40-bit
-+ exportable encryption and some may even support null encryption or
-+ MAC algorithms, this attack is of particular concern.
-+
-+ For this attack, an attacker must actively change one or more
-+ handshake messages. If this occurs, the client and server will
-+ compute different values for the handshake message hashes. As a
-+ result, the parties will not accept each others' finished messages.
-+ Without the master_secret, the attacker cannot repair the finished
-+ messages, so the attack will be discovered.
-+
-+ F.1.4. Resuming sessions
-+
-+ When a connection is established by resuming a session, new
-+ ClientHello.random and ServerHello.random values are hashed with the
-+ session's master_secret. Provided that the master_secret has not been
-+ compromised and that the secure hash operations used to produce the
-+ encryption keys and MAC secrets are secure, the connection should be
-+ secure and effectively independent from previous connections.
-+ Attackers cannot use known encryption keys or MAC secrets to
-+ compromise the master_secret without breaking the secure hash
-+ operations (which use both SHA and MD5).
-+
-+ Sessions cannot be resumed unless both the client and server agree.
-+ If either party suspects that the session may have been compromised,
-+ or that certificates may have expired or been revoked, it should
-+ force a full handshake. An upper limit of 24 hours is suggested for
-+ session ID lifetimes, since an attacker who obtains a master_secret
-+ may be able to impersonate the compromised party until the
-+ corresponding session ID is retired. Applications that may be run in
-+ relatively insecure environments should not write session IDs to
-+ stable storage.
-+
-+ F.1.5. MD5 and SHA
-+
-+ TLS uses hash functions very conservatively. Where possible, both MD5
-+ and SHA are used in tandem to ensure that non-catastrophic flaws in
-+ one algorithm will not break the overall protocol.
-+
-+ F.2. Protecting application data
-+
-+ The master_secret is hashed with the ClientHello.random and
-+ ServerHello.random to produce unique data encryption keys and MAC
-+ secrets for each connection.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 72]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Outgoing data is protected with a MAC before transmission. To prevent
-+ message replay or modification attacks, the MAC is computed from the
-+ MAC secret, the sequence number, the message length, the message
-+ contents, and two fixed character strings. The message type field is
-+ necessary to ensure that messages intended for one TLS Record Layer
-+ client are not redirected to another. The sequence number ensures
-+ that attempts to delete or reorder messages will be detected. Since
-+ sequence numbers are 64-bits long, they should never overflow.
-+ Messages from one party cannot be inserted into the other's output,
-+ since they use independent MAC secrets. Similarly, the server-write
-+ and client-write keys are independent so stream cipher keys are used
-+ only once.
-+
-+ If an attacker does break an encryption key, all messages encrypted
-+ with it can be read. Similarly, compromise of a MAC key can make
-+ message modification attacks possible. Because MACs are also
-+ encrypted, message-alteration attacks generally require breaking the
-+ encryption algorithm as well as the MAC.
-+
-+ Note: MAC secrets may be larger than encryption keys, so messages can
-+ remain tamper resistant even if encryption keys are broken.
-+
-+ F.3. Final notes
-+
-+ For TLS to be able to provide a secure connection, both the client
-+ and server systems, keys, and applications must be secure. In
-+ addition, the implementation must be free of security errors.
-+
-+ The system is only as strong as the weakest key exchange and
-+ authentication algorithm supported, and only trustworthy
-+ cryptographic functions should be used. Short public keys, 40-bit
-+ bulk encryption keys, and anonymous servers should be used with great
-+ caution. Implementations and users must be careful when deciding
-+ which certificates and certificate authorities are acceptable; a
-+ dishonest certificate authority can do tremendous damage.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 73]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ G. Patent Statement
-+
-+ Some of the cryptographic algorithms proposed for use in this
-+ protocol have patent claims on them. In addition Netscape
-+ Communications Corporation has a patent claim on the Secure Sockets
-+ Layer (SSL) work that this standard is based on. The Internet
-+ Standards Process as defined in RFC 2026 requests that a statement be
-+ obtained from a Patent holder indicating that a license will be made
-+ available to applicants under reasonable terms and conditions.
-+
-+ The Massachusetts Institute of Technology has granted RSA Data
-+ Security, Inc., exclusive sub-licensing rights to the following
-+ patent issued in the United States:
-+
-+ Cryptographic Communications System and Method ("RSA"), No.
-+ 4,405,829
-+
-+ Netscape Communications Corporation has been issued the following
-+ patent in the United States:
-+
-+ Secure Socket Layer Application Program Apparatus And Method
-+ ("SSL"), No. 5,657,390
-+
-+ Netscape Communications has issued the following statement:
-+
-+ Intellectual Property Rights
-+
-+ Secure Sockets Layer
-+
-+ The United States Patent and Trademark Office ("the PTO")
-+ recently issued U.S. Patent No. 5,657,390 ("the SSL Patent") to
-+ Netscape for inventions described as Secure Sockets Layers
-+ ("SSL"). The IETF is currently considering adopting SSL as a
-+ transport protocol with security features. Netscape encourages
-+ the royalty-free adoption and use of the SSL protocol upon the
-+ following terms and conditions:
-+
-+ * If you already have a valid SSL Ref license today which
-+ includes source code from Netscape, an additional patent
-+ license under the SSL patent is not required.
-+
-+ * If you don't have an SSL Ref license, you may have a royalty
-+ free license to build implementations covered by the SSL
-+ Patent Claims or the IETF TLS specification provided that you
-+ do not to assert any patent rights against Netscape or other
-+ companies for the implementation of SSL or the IETF TLS
-+ recommendation.
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 74]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ What are "Patent Claims":
-+
-+ Patent claims are claims in an issued foreign or domestic patent
-+ that:
-+
-+ 1) must be infringed in order to implement methods or build
-+ products according to the IETF TLS specification; or
-+
-+ 2) patent claims which require the elements of the SSL patent
-+ claims and/or their equivalents to be infringed.
-+
-+ The Internet Society, Internet Architecture Board, Internet
-+ Engineering Steering Group and the Corporation for National Research
-+ Initiatives take no position on the validity or scope of the patents
-+ and patent applications, nor on the appropriateness of the terms of
-+ the assurance. The Internet Society and other groups mentioned above
-+ have not made any determination as to any other intellectual property
-+ rights which may apply to the practice of this standard. Any further
-+ consideration of these matters is the user's own responsibility.
-+
-+ Security Considerations
-+
-+ Security issues are discussed throughout this memo.
-+
-+ References
-+
-+ [3DES] W. Tuchman, "Hellman Presents No Shortcut Solutions To DES,"
-+ IEEE Spectrum, v. 16, n. 7, July 1979, pp40-41.
-+
-+ [BLEI] Bleichenbacher D., "Chosen Ciphertext Attacks against
-+ Protocols Based on RSA Encryption Standard PKCS #1" in
-+ Advances in Cryptology -- CRYPTO'98, LNCS vol. 1462, pages:
-+ 1--12, 1998.
-+
-+ [DES] ANSI X3.106, "American National Standard for Information
-+ Systems-Data Link Encryption," American National Standards
-+ Institute, 1983.
-+
-+ [DH1] W. Diffie and M. E. Hellman, "New Directions in
-+ Cryptography," IEEE Transactions on Information Theory, V.
-+ IT-22, n. 6, Jun 1977, pp. 74-84.
-+
-+ [DSS] NIST FIPS PUB 186, "Digital Signature Standard," National
-+ Institute of Standards and Technology, U.S. Department of
-+ Commerce, May 18, 1994.
-+
-+ [FTP] Postel J., and J. Reynolds, "File Transfer Protocol", STD 9,
-+ RFC 959, October 1985.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 75]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ [HTTP] Berners-Lee, T., Fielding, R., and H. Frystyk, "Hypertext
-+ Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
-+
-+ [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
-+ Hashing for Message Authentication," RFC 2104, February
-+ 1997.
-+
-+ [IDEA] X. Lai, "On the Design and Security of Block Ciphers," ETH
-+ Series in Information Processing, v. 1, Konstanz: Hartung-
-+ Gorre Verlag, 1992.
-+
-+ [MD2] Kaliski, B., "The MD2 Message Digest Algorithm", RFC 1319,
-+ April 1992.
-+
-+ [MD5] Rivest, R., "The MD5 Message Digest Algorithm", RFC 1321,
-+ April 1992.
-+
-+ [PKCS1] RSA Laboratories, "PKCS #1: RSA Encryption Standard,"
-+ version 1.5, November 1993.
-+
-+ [PKCS6] RSA Laboratories, "PKCS #6: RSA Extended Certificate Syntax
-+ Standard," version 1.5, November 1993.
-+
-+ [PKCS7] RSA Laboratories, "PKCS #7: RSA Cryptographic Message Syntax
-+ Standard," version 1.5, November 1993.
-+
-+ [PKIX] Housley, R., Ford, W., Polk, W. and D. Solo, "Internet
-+ Public Key Infrastructure: Part I: X.509 Certificate and CRL
-+ Profile", RFC 2459, January 1999.
-+
-+ [RC2] Rivest, R., "A Description of the RC2(r) Encryption
-+ Algorithm", RFC 2268, January 1998.
-+
-+ [RC4] Thayer, R. and K. Kaukonen, A Stream Cipher Encryption
-+ Algorithm, Work in Progress.
-+
-+ [RSA] R. Rivest, A. Shamir, and L. M. Adleman, "A Method for
-+ Obtaining Digital Signatures and Public-Key Cryptosystems,"
-+ Communications of the ACM, v. 21, n. 2, Feb 1978, pp. 120-
-+ 126.
-+
-+ [RSADSI] Contact RSA Data Security, Inc., Tel: 415-595-8782
-+
-+ [SCH] B. Schneier. Applied Cryptography: Protocols, Algorithms,
-+ and Source Code in C, Published by John Wiley & Sons, Inc.
-+ 1994.
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 76]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ [SHA] NIST FIPS PUB 180-1, "Secure Hash Standard," National
-+ Institute of Standards and Technology, U.S. Department of
-+ Commerce, Work in Progress, May 31, 1994.
-+
-+ [SSL2] Hickman, Kipp, "The SSL Protocol", Netscape Communications
-+ Corp., Feb 9, 1995.
-+
-+ [SSL3] A. Frier, P. Karlton, and P. Kocher, "The SSL 3.0 Protocol",
-+ Netscape Communications Corp., Nov 18, 1996.
-+
-+ [TCP] Postel, J., "Transmission Control Protocol," STD 7, RFC 793,
-+ September 1981.
-+
-+ [TEL] Postel J., and J. Reynolds, "Telnet Protocol
-+ Specifications", STD 8, RFC 854, May 1993.
-+
-+ [TEL] Postel J., and J. Reynolds, "Telnet Option Specifications",
-+ STD 8, RFC 855, May 1993.
-+
-+ [X509] CCITT. Recommendation X.509: "The Directory - Authentication
-+ Framework". 1988.
-+
-+ [XDR] R. Srinivansan, Sun Microsystems, RFC-1832: XDR: External
-+ Data Representation Standard, August 1995.
-+
-+ Credits
-+
-+ Win Treese
-+ Open Market
-+
-+ EMail: treese@openmarket.com
-+
-+
-+ Editors
-+
-+ Christopher Allen Tim Dierks
-+ Certicom Certicom
-+
-+ EMail: callen@certicom.com EMail: tdierks@certicom.com
-+
-+
-+ Authors' Addresses
-+
-+ Tim Dierks Philip L. Karlton
-+ Certicom Netscape Communications
-+
-+ EMail: tdierks@certicom.com
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 77]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Alan O. Freier Paul C. Kocher
-+ Netscape Communications Independent Consultant
-+
-+ EMail: freier@netscape.com EMail: pck@netcom.com
-+
-+
-+ Other contributors
-+
-+ Martin Abadi Robert Relyea
-+ Digital Equipment Corporation Netscape Communications
-+
-+ EMail: ma@pa.dec.com EMail: relyea@netscape.com
-+
-+ Ran Canetti Jim Roskind
-+ IBM Watson Research Center Netscape Communications
-+
-+ EMail: canetti@watson.ibm.com EMail: jar@netscape.com
-+
-+
-+ Taher Elgamal Micheal J. Sabin, Ph. D.
-+ Securify Consulting Engineer
-+
-+ EMail: elgamal@securify.com EMail: msabin@netcom.com
-+
-+
-+ Anil R. Gangolli Dan Simon
-+ Structured Arts Computing Corp. Microsoft
-+
-+ EMail: gangolli@structuredarts.com EMail: dansimon@microsoft.com
-+
-+
-+ Kipp E.B. Hickman Tom Weinstein
-+ Netscape Communications Netscape Communications
-+
-+ EMail: kipp@netscape.com EMail: tomw@netscape.com
-+
-+
-+ Hugo Krawczyk
-+ IBM Watson Research Center
-+
-+ EMail: hugo@watson.ibm.com
-+
-+ Comments
-+
-+ The discussion list for the IETF TLS working group is located at the
-+ e-mail address <ietf-tls@lists.consensus.com>. Information on the
-+ group and information on how to subscribe to the list is at
-+ <http://lists.consensus.com/>.
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 78]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Archives of the list can be found at:
-+ <http://www.imc.org/ietf-tls/mail-archive/>
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 79]
-+ \f
-+ RFC 2246 The TLS Protocol Version 1.0 January 1999
-+
-+
-+ Full Copyright Statement
-+
-+ Copyright (C) The Internet Society (1999). All Rights Reserved.
-+
-+ This document and translations of it may be copied and furnished to
-+ others, and derivative works that comment on or otherwise explain it
-+ or assist in its implementation may be prepared, copied, published
-+ and distributed, in whole or in part, without restriction of any
-+ kind, provided that the above copyright notice and this paragraph are
-+ included on all such copies and derivative works. However, this
-+ document itself may not be modified in any way, such as by removing
-+ the copyright notice or references to the Internet Society or other
-+ Internet organizations, except as needed for the purpose of
-+ developing Internet standards in which case the procedures for
-+ copyrights defined in the Internet Standards process must be
-+ followed, or as required to translate it into languages other than
-+ English.
-+
-+ The limited permissions granted above are perpetual and will not be
-+ revoked by the Internet Society or its successors or assigns.
-+
-+ This document and the information contained herein is provided on an
-+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
-+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Dierks & Allen Standards Track [Page 80]
-+ \f
-diff -Pcr postfix-2.0.16/pfixtls/doc/rfc2487.txt postfix-2.0.16-ti1.20/pfixtls/doc/rfc2487.txt
-*** postfix-2.0.16/pfixtls/doc/rfc2487.txt Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/rfc2487.txt Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,451 ----
-+
-+
-+
-+
-+
-+
-+ Network Working Group P. Hoffman
-+ Request for Comments: 2487 Internet Mail Consortium
-+ Category: Standards Track January 1999
-+
-+
-+ SMTP Service Extension for Secure SMTP over TLS
-+
-+ Status of this Memo
-+
-+ This document specifies an Internet standards track protocol for the
-+ Internet community, and requests discussion and suggestions for
-+ improvements. Please refer to the current edition of the "Internet
-+ Official Protocol Standards" (STD 1) for the standardization state
-+ and status of this protocol. Distribution of this memo is unlimited.
-+
-+ Copyright Notice
-+
-+ Copyright (C) The Internet Society (1999). All Rights Reserved.
-+
-+ 1. Abstract
-+
-+ This document describes an extension to the SMTP service that allows
-+ an SMTP server and client to use transport-layer security to provide
-+ private, authenticated communication over the Internet. This gives
-+ SMTP agents the ability to protect some or all of their
-+ communications from eavesdroppers and attackers.
-+
-+ 2. Introduction
-+
-+ SMTP [RFC-821] servers and clients normally communicate in the clear
-+ over the Internet. In many cases, this communication goes through one
-+ or more router that is not controlled or trusted by either entity.
-+ Such an untrusted router might allow a third party to monitor or
-+ alter the communications between the server and client.
-+
-+ Further, there is often a desire for two SMTP agents to be able to
-+ authenticate each others' identities. For example, a secure SMTP
-+ server might only allow communications from other SMTP agents it
-+ knows, or it might act differently for messages received from an
-+ agent it knows than from one it doesn't know.
-+
-+ TLS [TLS], more commonly known as SSL, is a popular mechanism for
-+ enhancing TCP communications with privacy and authentication. TLS is
-+ in wide use with the HTTP protocol, and is also being used for adding
-+ security to many other common protocols that run over TCP.
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 1]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ 2.1 Terminology
-+
-+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
-+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
-+ document are to be interpreted as described in [RFC-2119].
-+
-+ 3. STARTTLS Extension
-+
-+ The STARTTLS extension to SMTP is laid out as follows:
-+
-+ (1) the name of the SMTP service defined here is STARTTLS;
-+
-+ (2) the EHLO keyword value associated with the extension is STARTTLS;
-+
-+ (3) the STARTTLS keyword has no parameters;
-+
-+ (4) a new SMTP verb, "STARTTLS", is defined;
-+
-+ (5) no additional parameters are added to any SMTP command.
-+
-+ 4. The STARTTLS Keyword
-+
-+ The STARTTLS keyword is used to tell the SMTP client that the SMTP
-+ server allows use of TLS. It takes no parameters.
-+
-+ 5. The STARTTLS Command
-+
-+ The format for the STARTTLS command is:
-+
-+ STARTTLS
-+
-+ with no parameters.
-+
-+ After the client gives the STARTTLS command, the server responds with
-+ one of the following reply codes:
-+
-+ 220 Ready to start TLS
-+ 501 Syntax error (no parameters allowed)
-+ 454 TLS not available due to temporary reason
-+
-+ A publicly-referenced SMTP server MUST NOT require use of the
-+ STARTTLS extension in order to deliver mail locally. This rule
-+ prevents the STARTTLS extension from damaging the interoperability of
-+ the Internet's SMTP infrastructure. A publicly-referenced SMTP server
-+ is an SMTP server which runs on port 25 of an Internet host listed in
-+ the MX record (or A record if an MX record is not present) for the
-+ domain name on the right hand side of an Internet mail address.
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 2]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ Any SMTP server may refuse to accept messages for relay based on
-+ authentication supplied during the TLS negotiation. An SMTP server
-+ that is not publicly referenced may refuse to accept any messages for
-+ relay or local delivery based on authentication supplied during the
-+ TLS negotiation.
-+
-+ A SMTP server that is not publicly referenced may choose to require
-+ that the client perform a TLS negotiation before accepting any
-+ commands. In this case, the server SHOULD return the reply code:
-+
-+ 530 Must issue a STARTTLS command first
-+
-+ to every command other than NOOP, EHLO, STARTTLS, or QUIT. If the
-+ client and server are using the ENHANCEDSTATUSCODES ESMTP extension
-+ [RFC-2034], the status code to be returned SHOULD be 5.7.0.
-+
-+ After receiving a 220 response to a STARTTLS command, the client
-+ SHOULD start the TLS negotiation before giving any other SMTP
-+ commands.
-+
-+ If the SMTP client is using pipelining as defined in RFC 1854, the
-+ STARTTLS command must be the last command in a group.
-+
-+ 5.1 Processing After the STARTTLS Command
-+
-+ After the TLS handshake has been completed, both parties MUST
-+ immediately decide whether or not to continue based on the
-+ authentication and privacy achieved. The SMTP client and server may
-+ decide to move ahead even if the TLS negotiation ended with no
-+ authentication and/or no privacy because most SMTP services are
-+ performed with no authentication and no privacy, but some SMTP
-+ clients or servers may want to continue only if a particular level of
-+ authentication and/or privacy was achieved.
-+
-+ If the SMTP client decides that the level of authentication or
-+ privacy is not high enough for it to continue, it SHOULD issue an
-+ SMTP QUIT command immediately after the TLS negotiation is complete.
-+ If the SMTP server decides that the level of authentication or
-+ privacy is not high enough for it to continue, it SHOULD reply to
-+ every SMTP command from the client (other than a QUIT command) with
-+ the 554 reply code (with a possible text string such as "Command
-+ refused due to lack of security").
-+
-+ The decision of whether or not to believe the authenticity of the
-+ other party in a TLS negotiation is a local matter. However, some
-+ general rules for the decisions are:
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 3]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ - A SMTP client would probably only want to authenticate an SMTP
-+ server whose server certificate has a domain name that is the
-+ domain name that the client thought it was connecting to.
-+ - A publicly-referenced SMTP server would probably want to accept
-+ any certificate from an SMTP client, and would possibly want to
-+ put distinguishing information about the certificate in the
-+ Received header of messages that were relayed or submitted from
-+ the client.
-+
-+ 5.2 Result of the STARTTLS Command
-+
-+ Upon completion of the TLS handshake, the SMTP protocol is reset to
-+ the initial state (the state in SMTP after a server issues a 220
-+ service ready greeting). The server MUST discard any knowledge
-+ obtained from the client, such as the argument to the EHLO command,
-+ which was not obtained from the TLS negotiation itself. The client
-+ MUST discard any knowledge obtained from the server, such as the list
-+ of SMTP service extensions, which was not obtained from the TLS
-+ negotiation itself. The client SHOULD send an EHLO command as the
-+ first command after a successful TLS negotiation.
-+
-+ The list of SMTP service extensions returned in response to an EHLO
-+ command received after the TLS handshake MAY be different than the
-+ list returned before the TLS handshake. For example, an SMTP server
-+ might not want to advertise support for a particular SASL mechanism
-+ [SASL] unless a client has sent an appropriate client certificate
-+ during a TLS handshake.
-+
-+ Both the client and the server MUST know if there is a TLS session
-+ active. A client MUST NOT attempt to start a TLS session if a TLS
-+ session is already active. A server MUST NOT return the TLS extension
-+ in response to an EHLO command received after a TLS handshake has
-+ completed.
-+
-+ 6. Usage Example
-+
-+ The following dialog illustrates how a client and server can start a
-+ TLS session:
-+
-+ S: <waits for connection on TCP port 25>
-+ C: <opens connection>
-+ S: 220 mail.imc.org SMTP service ready
-+ C: EHLO mail.ietf.org
-+ S: 250-mail.imc.org offers a warm hug of welcome
-+ S: 250 STARTTLS
-+ C: STARTTLS
-+ S: 220 Go ahead
-+ C: <starts TLS negotiation>
-+
-+
-+
-+ Hoffman Standards Track [Page 4]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ C & S: <negotiate a TLS session>
-+ C & S: <check result of negotiation>
-+ C: <continues by sending an SMTP command>
-+ . . .
-+
-+ 7. Security Considerations
-+
-+ It should be noted that SMTP is not an end-to-end mechanism. Thus, if
-+ an SMTP client/server pair decide to add TLS privacy, they are not
-+ securing the transport from the originating mail user agent to the
-+ recipient. Further, because delivery of a single piece of mail may
-+ go between more than two SMTP servers, adding TLS privacy to one pair
-+ of servers does not mean that the entire SMTP chain has been made
-+ private. Further, just because an SMTP server can authenticate an
-+ SMTP client, it does not mean that the mail from the SMTP client was
-+ authenticated by the SMTP client when the client received it.
-+
-+ Both the STMP client and server must check the result of the TLS
-+ negotiation to see whether acceptable authentication or privacy was
-+ achieved. Ignoring this step completely invalidates using TLS for
-+ security. The decision about whether acceptable authentication or
-+ privacy was achieved is made locally, is implementation-dependant,
-+ and is beyond the scope of this document.
-+
-+ The SMTP client and server should note carefully the result of the
-+ TLS negotiation. If the negotiation results in no privacy, or if it
-+ results in privacy using algorithms or key lengths that are deemed
-+ not strong enough, or if the authentication is not good enough for
-+ either party, the client may choose to end the SMTP session with an
-+ immediate QUIT command, or the server may choose to not accept any
-+ more SMTP commands.
-+
-+ A server announcing in an EHLO response that it uses a particular TLS
-+ protocol should not pose any security issues, since any use of TLS
-+ will be at least as secure as no use of TLS.
-+
-+ A man-in-the-middle attack can be launched by deleting the "250
-+ STARTTLS" response from the server. This would cause the client not
-+ to try to start a TLS session. An SMTP client can protect against
-+ this attack by recording the fact that a particular SMTP server
-+ offers TLS during one session and generating an alarm if it does not
-+ appear in the EHLO response for a later session. The lack of TLS
-+ during a session SHOULD NOT result in the bouncing of email, although
-+ it could result in delayed processing.
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 5]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ Before the TLS handshake has begun, any protocol interactions are
-+ performed in the clear and may be modified by an active attacker. For
-+ this reason, clients and servers MUST discard any knowledge obtained
-+ prior to the start of the TLS handshake upon completion of the TLS
-+ handshake.
-+
-+ The STARTTLS extension is not suitable for authenticating the author
-+ of an email message unless every hop in the delivery chain, including
-+ the submission to the first SMTP server, is authenticated. Another
-+ proposal [SMTP-AUTH] can be used to authenticate delivery and MIME
-+ security multiparts [MIME-SEC] can be used to authenticate the author
-+ of an email message. In addition, the [SMTP-AUTH] proposal offers
-+ simpler and more flexible options to authenticate an SMTP client and
-+ the SASL EXTERNAL mechanism [SASL] MAY be used in conjunction with
-+ the STARTTLS command to provide an authorization identity.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 6]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ A. References
-+
-+ [RFC-821] Postel, J., "Simple Mail Transfer Protocol", RFC 821,
-+ August 1982.
-+
-+ [RFC-1869] Klensin, J., Freed, N, Rose, M, Stefferud, E. and D.
-+ Crocker, "SMTP Service Extensions", STD 10, RFC 1869,
-+ November 1995.
-+
-+ [RFC-2034] Freed, N., "SMTP Service Extension for Returning Enhanced
-+ Error Codes", RFC 2034, October 1996.
-+
-+ [RFC-2119] Bradner, S., "Key words for use in RFCs to Indicate
-+ Requirement Levels", BCP 14, RFC 2119, March 1997.
-+
-+ [SASL] Myers, J., "Simple Authentication and Security Layer
-+ (SASL)", RFC 2222, October 1997.
-+
-+ [SMTP-AUTH] "SMTP Service Extension for Authentication", Work in
-+ Progress.
-+
-+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
-+ RFC 2246, January 1999.
-+
-+ B. Author's Address
-+
-+ Paul Hoffman
-+ Internet Mail Consortium
-+ 127 Segre Place
-+ Santa Cruz, CA 95060
-+
-+ Phone: (831) 426-9827
-+ EMail: phoffman@imc.org
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 7]
-+ \f
-+ RFC 2487 SMTP Service Extension January 1999
-+
-+
-+ C. Full Copyright Statement
-+
-+ Copyright (C) The Internet Society (1999). All Rights Reserved.
-+
-+ This document and translations of it may be copied and furnished to
-+ others, and derivative works that comment on or otherwise explain it
-+ or assist in its implementation may be prepared, copied, published
-+ and distributed, in whole or in part, without restriction of any
-+ kind, provided that the above copyright notice and this paragraph are
-+ included on all such copies and derivative works. However, this
-+ document itself may not be modified in any way, such as by removing
-+ the copyright notice or references to the Internet Society or other
-+ Internet organizations, except as needed for the purpose of
-+ developing Internet standards in which case the procedures for
-+ copyrights defined in the Internet Standards process must be
-+ followed, or as required to translate it into languages other than
-+ English.
-+
-+ The limited permissions granted above are perpetual and will not be
-+ revoked by the Internet Society or its successors or assigns.
-+
-+ This document and the information contained herein is provided on an
-+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
-+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 8]
-+ \f
-diff -Pcr postfix-2.0.16/pfixtls/doc/rfc3207.txt postfix-2.0.16-ti1.20/pfixtls/doc/rfc3207.txt
-*** postfix-2.0.16/pfixtls/doc/rfc3207.txt Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/rfc3207.txt Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,507 ----
-+
-+
-+
-+
-+
-+
-+ Network Working Group P. Hoffman
-+ Request for Comments: 3207 Internet Mail Consortium
-+ Obsoletes: 2487 February 2002
-+ Category: Standards Track
-+
-+
-+ SMTP Service Extension for
-+ Secure SMTP over Transport Layer Security
-+
-+ Status of this Memo
-+
-+ This document specifies an Internet standards track protocol for the
-+ Internet community, and requests discussion and suggestions for
-+ improvements. Please refer to the current edition of the "Internet
-+ Official Protocol Standards" (STD 1) for the standardization state
-+ and status of this protocol. Distribution of this memo is unlimited.
-+
-+ Copyright Notice
-+
-+ Copyright (C) The Internet Society (2002). All Rights Reserved.
-+
-+ Abstract
-+
-+ This document describes an extension to the SMTP (Simple Mail
-+ Transfer Protocol) service that allows an SMTP server and client to
-+ use TLS (Transport Layer Security) to provide private, authenticated
-+ communication over the Internet. This gives SMTP agents the ability
-+ to protect some or all of their communications from eavesdroppers and
-+ attackers.
-+
-+ 1. Introduction
-+
-+ SMTP [RFC2821] servers and clients normally communicate in the clear
-+ over the Internet. In many cases, this communication goes through
-+ one or more router that is not controlled or trusted by either
-+ entity. Such an untrusted router might allow a third party to
-+ monitor or alter the communications between the server and client.
-+
-+ Further, there is often a desire for two SMTP agents to be able to
-+ authenticate each others' identities. For example, a secure SMTP
-+ server might only allow communications from other SMTP agents it
-+ knows, or it might act differently for messages received from an
-+ agent it knows than from one it doesn't know.
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 1]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ TLS [TLS], more commonly known as SSL, is a popular mechanism for
-+ enhancing TCP communications with privacy and authentication. TLS is
-+ in wide use with the HTTP protocol, and is also being used for adding
-+ security to many other common protocols that run over TCP.
-+
-+ This document obsoletes RFC 2487.
-+
-+ 1.1 Terminology
-+
-+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
-+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
-+ document are to be interpreted as described in [RFC2119].
-+
-+ 2. STARTTLS Extension
-+
-+ The STARTTLS extension to SMTP is laid out as follows:
-+
-+ (1) the name of the SMTP service defined here is STARTTLS;
-+
-+ (2) the EHLO keyword value associated with the extension is STARTTLS;
-+
-+ (3) the STARTTLS keyword has no parameters;
-+
-+ (4) a new SMTP verb, "STARTTLS", is defined;
-+
-+ (5) no additional parameters are added to any SMTP command.
-+
-+ 3. The STARTTLS Keyword
-+
-+ The STARTTLS keyword is used to tell the SMTP client that the SMTP
-+ server is currently able to negotiate the use of TLS. It takes no
-+ parameters.
-+
-+ 4. The STARTTLS Command
-+
-+ The format for the STARTTLS command is:
-+
-+ STARTTLS
-+
-+ with no parameters.
-+
-+ After the client gives the STARTTLS command, the server responds with
-+ one of the following reply codes:
-+
-+ 220 Ready to start TLS
-+ 501 Syntax error (no parameters allowed)
-+ 454 TLS not available due to temporary reason
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 2]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ If the client receives the 454 response, the client must decide
-+ whether or not to continue the SMTP session. Such a decision is
-+ based on local policy. For instance, if TLS was being used for
-+ client authentication, the client might try to continue the session,
-+ in case the server allows it even with no authentication. However,
-+ if TLS was being negotiated for encryption, a client that gets a 454
-+ response needs to decide whether to send the message anyway with no
-+ TLS encryption, whether to wait and try again later, or whether to
-+ give up and notify the sender of the error.
-+
-+ A publicly-referenced SMTP server MUST NOT require use of the
-+ STARTTLS extension in order to deliver mail locally. This rule
-+ prevents the STARTTLS extension from damaging the interoperability of
-+ the Internet's SMTP infrastructure. A publicly-referenced SMTP
-+ server is an SMTP server which runs on port 25 of an Internet host
-+ listed in the MX record (or A record if an MX record is not present)
-+ for the domain name on the right hand side of an Internet mail
-+ address.
-+
-+ Any SMTP server may refuse to accept messages for relay based on
-+ authentication supplied during the TLS negotiation. An SMTP server
-+ that is not publicly referenced may refuse to accept any messages for
-+ relay or local delivery based on authentication supplied during the
-+ TLS negotiation.
-+
-+ A SMTP server that is not publicly referenced may choose to require
-+ that the client perform a TLS negotiation before accepting any
-+ commands. In this case, the server SHOULD return the reply code:
-+
-+ 530 Must issue a STARTTLS command first
-+
-+ to every command other than NOOP, EHLO, STARTTLS, or QUIT. If the
-+ client and server are using the ENHANCEDSTATUSCODES ESMTP extension
-+ [RFC2034], the status code to be returned SHOULD be 5.7.0.
-+
-+ After receiving a 220 response to a STARTTLS command, the client MUST
-+ start the TLS negotiation before giving any other SMTP commands. If,
-+ after having issued the STARTTLS command, the client finds out that
-+ some failure prevents it from actually starting a TLS handshake, then
-+ it SHOULD abort the connection.
-+
-+ If the SMTP client is using pipelining as defined in RFC 2920, the
-+ STARTTLS command must be the last command in a group.
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 3]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ 4.1 Processing After the STARTTLS Command
-+
-+ After the TLS handshake has been completed, both parties MUST
-+ immediately decide whether or not to continue based on the
-+ authentication and privacy achieved. The SMTP client and server may
-+ decide to move ahead even if the TLS negotiation ended with no
-+ authentication and/or no privacy because most SMTP services are
-+ performed with no authentication and no privacy, but some SMTP
-+ clients or servers may want to continue only if a particular level of
-+ authentication and/or privacy was achieved.
-+
-+ If the SMTP client decides that the level of authentication or
-+ privacy is not high enough for it to continue, it SHOULD issue an
-+ SMTP QUIT command immediately after the TLS negotiation is complete.
-+ If the SMTP server decides that the level of authentication or
-+ privacy is not high enough for it to continue, it SHOULD reply to
-+ every SMTP command from the client (other than a QUIT command) with
-+ the 554 reply code (with a possible text string such as "Command
-+ refused due to lack of security").
-+
-+ The decision of whether or not to believe the authenticity of the
-+ other party in a TLS negotiation is a local matter. However, some
-+ general rules for the decisions are:
-+
-+ - A SMTP client would probably only want to authenticate an SMTP
-+ server whose server certificate has a domain name that is the
-+ domain name that the client thought it was connecting to.
-+ - A publicly-referenced SMTP server would probably want to accept
-+ any verifiable certificate from an SMTP client, and would possibly
-+ want to put distinguishing information about the certificate in
-+ the Received header of messages that were relayed or submitted
-+ from the client.
-+
-+ 4.2 Result of the STARTTLS Command
-+
-+ Upon completion of the TLS handshake, the SMTP protocol is reset to
-+ the initial state (the state in SMTP after a server issues a 220
-+ service ready greeting). The server MUST discard any knowledge
-+ obtained from the client, such as the argument to the EHLO command,
-+ which was not obtained from the TLS negotiation itself. The client
-+ MUST discard any knowledge obtained from the server, such as the list
-+ of SMTP service extensions, which was not obtained from the TLS
-+ negotiation itself. The client SHOULD send an EHLO command as the
-+ first command after a successful TLS negotiation.
-+
-+ The list of SMTP service extensions returned in response to an EHLO
-+ command received after the TLS handshake MAY be different than the
-+ list returned before the TLS handshake. For example, an SMTP server
-+
-+
-+
-+ Hoffman Standards Track [Page 4]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ might not want to advertise support for a particular SASL mechanism
-+ [SASL] unless a client has sent an appropriate client certificate
-+ during a TLS handshake.
-+
-+ Both the client and the server MUST know if there is a TLS session
-+ active. A client MUST NOT attempt to start a TLS session if a TLS
-+ session is already active. A server MUST NOT return the STARTTLS
-+ extension in response to an EHLO command received after a TLS
-+ handshake has completed.
-+
-+ 4.3 STARTTLS on the Submission Port
-+
-+ STARTTLS is a valid ESMTP extension when used on the Submission port,
-+ as defined in [RFC2476]. In fact, since the submission port is by
-+ definition not a publicly referenced SMTP server, the STARTTLS
-+ extension can be particularly useful by providing security and
-+ authentication for this service.
-+
-+ 5. Usage Example
-+
-+ The following dialog illustrates how a client and server can start a
-+ TLS session:
-+
-+ S: <waits for connection on TCP port 25>
-+ C: <opens connection>
-+ S: 220 mail.imc.org SMTP service ready
-+ C: EHLO mail.example.com
-+ S: 250-mail.imc.org offers a warm hug of welcome
-+ S: 250-8BITMIME
-+ S: 250-STARTTLS
-+ S: 250 DSN
-+ C: STARTTLS
-+ S: 220 Go ahead
-+ C: <starts TLS negotiation>
-+ C & S: <negotiate a TLS session>
-+ C & S: <check result of negotiation>
-+ C: EHLO mail.example.com
-+ S: 250-mail.imc.org touches your hand gently for a moment
-+ S: 250-8BITMIME
-+ S: 250 DSN
-+
-+ 6. Security Considerations
-+
-+ It should be noted that SMTP is not an end-to-end mechanism. Thus,
-+ if an SMTP client/server pair decide to add TLS privacy, they are not
-+ securing the transport from the originating mail user agent to the
-+ recipient. Further, because delivery of a single piece of mail may
-+ go between more than two SMTP servers, adding TLS privacy to one pair
-+
-+
-+
-+ Hoffman Standards Track [Page 5]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ of servers does not mean that the entire SMTP chain has been made
-+ private. Further, just because an SMTP server can authenticate an
-+ SMTP client, it does not mean that the mail from the SMTP client was
-+ authenticated by the SMTP client when the client received it.
-+
-+ Both the SMTP client and server must check the result of the TLS
-+ negotiation to see whether an acceptable degree of authentication and
-+ privacy was achieved. Ignoring this step completely invalidates
-+ using TLS for security. The decision about whether acceptable
-+ authentication or privacy was achieved is made locally, is
-+ implementation-dependent, and is beyond the scope of this document.
-+
-+ The SMTP client and server should note carefully the result of the
-+ TLS negotiation. If the negotiation results in no privacy, or if it
-+ results in privacy using algorithms or key lengths that are deemed
-+ not strong enough, or if the authentication is not good enough for
-+ either party, the client may choose to end the SMTP session with an
-+ immediate QUIT command, or the server may choose to not accept any
-+ more SMTP commands.
-+
-+ A man-in-the-middle attack can be launched by deleting the "250
-+ STARTTLS" response from the server. This would cause the client not
-+ to try to start a TLS session. Another man-in-the-middle attack is
-+ to allow the server to announce its STARTTLS capability, but to alter
-+ the client's request to start TLS and the server's response. In
-+ order to defend against such attacks both clients and servers MUST be
-+ able to be configured to require successful TLS negotiation of an
-+ appropriate cipher suite for selected hosts before messages can be
-+ successfully transferred. The additional option of using TLS when
-+ possible SHOULD also be provided. An implementation MAY provide the
-+ ability to record that TLS was used in communicating with a given
-+ peer and generating a warning if it is not used in a later session.
-+
-+ If the TLS negotiation fails or if the client receives a 454
-+ response, the client has to decide what to do next. There are three
-+ main choices: go ahead with the rest of the SMTP session, retry TLS
-+ at a later time, or give up and return the mail to the sender. If a
-+ failure or error occurs, the client can assume that the server may be
-+ able to negotiate TLS in the future, and should try negotiate TLS in
-+ a later session, until some locally-chosen timeout occurs, at which
-+ point, the client should return the mail to the sender. However, if
-+ the client and server were only using TLS for authentication, the
-+ client may want to proceed with the SMTP session, in case some of the
-+ operations the client wanted to perform are accepted by the server
-+ even if the client is unauthenticated.
-+
-+ Before the TLS handshake has begun, any protocol interactions are
-+ performed in the clear and may be modified by an active attacker.
-+
-+
-+
-+ Hoffman Standards Track [Page 6]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ For this reason, clients and servers MUST discard any knowledge
-+ obtained prior to the start of the TLS handshake upon completion of
-+ the TLS handshake.
-+
-+ The STARTTLS extension is not suitable for authenticating the author
-+ of an email message unless every hop in the delivery chain, including
-+ the submission to the first SMTP server, is authenticated. Another
-+ proposal [SMTP-AUTH] can be used to authenticate delivery and MIME
-+ security multiparts [MIME-SEC] can be used to authenticate the author
-+ of an email message. In addition, the [SMTP-AUTH] proposal offers
-+ simpler and more flexible options to authenticate an SMTP client and
-+ the SASL EXTERNAL mechanism [SASL] MAY be used in conjunction with
-+ the STARTTLS command to provide an authorization identity.
-+
-+ 7. References
-+
-+ [RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
-+ April 2001.
-+
-+ [RFC2034] Freed, N., "SMTP Service Extension for Returning Enhanced
-+ Error Codes", RFC 2034, October 1996.
-+
-+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
-+ Requirement Levels", BCP 14, RFC 2119, March 1997.
-+
-+ [RFC2476] Gellens, R. and J. Klensin, "Message Submission", RFC
-+ 2476, December 1998.
-+
-+ [SASL] Myers, J., "Simple Authentication and Security Layer
-+ (SASL)", RFC 2222, October 1997.
-+
-+ [SMTP-AUTH] Myers, J., "SMTP Service Extension for Authentication",
-+ RFC 2554, March 1999.
-+
-+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
-+ RFC 2246, January 1999.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 7]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ Appendix
-+
-+ This document is a revision of RFC 2487, which is a Proposed
-+ Standard. The changes from that document are:
-+
-+ - Section 5 and 7: More discussion of the man-in-the-middle attacks
-+ - Section 5: Additional discussion of when a server should and
-+ should not advertise the STARTTLS extension
-+ - Section 5: Changed the requirements on SMTP clients after
-+ receiving a 220 response.
-+ - Section 5.1: Clarified description of verifying certificates.
-+ - Section 5.3: Added the section on "STARTTLS on the Submission
-+ Port"
-+ - Section 6: Bug fix in the example to indicate that the client
-+ needs to issue a new EHLO command, as already is described in
-+ section 5.2.
-+ - Section 7: Clarification of the paragraph on acceptable degree of
-+ privacy. Significant change to the discussion of how to avoid a
-+ man-in-the-middle attack.
-+ - Section A: Update reference from RFC 821 to RFC 2821.
-+
-+ Author's Address
-+
-+ Paul Hoffman
-+ Internet Mail Consortium
-+ 127 Segre Place
-+ Santa Cruz, CA 95060
-+
-+ Phone: (831) 426-9827
-+ EMail: phoffman@imc.org
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 8]
-+ \f
-+ RFC 3207 SMTP Service Extension - Secure SMTP over TLS February 2002
-+
-+
-+ Full Copyright Statement
-+
-+ Copyright (C) The Internet Society (2002). All Rights Reserved.
-+
-+ This document and translations of it may be copied and furnished to
-+ others, and derivative works that comment on or otherwise explain it
-+ or assist in its implementation may be prepared, copied, published
-+ and distributed, in whole or in part, without restriction of any
-+ kind, provided that the above copyright notice and this paragraph are
-+ included on all such copies and derivative works. However, this
-+ document itself may not be modified in any way, such as by removing
-+ the copyright notice or references to the Internet Society or other
-+ Internet organizations, except as needed for the purpose of
-+ developing Internet standards in which case the procedures for
-+ copyrights defined in the Internet Standards process must be
-+ followed, or as required to translate it into languages other than
-+ English.
-+
-+ The limited permissions granted above are perpetual and will not be
-+ revoked by the Internet Society or its successors or assigns.
-+
-+ This document and the information contained herein is provided on an
-+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
-+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-+
-+ Acknowledgement
-+
-+ Funding for the RFC Editor function is currently provided by the
-+ Internet Society.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Hoffman Standards Track [Page 9]
-+ \f
-diff -Pcr postfix-2.0.16/pfixtls/doc/security.html postfix-2.0.16-ti1.20/pfixtls/doc/security.html
-*** postfix-2.0.16/pfixtls/doc/security.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/security.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,78 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Security Considerations</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Security Considerations</h1>
-+
-+ The following sections cover some (possible) security issues with
-+ regard to Postfix/TLS.
-+
-+ <h2>Server/Client private key file</h2>
-+
-+ Postfix/TLS uses authentication for the server side (mandatory) and
-+ the client side (optional). In order to authenticate itself, the
-+ according process (smptd/smtp) must be able to access the private
-+ key, which must however be kept secret. As these processes are
-+ started from 'master' without the possibility of user interaction, it is not
-+ possible to supply a password, so that the private key can not be
-+ encrypted.
-+
-+ <p>The only protection can therefore come from filesystem access
-+ rights, which should be set to 'owner root' and 'readable for owner
-+ only':</p>
-+
-+ <pre>
-+ -rw------- 1 root sys 887 Apr 29 1999 /etc/postfix/key.pem
-+ </pre>
-+
-+ <p>This protection is only as good as your host is protected
-+ against root exploits.</p>
-+
-+ <p>You also should be aware, that people having physical access to
-+ your system might be able to 'steal' the private key if they can
-+ boot into single user mode without password protection or can move
-+ the disk to another computer, on which they have root rights. (Yes,
-+ I know there are such things as encrypted filesystems, but they are
-+ not in wide spread use today.)</p>
-+
-+ <h2>Disk based session cache</h2>
-+
-+ If you run disk based session caching (the default) people being
-+ able to get hold of the files might be able to figure out security
-+ relevant communication parameters. The security situation is
-+ however not more dramatic than the private key issue explained
-+ above, so I don't consider any additional danger coming from saving
-+ session information to stable storage.
-+
-+ <p>As breaking the code with public key cryptography is just a
-+ matter of time (even though it might be a very long time), sessions
-+ should not be used for an infinite duration. The default value for
-+ Postfix/TLS is 1h; RFC2246 (TLSv1) recommends to not use sessions
-+ for more than 24h.</p>
-+
-+ <h2>DNS issues</h2>
-+
-+ One weak point in authentication is the use of the DNS to find out
-+ the MX information. Since we do (E)SMTP, we must use the MX
-+ information!
-+
-+ <p>As we have to authenticate the server retrieved via MX, somebody
-+ able to spoof a wrong MX entry might be able to receive the email,
-+ if his host can present a certificate issued by an acceptable CA.
-+ The last part is not too difficult if 'standard' CAs like Verisign,
-+ Thawte,... are included.</p>
-+
-+ <p>The only way to protect against this problem is that for those
-+ recipients, for which we want to <strong>enforce</strong>
-+ encryption and authentication, the MX lookup must be overridden
-+ with an appropriate entry in the /etc/postfix/transport table:</p>
-+
-+ <pre>
-+ important.dom.ain smtp:[mailserver.important.dom.ain]
-+ </pre>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/setup.html postfix-2.0.16-ti1.20/pfixtls/doc/setup.html
-*** postfix-2.0.16/pfixtls/doc/setup.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/setup.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,220 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Setting up the certificates</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Setting up the certificates</h1>
-+
-+ This section explains what kind of certificates are needed to run
-+ postfix with TLS. The certificates (and maybe keys) can be obtained
-+ from a third party, that might be a commercial certification
-+ authority or your internet service provider. On the long run you do
-+ need certificates that are accepted by other Internet parties, so
-+ you have to agree with them on certification authorities, of which
-+ type they might be.
-+
-+ <h2>Server certificate</h2>
-+
-+ To run SMTP with TLS in server mode, your server <strong>
-+ must</strong> have a pair of <em>private key</em> and <em>public
-+ key</em>.
-+
-+ <p>As the public key must be distributed to the client somehow, it
-+ is sent from the server to the client during the startup
-+ negotiation. The client however cannot know from just the
-+ negotiation, that the public key really belongs to the server and
-+ is not faked. Therefore a third component is necessary, a <em>
-+ certificate</em> from a certificate authority (CA), that is sent
-+ combined with the public key. This <em>server certificate</em>
-+ contains the <code>name.of.your.host</code>. The client will then
-+ check the <em>signature</em> of the CA on the public key to decide,
-+ whether the certificate (and public key) are authentic.</p>
-+
-+ <p>So for the server we do need:</p>
-+
-+ <ul>
-+ <li>1 <em>server private key</em></li>
-+
-+ <li>1 server public key signed by a CA, a <em>server
-+ certificate</em>, certifying that the public key belongs to <code>
-+ name.of.your.host</code>.</li>
-+
-+ <li>1 <em>CA certificate</em> with the public key of the CA</li>
-+ </ul>
-+
-+ For this list I definitely want point out the number of components
-+ used to be <strong>1</strong>, because you must have <strong>
-+ 1</strong>, you cannot have less, you cannot have more!
-+
-+ <h3>Server certificate policy</h3>
-+
-+ At this point you have to decide about policy. The client which is
-+ going to connect to your host will check the names in the <em>server
-+ certificate</em>, the dNSName entries in the SubjectAlternativeName
-+ or the CN (Common Name) if no dNSName is found, against the FQDN (Fully
-+ Qualified Domain Name) of your server. If both agree, your server's
-+ identity is proved.
-+
-+ <p>To see, whether the certificate itself is authentic, the client
-+ itself <em>must have</em> the <em>CA certificate</em>. So, if you
-+ want to make it easily accessible to other, unknown parties, you
-+ should have your server certificate issued by a well known and well
-+ trusted CA. Remember, that your server can only have one server
-+ certificate at a time.</p>
-+
-+ <p>There are commercial providers (Thawte, Verisign, just to name
-+ some), the CA certificats of which are well distributed. Not
-+ knowing of other countries, at least in Germany the
-+ Research Network (DFN) has started a program for universities [<a
-+ href="references.html#dfnpca">DFNPCA</a>].</p>
-+
-+ <p>If you do not care about that for know (you can change that
-+ later), you can just become your own CA and distribute your CA cert
-+ to those parties who should know it, and you are set. It is not
-+ difficult to do.<br>
-+ <a href="myownca.html">Lutz's very short course on being your own
-+ CA</a>.</p>
-+
-+ <h3>Using the certificates with Postfix/TLS</h3>
-+
-+ To make the key and certificates available to Postfix/TLS, they
-+ must be in "PEM" format. Then you have to tell postfix in main.cf
-+ where to find them:
-+
-+ <ul>
-+ <li>The private key:
-+
-+ <pre>
-+ smtpd_tls_key_file = /etc/postfix/key.pem
-+ </pre>
-+
-+ As the public key is public including the certificate (everybody
-+ can get a copy), everybody who has a copy of the private key can
-+ fake your identity. It is not too easy, as he must be able to
-+ redirect or intercept the IP packages sent to your server, but I
-+ have seen a lot of things happening. So protect this key with:
-+
-+ <pre>
-+ chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem
-+ </pre>
-+
-+ One more possibility for protection is a passphrase. This is
-+ however a problem, as you have to enter it everytime the server has
-+ to be started. This has to drawbacks: firstly you would have to
-+ enter it to postfix everytime you restart it, which I find quite
-+ impractical for an unattended server which might restart
-+ automatically after a power outage. Secondly the smtpd processes
-+ are independently started from master, so that master would have to
-+ pass the passphrase to the clients somehow. Alltogether I think
-+ this is impractical and so I don't support by software.</li>
-+
-+ <li>The server certificate: This certificate is not secret, as it
-+ will be presented to every client anyhow, so you just name it to
-+ postfix:
-+
-+ <pre>
-+ smtpd_tls_cert_file = /etc/postfix/cert.pem
-+ </pre>
-+
-+ If you like, you can put private key and cert into one file.</li>
-+
-+ <li>The CA certificate: To also have the CA certificate available,
-+ you put it into a file and name it to Postfix/TLS. We will come
-+ back to this file later.
-+
-+ <pre>
-+ smtpd_tls_CAfile = /etc/postfix/CAcert.pem
-+ </pre>
-+ </li>
-+ </ul>
-+
-+ With these certificates you should already have enough to get
-+ Postfix/TLS running.
-+
-+ <h3>Postfix/TLS client mode</h3>
-+
-+ When connecting to a server offering TLS, postfix can present a
-+ client certificate of its own. As realized by now, only one
-+ certificate can be managed, so it should be issued on your own
-+ hostname. No default is supplied (no certificate is presented),
-+ unless you explicitly set the certificate in the configuration. You
-+ can use the same certificate as for the server side:
-+
-+ <pre>
-+ smtp_tls_key_file = /etc/postfix/key.pem
-+ chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem
-+ </pre>
-+
-+ <pre>
-+ smtp_tls_cert_file = /etc/postfix/cert.pem
-+ </pre>
-+
-+ <pre>
-+ smtp_tls_CAfile = /etc/postfix/CAcert.pem
-+ </pre>
-+
-+ <h2>Client certificates</h2>
-+
-+ One reason to do all of this work is that I want to do relaying
-+ based on client certificates. The clients present a certificate
-+ from a CA, that is unique and cannot be faked.
-+
-+ <p>Some clients can have several certificates issued by different
-+ CAs. Upon connection the server will pass the client the list of
-+ CAs he knows (has the CA certificates) and the client can then pass
-+ back a certificate of choice. With Netscape this means, a window is
-+ opened and only those client certificates compatible with the
-+ server are listed for selection.</p>
-+
-+ <p>So if your clients already have certificates from trustable
-+ sources, it is not necessary to create a lot of problems. You just
-+ have to collect the CA certificates and make them available to
-+ Postfix/TLS. If that is not enough, you can still become your own
-+ CA to easily create client certificates for your users (which are
-+ of course of no use outside your scope).</p>
-+
-+ <h3>Listing CA certificates</h3>
-+
-+ <p>You have two possibilities to perform this task.</p>
-+
-+ <ol>
-+ <li>You just add the CA certificates to the <code>
-+ smtp[d]_tls_CAfile</code> you already have created, one after the
-+ other. This file is probably not very readable, but it has the
-+ advantage that it is read at smtpd before switching to chroot jail
-+ and hence works in chroot mode.</li>
-+
-+ <li>You can add the CA certificates in single files with adequate
-+ names to a certificate directory specified in:
-+
-+ <pre>
-+ smtpd_tls_CApath = /etc/postfix/certs
-+ </pre>
-+
-+ Please don't forget to issue a <code>$OPENSSL_HOME/bin/c_rehash
-+ /etc/postfix/certs</code> after you have made changes, as the
-+ hashes are use to find the right CA certificate. This method should
-+ not work in chroot mode.</li>
-+ </ol>
-+
-+ <h3>Adding client certificates</h3>
-+
-+ The client certificates are issued for a DN (Distinguished Name)
-+ made up of company, department, name, email... As they may contain
-+ blanks, @ signs and colons, it is quite difficult to handle them
-+ with standard postfix tools.
-+
-+ <p>A quite practical thing is that every client certificate has a
-+ "fingerprint" that is extremely difficult to fake (read this: from
-+ my knowledge, it might take years even on fast computers). I have
-+ to do some more research about the security of the fingerprint, but
-+ at least for relaying it should be secure enough. I will much
-+ easier find a host with worse security to send out my SPAM than to
-+ fake a client certificate with a matching fingerprint (which I also
-+ don't know to from the outside, even from the inside you might
-+ protect the fingerprint data with a <code>chmod 400</code>).</p>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc/test.html postfix-2.0.16-ti1.20/pfixtls/doc/test.html
-*** postfix-2.0.16/pfixtls/doc/test.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc/test.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,167 ----
-+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-+ <html>
-+ <head>
-+ <meta name="generator" content="HTML Tidy, see www.w3.org">
-+ <title>Postfix/TLS - Testing</title>
-+ </head>
-+ <body>
-+ <h1>Postfix/TLS - Testing</h1>
-+
-+ Testing the package is a little bit difficult, as the communication
-+ is encrypted, so that you cannot "imitate" the conversation just by
-+ telnetting to the SMTP port. You also cannot capture the packets
-+ (well, you can, but if everything is working as advertised, it
-+ won't help you :-).
-+
-+ <h2>Included debugging aids</h2>
-+
-+ As all of the messages generated by Postfix are sent to the syslog
-+ facility, debugging must be done using your normal system logfiles.
-+ Postfix/TLS supports the logging levels 0 (very quiet) up to 4 (a
-+ dump of the complete conversation, not recommended).
-+
-+ <p>As a first step set <code>smpt[d]_tls_loglevel=2</code> and
-+ watch the logfile. Typically you will have problems with the access
-+ to the keys or certificates, so you will find error messages
-+ here.</p>
-+
-+ <p>You can always try to send an email to <tt>
-+ postfix_tls-bounce@serv01.aet.tu-cottbus.de</tt> with TLS enabled
-+ at your side and watch, what is going to happen :-)</p>
-+
-+ <p>While testing the interoperability with ZMailer we learned, that
-+ an incorrect certificate type (must be server for the server :-)
-+ can lead to connection failures without clear symptoms. It helps to
-+ use Netscape 4.5x as a client and carefully study the message boxes
-+ and certificate information. I have yet to find out how to identify
-+ this problem from postfix to print a suitable warning to the
-+ logfile. Hopefully it will be possible without changes in the
-+ OpenSSL library.</p>
-+
-+ <h2>Platforms</h2>
-+
-+ <ul>
-+ <li>Development Platform:
-+
-+ <ul>
-+ <li>OS: HP-UX 10.20</li>
-+
-+ <li>OS: Linux 2.x (SuSE Linux)</li>
-+ </ul>
-+ </li>
-+
-+ <li>Test Client:
-+
-+ <ul>
-+ <li>Software: Netscape 4.5x, Netscape 4.6x, Netscape 4.7x</li>
-+
-+ <li>OS: HP-UX 10.20, Linux 2.x, Win95</li>
-+ </ul>
-+ </li>
-+ </ul>
-+
-+ Please don't comment on the stability of Netscape, especially not
-+ on HP-UX...
-+
-+ <h2>Interoperability</h2>
-+
-+ Besides support by generic wrapper solutions, there exist specially
-+ crafted extensions for other MTAs:
-+
-+ <ul>
-+ <li><strong>Qmail</strong> There is an OpenSource patch available,
-+ extending the Qmail [<a href="references.html#qmail">QMAIL</a>] MTA
-+ to support RFC2487, written by Frederik Vermeulen [<a href=
-+ "references.html#qmailtls">QMAILTLS</a>]. Sending and receiving is
-+ working from both sides.
-+
-+ <p>Testing: send mail to <tt>ping@linux.student.kuleuven.ac.be</tt>
-+ (will send back complete email including headers).</p>
-+ </li>
-+
-+ <li><strong>Zmailer</strong> The author/maintainer of ZMailer,
-+ Matti Aarnio, has incorporated both server and client side TLS
-+ support [<a href="references.html#zmailer">ZMAILER</a>].
-+
-+ <p>Zmailer -> Postfix works fine,<br>
-+ Postfix -> Zmailer does not work, since ESMTP is not recognized
-+ (problem reported).</p>
-+
-+ <p>Testing: send mail to <tt>autoanswer@mea.tmt.tele.fi</tt> (will
-+ send back headers).</p>
-+ </li>
-+
-+ <li><strong>Sendmail</strong> The commercial verson of sendmail
-+ supports client and server TLS, both sides interoperating with
-+ Postfix/TLS. As of sendmail-8.11, TLS is also included with the
-+ opensource version [<a href=
-+ "references.html#sendmail">SENDMAIL</a>].
-+
-+ <p>Testing: send mail to <tt>bounce@esmtp.org</tt> (will bounce
-+ error message including old headers).</p>
-+ </li>
-+
-+ <li><strong>Postfix</strong> Can send emails to itself :-).
-+
-+ <p>Testing: send mail to <tt>
-+ postfix_tls-bounce@serv01.aet.tu-cottbus.de</tt> (will bounce back,
-+ includes old headers).</p>
-+ </li>
-+ </ul>
-+
-+ Other reports are welcome.
-+
-+ <h2>Known interoperability problems</h2>
-+
-+ <ul>
-+ <li>Postfix/TLS server: Under Win95/NT I have some problems with the
-+ client certificates. When opening the first connection (and
-+ Netscape asks for the password to access the certificate database),
-+ the connection hangs. This seems to be caused by Netscape: a dump
-+ of the communication shows, that Netscape just does not resume the
-+ TLS handshake.<br>
-+ <strong>Remark:</strong>I could not reproduce this bug recently
-+ after upgrading OpenSSL 0.9.4. I hope it has vanished, but maybe it
-+ is just a consequence of playing around with Netscape's security
-+ options. More testing required...<br>
-+ Workarounds: kill this connection, the next one will work
-+ immediately <strong>or</strong> use SSLv2 only (second workaround
-+ not recommended).
-+
-+ <p><strong>Should finally be fixed with OpenSSL 0.9.5.</strong></p>
-+ </li>
-+
-+ <li>Postfix/TLS server: Outlook Express as of Internet Explorer 5 will
-+ work with Postfix/TLS, but it will not present any client
-+ certificate. So you can encrypt your email transfer but you cannot
-+ authenticate (and relay) with client certificates. It only works on
-+ port 25 (smtp); on other ports you must use smtpd_tls_wrappermode
-+ instead. [<a href="references.html#oe_ssl">Microsoft
-+ Knowledgebase</a>]</li>
-+
-+ <li>Postfix/TLS server: Outlook Express as of Internet Explorer 4 does not
-+ support RFC2487. Use smtpd_tls_wrappermode=yes on a different
-+ port(!) (465=smpts?) instead.</li>
-+
-+ <li>Postfix/TLS server: Outlook Express (Mac) seems not to support
-+ RFC2487, you must use smtpd_tls_wrappermode on a different port(!)
-+ (465=smtps?) instead.</li>
-+
-+ <li>Postfix/TLS client: MS Exchange also in recent versions (5.5) offers
-+ STARTTLS even if not configured (from the mailing list [<a href=
-+ "references.html#imcorgappstls">IETF-APPS-TLS</a>]). I could not
-+ test this without access to such server, so I cannot predict what
-+ is going to happen.</li>
-+
-+ <li>Postfix/TLS client: TLS connections to a CommunigatePro server fail
-+ with a handshake error with older versions of CommunigatePro.
-+ Reason is a protocol violation of the CommunigatePro server with
-+ respect to SSL-protocol version numbering. The respective part of
-+ the protocol is the specification of the client_version in section
-+ 7.4.7.1. of RFC2246.<br>
-+ This problem has been fixed in CommunigatePro 3.3b?? (don't know
-+ the exact numbering) around June 09, 2000.</li>
-+ </ul>
-+ </body>
-+ </html>
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/conf.html postfix-2.0.16-ti1.20/pfixtls/doc_french/conf.html
-*** postfix-2.0.16/pfixtls/doc_french/conf.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/conf.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,600 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>Postfix/TLS - Configurer main.cf et master.cf </p>
-+ <p>Afin d'utiliser les extensions TLS vous devez renseigner quelques informations
-+ a Postfix. Regardez également le fichier conf/sample-tls.cf</p>
-+ <p>main.cf: smtpd (serveur) variables spécifiques<br>
-+ # pour utiliser TLS nous avons besoin d'un certificat et d'une clef privée. Tous
-+ les deux doivent être <br>
-+ # au format "PEM ",la clé privée ne doit pas être chiffrée, ce qui signifie:
-+ <br>
-+ # elle doit être accessible sans mot de passe. Les deux pièces (certificat et<br>
-+ # clé privée) peuvent être dans le même fichier <br>
-+ # <br>
-+ # RSA et DSA sont des formats de certificats supportées <br>
-+ # Typiquement vous pouvez seulement vous faire délivrer des certificats de RSA
-+ par un CA commercial<br>
-+ # Les outils OpenSSL vont, par defaut, générer des certificats
-+ RSA<br>
-+ # Vous pouvez avoir les deux en même temps, dans ce cas-ci le chiffrage du client
-+ utilisé décide<br>
-+ # Pour les clients Netscape et OpenSSL le certificat
-+ de RSA est préféré.<br>
-+ #<br>
-+ # Afin de contrôler les certificats, le certificat CA (dans le cas d'une chaine
-+ de certificats, tous les certificats CA) doit être disponible<br>
-+ # Vous devez ajouter ces certificats aux certificat du serveur, ce dernier en
-+ premier puis ceux émis par par le(s) CA(s)<br>
-+ #<br>
-+ # exemple: le certificat pour "serveur.chez.moi" a été
-+ émis par "Intermediate CA"<br>
-+ # qui lui même a un certificat de "root CA". Creez le fichier
-+ server.pem en faisant 'cat server_cert.pem intermediate.pem > server.pem'<br>
-+ #<br>
-+ # Si vous voulez accepter des certificats délivrés par ces derniers en tant
-+ que vous-même, vous pouvez aussi ajouter les certificats CA <br>
-+ # au fichier smtpd_tls_CAfile, dans ce cas ce n'et pas nécessaire de les
-+ avoir dans le fichier smtpd_tls_[d]cert_file<br>
-+ #<br>
-+ # Un certificat fourni ici doit être utilisable comme SSL certificat serveur
-+ et par conséquent passer le test<br>
-+ # "openssl verify -purpose sslserver ..." <br>
-+ #<br>
-+ smtpd_tls_cert_file = /etc/postfix/server.pem <br>
-+ smtpd_tls_key_file = $smtpd_tls_cert_file <br>
-+ # <br>
-+ # Les équivalents DSA<br>
-+ smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem <br>
-+ smtpd_tls_dkey_file = $smtpd_tls_dcert_file <br>
-+ #<br>
-+ # le certificat a été délivré par une autorité de certification (CA) le certificat
-+ CA de celui-ci doit être disponible<br>
-+ # si il n'est pas dans le fichier de certificats.<br>
-+ # Ce fichier peut également contenir les les certificats de CA d'autres CA de
-+ confiance.<br>
-+ # Vous devez utiliser ce fichier pour la liste de CA de confiance si vous voulez
-+ utiliser le mode chroot.<br>
-+ # Il n'y a pas de valeurs par defaut<br>
-+ #<br>
-+ # smtpd_tls_CAfile = /etc/postfix/CAcert.pem <br>
-+ <br>
-+ # pour vérifier le certificat de pair, nous devons connaître les certificats des
-+ autorités de certification. Ces certificats sont au format PEM<br>
-+ # et sont rassemblés dans un répertoire. Les mêmes CA sont offerts aux
-+ clients pour la vérification. N'oubliez pas de créer<br>
-+ # les tables de hachages nécessaires avec $OPENSSL_HOME/bin/c_rehash
-+ /etc/postfix/certs. Une place classique<br>
-+ # pour les certificats CA peut être aussi $OPENSSL_HOME/certs, il n'y
-+ a donc aucune valeur par défaut et vous avez à<br>
-+ # le spécifier ici<br>
-+ #<br>
-+ # Pour utiliser cette option en mode chrooté, ce répertoire ou
-+ une copie de celui-ci doit être dans la 'cage'. Veuillez noter également<br>
-+ # que les CA listés dans ce répertoire ne sont pas listés
-+ aux clients, Netscape ne peut donc pas offrir de certificats émis par
-+ ceux ci.<br>
-+ #<br>
-+ # Je n'encourage pas à l'utilisation de cette option<br>
-+ <br>
-+ smtpd_tls_CApath = /etc/postfix/certs <br>
-+ <br>
-+ # Pour obtenir des informations supplémentaires pendant la mise en place
-+ et les négociations TLS<br>
-+ # vous pouvez augmenter le niveau de journalisation de 0 à 4:<br>
-+ # 0 : rien a propos du TLS<br>
-+ # 1 : Notification de mise en route et information de certificat <br>
-+ # 2 : 1 + impression des niveaux pendant la négociation <br>
-+ # 3 : 2 + hexa et vidage mémoire Ascii du processus de négociation <br>
-+ # 4 : 4: 3 + hexa et vidage mémoire Ascii de transmission complète après STARTTLS
-+ <br>
-+ # utilisez le niveau 3 uniquement en cas de problémes. L'utilisation
-+ du niveau 4 est fortement déconseillée.<br>
-+ #<br>
-+ # smtpd_tls_loglevel = 0 <br>
-+ # Afin d'inclure des informations sur le protocole et le cryptage utilisé
-+ aussi bien que le client et l'émetteur <br>
-+ # dans l'entête "Received:", positionnez la variable smtpd_tls_received_header
-+ à true. Par défaut elle est a no, <br>
-+ # du fait que cette information n'est pas forcément authentique. Seulement
-+ la destination finale est fiable, <br>
-+ # puisque les en-têtes pourraient avoir été modifiées entre temps.<br>
-+ #<br>
-+ # smtpd_tls_received_header = yes<br>
-+ <br>
-+ # Vous pouvez IMPOSER l'utilisation de TLS, de sorte qu'on ne permette aucune
-+ commande (excepté QUIT naturellement) <br>
-+ # sans TLS. Selon la RFC2487 ceci NE DOIT PAS être appliquée dans le cas d'un
-+ serveur SMTP public. Cette option est <br>
-+ # donc inactive par defaut et ne doit être utilisée que rarement.
-+ Cette fonction implique<br>
-+ # smtpd_use_tls = yes <br>
-+ #<br>
-+ #smtpd_enforce_tls = no <br>
-+ # <br>
-+ # Sans compter que quelques clients, comme outlook express prefère utiliser
-+ un mode d'emballage non-standard et non les<br>
-+ # améliorations STARTTLS de SMTP.<br>
-+ # Ceci est vrai pour outlook express ( Win32 < 5.0 et Win 32 >= 5.0 quand
-+ on l'utilise sur un port differents de 25<br>
-+ # et sur 5.01 pour Mac sur tous les ports<br>
-+ # Il est strictement découragé d'utiliser utiliser ce mode depuis main.cf. Si
-+ vous voulez <br>
-+ # supporter ce service, rajoutez un port spécial dans master.cf. Le port 465
-+ (smtps) a été choisi pour ce dispositif. <br>
-+ # smtpd_tls_wrappermode = no<br>
-+ <br>
-+ # Pour recevoir un certificat de client, le serveur doit explicitement en demander
-+ un. Par conséquent Netscape se plaindra <br>
-+ # si aucun certificat n'est disponible (pour la liste des CA dans /etc/postfix/certs)
-+ ou vous offrira des certificats clients<br>
-+ # pour choisir. Ceci peut être ennuyeux, ainsi cette option est "Off" par défaut
-+ . <br>
-+ # Vous aurez peut être besoin du certificat si vous voulez faire du relayage
-+ à partir des certificats<br>
-+ #<br>
-+ # smtpd_tls_ask_ccert = no <br>
-+ <br>
-+ # Vous pouvez également décider D'EXIGER d'un certificat de client afin de permettre
-+ des connexions de TLS. <br>
-+ # Je ne pense pas que ce sera nécessaire souvent, il est cependant inclus ici.
-+ Cette option smtpd_tls_ask_ccert = yes<br>
-+ # <br>
-+ # Notez bien que ceci empêchera des connexions TLS sans un certificat approprié,
-+ et n'a de sens que dans le cas<br>
-+ # de soumission normal desactivée (smtpd_enforce_tls). Autrement les
-+ clients peuvent éviter ceci en n'utilisant pas du tout <br>
-+ # STARTTLS. Quand TLS n'est pas imposé, la connexion ne sera traitée comme
-+ si smtpd_tls_ask_ccert = yes <br>
-+ # était activé et une information est journalisée.<br>
-+ <br>
-+ # smtpd_tls_req_ccert = no<br>
-+ <br>
-+ # la profondeur de vérification pour des certificats de client. Une profondeur
-+ de 1 est suffisante si le certificat<br>
-+ # est émis directement par un CA listé dans la liste des CA.<br>
-+ # La valeur par defaut (5) suffit également pour de plus longues chaînes (le
-+ root CA émet le CA spécial <br>
-+ # qui délivre alors le certificat réel...)<br>
-+ <br>
-+ # smtpd_tls_ccert_verifydepth = 5 <br>
-+ <br>
-+ # le serveur et le client négocient une session, qui prend un certain temps
-+ machine et une largeur de bande passante.<br>
-+ # La session est cachée seulement dans le processus de smtpd réellement en utilisant
-+ cette session et est détruite <br>
-+ # quand le processus meurt pour partager l'information de session entre les
-+ processus de smtpd, <br>
-+ # antémémoire de session peut être utilisée avec des bases de données
-+ SDBM (sous-programmes inclus dans Postfix/TLS)<br>
-+ # Puisque l'écriture concourante doit être supportée seulement SDBM peut être
-+ utilisé. <br>
-+ <br>
-+ smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache <br>
-+ <br>
-+ # les sessions cachées ont un delais d'attente. Je n'utilise pas le défaut d'OpenSSL
-+ de 300sec, mais un plus long temps <br>
-+ # de 3600sec (= 1 heure). RFC2246 recommande un maximum de 24 heures <br>
-+ <br>
-+ # smtpd_tls_session_cache_timeout = 3600s <br>
-+ <br>
-+ # deux options supplémentaires a été ajoutées pour la commande de relais aux
-+ règles d'UCE<br>
-+ # permit_tls_clientcerts (a) <br>
-+ # et <br>
-+ # permit_tls_all_clientcerts. (b) <br>
-+ # <br>
-+ # Si une de ces options est ajoutée <br>
-+ # smtpd_recipient_restrictions<br>
-+ # postfix va relayer si<br>
-+ # (a) Un client valide (vérification faite) est présenté
-+ et que son empreinte est inscrite dans la liste des certificats clients<br>
-+ # (relay_clientcerts), <br>
-+ # (b) n'importe quel client valide (vérification faite) est présenté.<br>
-+ #<br>
-+ # L'option (b) doit seulement être utilisée, si un CA spécial délivre les certificats
-+ et seulement ce CA <br>
-+ # est énuméré en tant que CA de confiance. Si on fait confiance à d'autres
-+ CA tout propriétaire d'un certificat client valide <br>
-+ # peut être relayé. L'option (b) peut être pratique pour un relais
-+ spécialement créé. Il est recommande cependant de rester
-+ <br>
-+ # avec l'option (a) et d'énumérer tous les certificats, car (b) ne permet aucun
-+ contrôle quand un certificat ne doit<br>
-+ # plus être utilisé (par exemple un employé partant). <br>
-+ <br>
-+ # smtpd_recipient_restrictions = ... permit_tls_clientcerts ...<br>
-+ <br>
-+ # La liste de certificats de client pour lesquels le relais sera permis.<br>
-+ # Malheureusement les sous-programmes pour des listes utilise des espaces comme
-+ séparateurs <br>
-+ # et s'emmèle sur les caractères spéciaux<br>
-+ # Ainsi l'utilisation du certificat # du X509ONELINES est tout à fait impraticable.
-+ Nous utiliserons donc <br>
-+ # les empreintes digitales à ce point, car il est difficile de les truquer mais
-+ facile à utiliser pour la consultation <br>
-+ # pendant que le postmap (en utilisant par exemple le DB) exige d'avoir une
-+ paire de clé et de valeur, <br>
-+ # mais nous avons besoin seulement de la clef, la valeur pouvant être choisie
-+ librement, par exemple le nom <br>
-+ # de l'utilisateur ou de l'hôte: <br>
-+ # D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home<br>
-+ <br>
-+ # relay_clientcerts = hash:/etc/postfix/relay_clientcerts <br>
-+ <br>
-+ # Pour influencer la sélection du cryptage, vous pouvez donner une liste
-+ de cryptage.<br>
-+ # Une description complète irait troin loin ici, allez voir la documentation
-+ sur le site d'OpenSSL<br>
-+ # Si vous ne savez pas quoi faire avec, n'y touchez pas et laissez celui d'openssl
-+ par defaut <br>
-+ # N'UTILISEZ PAS " pour entourer la chaîne de caractères, juste la chaîne de
-+ caractères!!! <br>
-+ #<br>
-+ # smtpd_tls_cipherlist = default<br>
-+ <br>
-+ # Si vous voulez tirer profit du chiffrage avec EDH, les paramètres de DH sont
-+ nécessaires.<br>
-+ # Ils sont construits dans les paramètres DH pour à la fois le
-+ 1025éme et le 512éme bit disponible<br>
-+ # Il vaut mieux cependant avoir ses "propres" paramètres, puisqu'autrement
-+ ce serait "payant" pour un<br>
-+ # 'pirates' d'attaquer en brute force ces paramètres qui sont utilisés
-+ communément.<br>
-+ # Pour cette raison, les paramètres choisis sont déjà différents de ceux distribués
-+ avec le package TLS<br>
-+ <br>
-+ # Pour produire de votre propre ensemble de paramètres, faites :<br>
-+ # openssl gendh -out /etc/postfix/dh_1024.pem -2 -rand /var/run/egd-pool 1024
-+ <br>
-+ # openssl gendh -out /etc/postfix/dh_512.pem -2 -rand /var/run/egd-pool 512
-+ <br>
-+ # Votre source pour la génération aléatoire peut varier;
-+ sur des ystèmes linux c'est /dev/random<br>
-+ # Pour d'autres systèmes vous pouvez consulter "Entropy Gathering Daemon
-+ EGD", <br>
-+ # disponible sur http://www.lothar.com/tech/crypto/. <br>
-+ <br>
-+ smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem <br>
-+ smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem <br>
-+ <br>
-+ # le smtpd_starttls_timeout paramètre la limite de temps en secondes pour
-+ lire et écrire<br>
-+ # les opérations pendant les procédures de 'serrages de mains'
-+ (SSL handshake) <br>
-+ # <br>
-+ # smtpd_starttls_timeout = 300s <br>
-+ <br>
-+ # Main.cf smtp (client) variables spécifiques<br>
-+ # Pendant la négociation de démarrage nous pourrions présenter un certificat
-+ au serveur. Netscape <br>
-+ # est plutôt intelligent ici et laisse l'utilisateur choisi entre seulement
-+ ceux qui corresipondront à ceux reçus du serveur<br>
-+ # Comme j'utilise simplement la commande "SSL_connect()" du package OpenSSL,
-+ ceci n'est pas encore possible<br>
-+ # et nous ne devons choisir qu'un certificat.<br>
-+ # Le paramètre par defaut est de n'utiliser aucun certificat/clef a moins
-+ de de le définir ici.<br>
-+ # Si un certificat est présent il doit être au format PEM, la clef
-+ privée ne doit pas être encryptée : concrétement<br>
-+ # cela veut dire qu'elle doit être accessible sans mot de passe. LA clef
-+ et le certificats peuvent être dans le même fichier.<br>
-+ <br>
-+ # Afin de contrôler les certificats, le certificat CA doit être
-+ disponible (dans le cas d'une chaine de certificats, tous les <br>
-+ # certificats CA).<br>
-+ # Exemple: le certificat pour "moi.chez.moi.fr" a été
-+ émis par "intermedaire CA" qui lui-même<br>
-+ # a un certificat de "racine CA". Créez le client.pem par :
-+ <br>
-+ # 'cat client_cert.pem intermediaire_CA.pem racine_CA.pem > client.pem'<br>
-+ # <br>
-+ # Si vous voulez accepter vous mêmes les certificats émis par ces
-+ CA, vous pouvez également ajouter<br>
-+ # les certificats CA au fichier smtp_tls_CAfile, dans ce cas il n'est pas nécessaire
-+ de les avoir <br>
-+ # dans le fichier smtp_tls_[d]cert_file<br>
-+ <br>
-+ # Un certificat fourni ici doit être utilisable en tant que certificat de client
-+ de SSL et passer le test<br>
-+ # "openssl verify -purpose sslclient ..." <br>
-+ <br>
-+ smtp_tls_cert_file = /etc/postfix/client.pem <br>
-+ smtp_tls_key_file = $smtp_tls_cert_file <br>
-+ <br>
-+ # Le certificat a été délivré par une autorité de certification (CA), son certificat
-+ CA doit être disponible, si il n'est<br>
-+ # pas dans le fichier de certificat<br>
-+ # Ce fichier peut aussi contenir les certificats CA d'autres CA de confiance.<br>
-+ # Vous devez utiliser ce fichier pour lister les CA de confiance si voulez utiiser
-+ le mode chroot<br>
-+ # Cette variable n'a aucune valeur fixèe par défaut<br>
-+ <br>
-+ smtp_tls_CAfile = /etc/postfix/CAcert.pem <br>
-+ <br>
-+ # Pour vérifier le certificat de pair, nous devons connaître les certificats des
-+ autorités de certification. Ces certificats <br>
-+ # au format PEM sont rassemblés en répertoire. N'oubliez pas de créer
-+ les tables de hachage nécessaires avec<br>
-+ # un $OPENSSL_RACINE/bin/c_rehash /etc/postfix/certs, il n'y a pas de valeurs
-+ par defaut et vous devez en <br>
-+ # renseigner une ici<br>
-+ # Pour utiliser cette option en mode chroot, ce repertoire ou une copie de celui-ci
-+ doit être dans la cage<br>
-+ <br>
-+ smtp_tls_CApath = /etc/postfix/certs <br>
-+ <br>
-+ # Pour obtenir des informations suplémentaires pendant la mise en place
-+ et les négociations TLS<br>
-+ # vous pouvez augmenter le niveau de journalisation de 0 à 4:<br>
-+ # 0 : rien a propos du TLS<br>
-+ # 1 : Notification de mise en route et information de certificat <br>
-+ # 2 : 1 + impression des niveaux pendant la négociation <br>
-+ # 3 : 2 + hexa et vidage mémoire Ascii du processus de négociation <br>
-+ # 4 : 4: 3 + hexa et vidage mémoire Ascii de transmission complète après STARTTLS
-+ <br>
-+ # utilisez le niveau 3 uniquement en cas de problémes. L'utilisation
-+ du niveau 4 est fortement déconseillée.<br>
-+ <br>
-+ smtp_tls_loglevel = 0 <br>
-+ <br>
-+ # le serveur et le client négocient une session, qui prend un certain temps
-+ machine machine et une certaine bande passante.<br>
-+ # La session est cachée seulement dans le processus de smtpd réellement en utilisant
-+ cette session et est détruite <br>
-+ # quand le processus meurt pour partager l'information de session entre les
-+ processus de smtpd, <br>
-+ # antémémoire de session peut être utilisée avec des bases de données
-+ SDBM (sous-programmes inclus dans Postfix/TLS)<br>
-+ # Puisque l'écriture concourante doit être supportée, seulement SDBM peut être
-+ utilisé. <br>
-+ <br>
-+ smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache <br>
-+ <br>
-+ # les sessions cachées ont un delais d'attente. Je n'utilise pas le défaut d'OpenSSL
-+ de 300sec, mais un plus long temps <br>
-+ # de 3600sec (= 1 heure). RFC2246 recommande un maximum de 24 heures <br>
-+ <br>
-+ # Par defaut TLS est désactivé, ainsi aucune différence au Postfix
-+ ordinaire n'est visible. Si vous l'activez <br>
-+ # TLS sera utilisé quand le serveur l'offrira.<br>
-+ # ATTENTION : Je n'ai pas eu accès à d'autres logiciels (autres que ceux énumérés)
-+ pour tester l'interaction.<br>
-+ # Sur certaines listes de diffusions il y a eu une discussion a propos des serveurs
-+ MS EXCHANGE qui offre TLS<br>
-+ # même si il n'est pas configuré, ainsi il pourrait être sage de
-+ ne pas utiliser ceci sur votre serveur central de messagerie<br>
-+ # car vous ne savez pas à l'avance si vous allez rencontrer ce genre
-+ de serveur. Utilisez les options de recipient/site à la place .<br>
-+ # Conseil: je l'ai activé sur mes serveurs de courrier et je n'a eu qu'une
-+ panne depuis que la version client de TLS <br>
-+ # est implémentée (c'était un serveur EXCHANGE mal configuré,
-+ j'ai contacté l'administrateur).<br>
-+ # Par conséquent j'en suis satisfait de l'utiliser tout le temps, mais
-+ je suis toutefois intéressé par des tests.<br>
-+ # Cependant vous aurez été prévenu ;-)<br>
-+ <br>
-+ # Dans le cas d'un echec, un code "4xx" (ndt: erreur temporaire) est
-+ émis et le message reste dans la file d'attente<br>
-+ # Spécifiez le ici si vous le voulez<br>
-+ <br>
-+ smtp_use_tls = yes <br>
-+ <br>
-+ # Vous pouvez IMPOSER l'utilisation de TLS, de sorte que seulement des connexions
-+ avec TLS soient acceptées<br>
-+ # De plus, le nom de l'hôte doit être identique au nom contenu dans
-+ le certificat. En outre, le certtificat doit <br>
-+ # passer avec succès la vérification, le client doit faire confiance
-+ à l'entité de certification qui a émis le certificat.<br>
-+ # Si le certificat ne correspond pas au nom de la machine ou si le test de vérification
-+ échoue un code "4xx" <br>
-+ # va être envoyé et le message va rester en file d'attente.<br>
-+ # Le nom d'hôte utilisé est évident, en effet il doit être
-+ le nom principal de la machine (pas de CNAME ici).<br>
-+ # Le comportement peut être changé avec l'option de smtp_tls_enforce_peername
-+ <br>
-+ <br>
-+ # smtp_tls_enforce_peername = yes <br>
-+ <br>
-+ # Comme offrir TLS par défaut peut être une mauvaise idéee
-+ (quelques machines offre STARTTLS mais<br>
-+ # la négociation va échouer avec des erreurs inexpliquables, il
-+ peut être une bonne idée de décider selon<br>
-+ # le destinataire ou la machine distante sur laquelle vous vous connectez<br>
-+ <br>
-+ # Décider par destinataire peut être difficile, car un seul message
-+ peut avoir plusieurs destinataires.<br>
-+ # Nous allons utiliser le mécanisme "nexthop" (prochain saut)
-+ interne de Postfix.<br>
-+ # Quand un message va être délivré, the "nexthop"
-+ est obtenu. Si il correspond à une entrée<br>
-+ # dans la liste smtp_tls_per_site, une action appropriée est effectuée<br>
-+ # Une entrée dans la table de transport ou l'utilisation de relay_host
-+ réecrivent le paramètre "nexthop"<br>
-+ # dans ce cas l'hôte de relayage doit être indiqué dans la
-+ liste. Dans tous les cas le nom <br>
-+ # de l'hote à contacter est résolu (en fait l'enregistrement MX
-+ ou le nom de la machine si il n'y a pas de MX)<br>
-+ # Conseil spécial pour le renforcement: <br>
-+ # puisqu'il n'y a aucun moyen disponible pour sécuriser les résolutions
-+ DNS , le paramètrage recommandé est:<br>
-+ # mettez les domaines sensibles dans une table de transport (vous pouvez ainsi
-+ vous assurer de la sécurité<br>
-+ # de cette table à la différence de DNS), puis paramétrez
-+ à MUST cet hôte de messagerie.<br>
-+ <br>
-+ # Format de la table:<br>
-+ # Le entrées clefs sont sur le coté gauche, les jokers ne sont
-+ pas autorisés. Sur la partie droite<br>
-+ # les mots clefs NONE (n'utilise pas TLS), MAY (essaye d'utiliser TLS si il
-+ est offert, sinon pas de problèmes)<br>
-+ # MUST (force l'usage de TLS, vérifie le nom du certificat server avec
-+ le nom du serveur), MUST_NOPEERMATCH<br>
-+ # (force l'usage de TLS et vérifie le certificat, mais ignore les différences
-+ entre le nom commun du certificat et le nom<br>
-+ # de la machine).<br>
-+ # dom.ain NONE <br>
-+ # host.dom.ain MAY <br>
-+ # important.host MUST <br>
-+ # some.host.dom.ain MUST_NOPEERMATCH </p>
-+ <p># Si une entrée ne correspond pas la politique par défaut est
-+ appliquée; si la politique par défaut est "enforce",<br>
-+ # NONE la désactive explicitement, sinon le mode "enforce"
-+ est utilisé même pour les entrées "MAY"<br>
-+ # <br>
-+ smtp_tls_per_site = hash:/etc/postfix/tls_per_site <br>
-+ <br>
-+ # la profondeur de vérification pour des certificats de client. Une profondeur
-+ de 1 est suffisante si le certificat<br>
-+ # est émis directement par un CA listé dans la liste des CA.<br>
-+ # La valeur par defaut (5) suffit également pour de plus longues chaînes (le
-+ root CA émet le CA spécial <br>
-+ # qui délivre alors le certificat réel...) <br>
-+ <br>
-+ # smtp_tls_scert_verifydepth = 5 <br>
-+ <br>
-+ # Comme nous avons décidé d'opter pour une politique "par site"
-+ afin d'utiliser ou non TLS, il serait interessant<br>
-+ # d'avoir une liste de sites offrant STARTTLS. Nous pouvons la récupérer
-+ nous mêmes avec cette option:<br>
-+ # Si ce paramètre est activé et que TLS n'est pas activé
-+ pour cet hôte, une ligne est ajouté dans le fichier<br>
-+ # de journalisation:<br>
-+ # postfix/smtp[pid]: Host offered STARTTLS: [nom.de.la.machine] <br>
-+ # smtp_tls_note_starttls_offer = yes <br>
-+ <br>
-+ # Pour influencer la sélection du cryptage, vous pouvez donner une liste
-+ de cryptage.<br>
-+ # Une description complète irait troin loin ici, allez voir la documentation
-+ sur le site d'OpenSSL<br>
-+ # Si vous ne savez pas quoi faire avec, n'y touchez pas et laissez celui d'openssl
-+ par defaut <br>
-+ # N'UTILISEZ PAS " pour entourer la chaîne de caractères, juste la chaîne de
-+ caractères!!! <br>
-+ #<br>
-+ # smtp_tls_cipherlist = DEFAULT <br>
-+ <br>
-+ # le smtp_starttls_timeout paramètre limite le temps en secondes pour
-+ lire et écrire<br>
-+ # les opérations pendant les procédures de 'serrages de mains'
-+ (SSL handshake) <br>
-+ # <br>
-+ # smtp_starttls_timeout = 300s <br>
-+ </p>
-+ <p>main.cf : variables générales</p>
-+ <p># Afin d'alimenter le PRNG Pseude Random Number Generator (pseudo générateur
-+ de nombres aléatoires),<br>
-+ # des données aléatoires sont nécéssaires. Le 'stock'
-+ de PRNG est mis à jour par le démon "tlsmgr" et est
-+ utilisé (lu) <br>
-+ # par les process smtp(d) après avoir ajouté encore plus d'entropie par l'agitation
-+ du temps et de l'identifiant du process.<br>
-+ # le fichier, qui est de temps en temps réécrit par tlsmgr, est
-+ créé si il n'existe pas. Une valeur par défaut est donnée<br>
-+ # et doit sûrement être dans la partition /var mais PAS dans la
-+ cage de chroot.<br>
-+ <br>
-+ # tls_random_exchange_name = /etc/postfix/prng_exch <br>
-+ <br>
-+ # Pour alimenter le stock PRNG, l'entropie est lue depuis une source externe,
-+ à la fois au démarrage et pendant l'éxecution<br>
-+ # Spécifiez ici une bonne source, comme EGD ou /dev/urandom, soyez certains
-+ de ne pas utiliser des sources bloquantes<br>
-+ # Dans les deux cas, 32 octets sont lus à chaque 'alimentation' (qui
-+ est une quantité de 256 bits et par conséquent <br>
-+ # assez bon pour des clefs symétriques de 128bits)<br>
-+ # Vous devez spécifier la type de sources : "dev:" pour un
-+ pour un fichier spécial de périphérique ou "egd:" pour<br>
-+ # une source avec un port de communication (socket) compatible avec l'interface
-+ EGD. Un maximum de 255 octets<br>
-+ # est lu depuis ces sources à chaque étape.<br>
-+ # Si vous spécifiez un fichier normal, un plus grand nombre de données
-+ peut être lu.<br>
-+ <br>
-+ # La source d'entropie est interrogée de nouveau après un certains
-+ temps. ce temps est calculé en utilisant le PRNG,<br>
-+ # il est compris entre 0 et le temps spécifié, un defaut est spécifié
-+ à 1 heure<br>
-+ <br>
-+ # tls_random_source = dev:/dev/urandom <br>
-+ tls_random_source = egd:/var/run/egd-pool <br>
-+ # tls_random_bytes = 32 <br>
-+ # tls_random_reseed_period = 3600s <br>
-+ <br>
-+ # Le stock PRNG dans tlsmgr est utilisé pour regénérer
-+ le fichier de 1024 octets qui est lu par smtp(d). Le temps, après lequel<br>
-+ # le fichier d'échange se trouve regénéré est calculé
-+ en utilisant le PRNG, il est compris entre 0 et le temps spécifié,
-+ <br>
-+ # le defaut est un maximum de 60 secondes<br>
-+ <br>
-+ # tls_random_upd_period = 60s<br>
-+ <br>
-+ # Si vous avez une source d'entropie disponible, qui n'est pas facilement vidée
-+ (comme /dev/urandom), les démons<br>
-+ # peuvent aussi charger une entropie supplémentaire au démarrage
-+ depuis une source spécifiée. Par défaut une quantité<br>
-+ # de 32 octets est lue, équivalent à 256 bits. Ceci est plus que suffisant pour
-+ générer une clef de session de 128 (ou 168) bits<br>
-+ # mais nous avons à en générer plus d'une. L'utilisation
-+ de cette option peut vider EGD (en prenant le cas de 50 smtp <br>
-+ # démarrant avec une file d'attente pleine en faisant "postfix start",
-+ ceci devrait requérir 1600 octets d'entropie). Ceci<br>
-+ # n'est cependant pas une cause d'arrêt, du fait que les données
-+ d'entropie peuvent être lues depuis le fichier d'échange.<br>
-+ <br>
-+ # tls_daemon_random_source = dev:/dev/urandom <br>
-+ tls_daemon_random_source = egd:/var/run/egd-pool <br>
-+ # tls_daemon_random_bytes = 32 </p>
-+ <p>master.cf: le démon tlsmgr</p>
-+ <p>Si vous n'avez pas de périphérique /dev/urandom ou si vous n'utilisez
-+ pas le système de cache de session, vous devez lancer <br>
-+ le démon tlsmgr (voir conf/master.cf). Tlsmgr a besoin d'avoir accés
-+ à la source d'entropie et ne peut (encore) être éxécuté
-+ <br>
-+ dans une cage. Il peut restreindre ses privilèges, si les sources d'entropie
-+ (par exemple /dev/urandom ou un port de communication<br>
-+ (socket) EGD) n'ont pas des restrictions d'accès.<br>
-+ <br>
-+ # ==========================================================================
-+ <br>
-+ # service type private unpriv chroot wakeup maxproc command + args <br>
-+ # (yes) (yes) (yes) (never) (50) <br>
-+ # ==========================================================================
-+ <br>
-+ tlsmgr fifo - - n 300 1 tlsmgr </p>
-+ <p>master.cf: services supplémenentaires</p>
-+ <p> Il peut être pratique d'avoir postfix écoutant sur des ports supplémentaires,
-+ nommés "submission"=587 pour la <br>
-+ soumission d'email comme défini dans la RFC2476; c'est particulièrement utile
-+ si vous voulez permettre une authentification<br>
-+ avec des mots de passes en clair (PLAIN,LOGIN) et par conséquent exécuter sur
-+ un port avec l'application de <br>
-+ chiffrement. Un autre port utile peut être "smtps"=465 qui a été destiné pour
-+ l'emballage TLS et qui est toujours<br>
-+ utlisé par outlook (express)<br>
-+ <br>
-+ Les deux entrées d'exemple contiennent déjà les indicateurs pour permettre l'authentification
-+ de SASL (qui peut être <br>
-+ desactivé sur le port normal). Puisque les noms réels de service sont
-+ utilisés, les smtps et la soumission doivent être définis<br>
-+ dans /etc/services (et probablement aussi dans / var/spool/postfix/etc/services
-+ si éxecuté dans une cage)!!! <br>
-+ (utilisez les numéros de ports autrement.) <br>
-+ <br>
-+ # ==========================================================================
-+ <br>
-+ # service type private unpriv chroot wakeup maxproc command + args <br>
-+ # (yes) (yes) (yes) (never) (50)<br>
-+ # ==========================================================================
-+ <br>
-+ smtps inet n - y - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
-+ <br>
-+ submission inet n - y - - smtpd -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes
-+ </p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/index.html postfix-2.0.16-ti1.20/pfixtls/doc_french/index.html
-*** postfix-2.0.16/pfixtls/doc_french/index.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/index.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,35 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p><b>Postfix/tls - Une extension TLS pour Postfix </b></p>
-+ <p><b>Contenu : </b></p>
-+ <p><a href="intro.html">Introduction </a></p>
-+ <p><a href="install.html">Installation de la mise à jour </a></p>
-+ <p><a href="setup.html">Configurer les certificats </a></p>
-+ <p><a href="conf.html">Configurer main.cf </a></p>
-+ <p><a href="security.html">Considérations de sécurité </a></p>
-+ <p><a href="test.html">Tester </a></p>
-+ <p>RAPPELEZ VOUS QU'IMPORTER/EXPORTER ET/OU L'USAGE DE LOGICIELS USANT<br>
-+ DE CHIFFREMENT FORT, FOURNIR DES POINTS D'ENTREE POUR DES FONCTIONS <br>
-+ CRYPTOGRAPHIQUES OU DIVULGUER DES TECHNIQUES DE CRYPTOGRAPHIE EST<br>
-+ ILLEGAL DANS CERTAINES PARTIES DU MONDE. DONC SI VOUS IMPORTEZ CE <br>
-+ PAQUET DANS VOTRE PAYS, LE REDISTRIBUEZ DEPUIS ICI OU MEME JUSTE<br>
-+ ENVOYER DES SUGGESTIONS TECHNIQUES PAR COURRIER ELECTRONIQUE OU <br>
-+ MEME DES CORRECTIONS DE SOURCES A L'AUTEUR OU D'AUTRES PERSONNES<br>
-+ VOUS ETES LARGEMENT INVITE A FAIRE ATTENTION A TOUTES LES LOIS<br>
-+ CONCERNANT L'IMPORT/EXPORT QUI S'APPLIQUENT DANS VOTRE PAYS.<br>
-+ L'AUTEUR DE POSTFIX/TLS NE PEUT PAS ETRE TENU POUR RESPONSABLE EN CAS<br>
-+ DE VIOLATION. DONC FAITES TRES ATTENTION, IL EN VA DE VOTRE RESPONSABILITE.</p>
-+ <p> </p>
-+ <p>Lutz Jänicke,<a href="http://www.aet.tu-cottbus.de/personen/jaenicke/"> Homepage</a>,
-+ Email: <a href="mailto:Lutz.Jaenicke@aet.TU-Cottbus.DE">Lutz.Jaenicke@aet.TU-Cottbus.DE</a>
-+ </p>
-+ Merci a tous ceux qui m'ont aidé sur #linuxfr ;-)
-+ </body>
-+ </html>
-+
-+
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/install.html postfix-2.0.16-ti1.20/pfixtls/doc_french/install.html
-*** postfix-2.0.16/pfixtls/doc_french/install.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/install.html Mon Jan 5 16:58:05 2004
-***************
-*** 0 ****
---- 1,57 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>postfix/TLS - Installation de la mise a jour</p>
-+ <p>Prérequis:<br>
-+ Postfix Version 2.0.15<br>
-+ http://www.postfix.org </p>
-+ <p>L'utilisation d'autres versions pourrait mener à des conflits ou à des pannes
-+ silencieuses du fait que nous intervenons directement sur le code source.<br>
-+ OpenSSL Version 0.9.5 ou plus (0.9.7b recommandée)<br>
-+ http://www.openssl.org</p>
-+ <p>Nous utilisons OpenSSL comme bibliothèque (et quelques outils en ligne de commande
-+ pour créer les certificats, au besoin). OpenSSL est le successeur de SSLeay.
-+ </p>
-+ <p>Postfix/TLS utilise les propriétés qui sont seulement disponibles à
-+ partir de la version 0.9.5 des bibliothèque OpenSSL. 0.9.5a a prouvé une stabilité
-+ au delà de plusieurs mois. La dernière version 0.9.7b contient plusieurs
-+ améliorations et a prouvé sa stabilité jusqu'ici. <br>
-+ Vous pouvez également avoir à mettre à jour votre utilitaire 'patch'(voir ci-dessous).
-+ </p>
-+ <p>Mettre à jour:</p>
-+ <p>Les modifications du code source de Postfix tout comme les fichiers supplementaires
-+ sont inclus dans le fichier "pfixtls.diff" dans le répertoire
-+ principal du kit de mise à jour.<br>
-+ Pour appliquer la mise à jour, allez dans le répertoire parent de l'arborescence
-+ des sources originales de Postfix (vous devez voir "postfix-xxxxxx"
-+ ou "snapshot-xxxxxx" quand vous faites un "ls -al" depuis
-+ ce repertoire. La mise à jour est alors appliquee par:</p>
-+ <p>patch -p0 < chemin-de/pfixtls.diff </p>
-+ <p>Si vous avez des problèmes pendant le processus de mise à jour (par exemple avec les
-+ includes de HP-UX 10.20), vous devriez mettre à jour votre utilitaire de patch,
-+ par exemple un GNU-patch plus récent.<br>
-+ Si vous avez besoin d'appliquer la mise à jour sur une autre version de postfix, vous
-+ pouvez essayer:<br>
-+ cd repertoire-postfix; patch -p1 < chemin-de/pfixtls.diff <br>
-+ Puisque la mise à jour est sous forme unifiée, elle peut être également
-+ appliqué à un code source modérément modifié
-+ sans que des conflits apparaissent.</p>
-+ <p>Compiler</p>
-+ <p>Apres être mis à jour; postfix va se configurer et se compiler comme
-+ avant. Dans le but d'activer les fonctions TLS, vous devez spécifier
-+ le chemin des headers OpenSSL ainsi que les bibliothéques appropriées,
-+ et vous devez définir USE_SSL. Votre commande pour la configuration doit
-+ être :<br>
-+ make makefiles CCARGS="-DUSE_SSL -I/usr/local/ssl/include" AUXLIBS="-L/usr/local/ssl/lib
-+ -lssl -lcrypto" <br>
-+ Vous pourriez avoir besoin de personnalisation supplémentaire par exemple pour
-+ l'usage des Berkeley-DB comme énuméré dans les instructions INSTALL de postfix
-+ . Vous pouvez alors continuer de la manière habituelle avec: <br>
-+ make</p>
-+ <p>et ensuite suivre les instructions du fichier INSTALL de postfix</p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/intro.html postfix-2.0.16-ti1.20/pfixtls/doc_french/intro.html
-*** postfix-2.0.16/pfixtls/doc_french/intro.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/intro.html Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,116 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>Postfix/TLS - Introduction</p>
-+ <p>Postfix/PLS est une extension du MTA Postfix dans le but de supporter le protocole
-+ TLS</p>
-+ <p>Une note à propos du démarrage du projet</p>
-+ <p>Quand j'ai commencé a écrire ce programme, j'avais en tête un un moyen sophistiqué
-+ pour autoriser le relayage de mes utilisateurs itinérants. En
-+ attendant ce projet vit de lui-même.</p>
-+ <p>RFC2246 : le protocol TLS (anciennement SSL)</p>
-+ <p>Par défaut toutes les communications sur internet sont faites sans cryptage
-+ et sans authentification forte. Cela signifie que toute personne avec un accès
-+ physique au chemin de communication qu'emprunte un paquet peut écouter vos communications.
-+ Pire, il est même possible de rediriger ou de modifier vos communications donc
-+ l'information que vous voulez envoyer à quelqu'un peut être perdue ou modifiée
-+ à votre insu.</p>
-+ <p>Dans le but de résoudre ces problèmes de sécurité, le protocole SSL (Secure
-+ Socket Layers), présenté par Netscape inc.,
-+ a maintenant évolué en protocole TLS (Transportation Layer Security)
-+ standardisé par la <a href="http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/doc/rfc2246.txt">RFC2246</a>.
-+ Cela permet à la fois le cryptage de la communication (arrêt des
-+ écoutes) et l'authentification forte (être sûr que les deux parties de
-+ la communication sont correctement identifiées et que la communication
-+ ne peut pas être altérée)</p>
-+ <p>Postfix/TLS ne réalise pas le protocole TLS lui-même, il utilise
-+ plutôt le package OpenSSL pour cette tâche. Sur le site d'OpenSSL, vous
-+ trouverez aussi des liens vers une documentation plus approfondie sur le
-+ protocole et ses dispositifs, il n'est donc pas nécessaire de les inclure
-+ ici. (Et, bien sûr il n'y a aucune utilité de réécrire ce
-+ que d'autres ont déjà ecrits, cela présente juste l'intérêt
-+ de rajouter des erreurs)</p>
-+ <p> </p>
-+ <p>RFC2487: Présentation de TLS a SMTP</p>
-+ <p>L'intégration du protocole TLS au protocole SMTP (Simple Mail Transport Protocol)
-+ est décrit dans la RFC2487</p>
-+ <p>À la différence des premières incarnations du SSL comme 'emballage'
-+ d'une communication normale [STUNNEL] [JONAMA], le protocole TLS est maintenant
-+ complétement intégré dans SMTP : pendant la négociation
-+ de départ (EHLO) le serveur offre le support de TLS avec la commande
-+ STARTTLS. Le client peut maintenant envoyer la commande STARTTLS pour permettre
-+ l'authentification et passer en mode crypté.</p>
-+ <p>Postfix/TLS : Ce qu'il peut faire pour vous </p>
-+ <p>La liste de fonctions présentée ici doit être comprise
-+ comme une liste d'idées. Toutes ne sont pas encore réalisées,
-+ regardez bien les notes pour chaque fonction.</p>
-+ <p>Encryption de message d'une machine à une autre:<br>
-+ Etat: Fait<br>
-+ Commentaire: une fois que la negociation STARTTLS est réalisée,
-+ la communication entre les deux machines est cryptée. Ceci inclue aussi
-+ les enveloppes MAIL FROM: et RCPT TO:, les 'sniffeurs' ne seront pas capables
-+ d'avoir ces informations.</p>
-+ <p>Authentification de l'hôte récepteur afin d'éviter une interception<br>
-+ Etat: Fait<br>
-+ Commentaire: Ceci est une fonction importante qui n'est pas difficile a implementer.
-+ Le problème est en fait que toutes les machines (en fait presque aucune) ne
-+ supportent pas ce protocole. L'expéditeur doit par conséquent mettre à jour une liste
-+ de récepteurs qui doivent s'identifier par TLS, sinon quelqu'un peut intercepter
-+ la session et ne pas prèsenter la commande STARTTLS, dans ce cas, aucune authentification
-+ n'est faite. On doit également faire attention à utiliser le nom correct du
-+ serveur (voir le CNAME), mais ce problème est le même pour des serveurs HTTP.</p>
-+ <p>Authentification de l'hote émetteur afin d'éviter la contrefaçon<br>
-+ Etat: Fait<br>
-+ Commentaire: Ceci est l'idée à l'origine de ce projet, ce fut
-+ donc la première réalisation. Basé sur le certificat du
-+ client MTA (ou MUA) présenté au serveur, le relayage peut être
-+ ainsi autorisé.</p>
-+ <p>D'autres idées:<br>
-+ Etat: envoyez moi un message</p>
-+ <p>Postfix/TLS: ce qu'il ne peut pas faire pour vous</p>
-+ <p>Voici un point sur lequel je veux insister:</p>
-+ <p>Garantir l'intimité de votre correspondance<br>
-+ Etat: ne peut pas etre fait<br>
-+ Commentaire: La RFC2487 ne prend en compte uniquement le transport entre deux
-+ serveurs de courrier. Pour vous assurer que personne ne peut 'sniffer' votre
-+ correspondance il faudrait que:<br>
-+ - Tous les serveurs de courrier soient forcés en TLS<br>
-+ - Tous les serveurs eux-mêmes soient dignes de confiance, car l'email est seulement
-+ chiffré pendant le transport, pas en spool ni en queue.<br>
-+ - La destination soit digne de confiance, car le courrier est spoolé en
-+ clair et toute personne pouvant accéder à votre boite aux lettres (root par exemple)
-+ peut lire votre courrier! <br>
-+ Par conséquent, si vous voulez une intimité plus conséquente, vous devez
-+ envoyer votre email chiffré, par exemple en utilisant S/MIME ou le module traditionnel
-+ de PGP</p>
-+ <p>Authentifier l'émetteur du message<br>
-+ Etat: ne peut être fait<br>
-+ Commentaire: Beaucoup de MUA envoient les messages juste en se connectant sur
-+ le port SMTP de l'hôte local ou du mailhub le plus proche. il n'y a aucun moyen
-+ de s'assurer que l'émetteur listé dans le message est bien l'émetteur
-+ réel. Et même si il était possible d'identifier l'émetteur,
-+ le contenu du message pourrait avoir été modifié entre
-+ temps.<br>
-+ Pour assurer l'identité de l'expéditeur et l'intégrité de l'email, vous pouvez
-+ encore employer S/MIME ou PGP. </p>
-+ <p>D'autres packages Opensource:<br>
-+ Depuis la version 8.11 sendmail intègre le support de la RFC2487.<br>
-+ Frederik Vermeulen a réalisé une extension de la RFC2487 pour
-+ le MTA Qmail.<br>
-+ Matti Aarnio a intégré la RFC2487 dans ZMailer.<br>
-+ Michal Trojnara est actuellement en train d'intégrer un système basique
-+ d'authentification SMTP dans son logiciel stunnel depuis la version stunnel-3.3.<br>
-+ Trey Childs travaille sur une solution d'emballage.</p>
-+ <p>Implémentations commerciales:</p>
-+ <p>La version commerciale de sendmail supporte la RFC2487.<br>
-+ Netscape Enterprise Server et Microsoft exchange server supportent aussi la
-+ RFC 2487.<br>
-+ CommunigatePro mailserver software supporte aussi la RFC2487.</p>
-+ <p> </p>
-+ <p> </p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/security.html postfix-2.0.16-ti1.20/pfixtls/doc_french/security.html
-*** postfix-2.0.16/pfixtls/doc_french/security.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/security.html Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,67 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>Postfix/TLS - Considérations de Sécurité</p>
-+ <p>Les sections suivantes couvrent quelques considérations de sécurités
-+ (possibles) en ce qui concerne Postfix/TLS.</p>
-+ <p>Clef privée du client/serveur<br>
-+ Postfix/TLS utilise l'authentification du côté serveur (obligatoire) et du côté
-+ client (facultatif). Afin de s'authentifier, <br>
-+ le processus défini (smptd/smtp) doit pouvoir accéder à la clef privée,
-+ qui doit cependant être maintenue secrète.<br>
-+ Car ces processus sont lancés à partir de 'master' sans possibilité d'interaction
-+ d'utilisateur, il n'est pas possible <br>
-+ de fournir un mot de passe, de sorte que la clef privée ne puisse pas être chiffrée.
-+ </p>
-+ <p>La seule protection peut donc venu des droits d'accès de systéme de
-+ fichiers, qui devraient être placés <br>
-+ Ã 'root' et ' lisible pour le propriétaire seulement <br>
-+ -rw------- 1 root sys 887 Apr 29 1999 /etc/postfix/key.pem <br>
-+ <br>
-+ Cette protection n'est valable que si votre système est protégé
-+ contre les failles de sécurités concernant root<br>
-+ <br>
-+ Vous devez aussi vous rendre compte que des personnes ayant un accés physique
-+ à la machine peuvent voler<br>
-+ la clef privée si ils peuvent démarrer la machine en mode 'superutilisateur'
-+ (single-user) sans mot de passe<br>
-+ ou peuvent voler le disque et le monter sur un autre système où
-+ ils sont super-utilisateur. (Oui je sais qu'il existe <br>
-+ des systémes de fichiers encryptés mais ils n'ont pas encore une
-+ large diffusion)</p>
-+ <p>Antémemoire de session sur le disque</p>
-+ <p>Si vous utilisez l'antémemoire de session sur le disque (par défaut)
-+ des personnes capables mettre la main sur les fichiers <br>
-+ devraient pouvoir éviter les paramètres de transmission sécurisée.
-+ Cette situation n'est cependant pas plus grave que le cas<br>
-+ de la clef privée décrit ci-dessus, ainsi je ne considère aucun
-+ danger supplémentaire venant de l'enregistrement information <br>
-+ de session sur un peripherique de stockage <br>
-+ <br>
-+ Casser le cryptage avec un système de clefs n'est qu'une affaire de temps
-+ (même si ce temps peut être très long), les sessions<br>
-+ ne devraient pas être utilisées indéfiniment. La valeur par défaut
-+ pour Postfix/TLS est 1 heure, la RFC 2246 recommande <br>
-+ de ne pas utiliser les sessions plus de 24 heures</p>
-+ <p>Solutions pour le DNS<br>
-+ Un point faible dans l'authentification est l'utilisation du DNS pour découvrir
-+ le MX. Comme nous faisons du (E)SMTP<br>
-+ nous avons à utiliser les enregistrements MX.<br>
-+ Comme nous avons à authentifier le server découvert par le MX,
-+ quelqu'un est capable d'usurper un faux enregistrement MX<br>
-+ pour être capable de recevoir le mail, si son serveur peut présenter un
-+ certificat délivré par un CA acceptable. La dernière <br>
-+ partie n'est pas difficile si les certificat 'standarts' sont inclus (Verisign,
-+ Thawte,...)<br>
-+ Le seul moyen de se protéger contre ce problème est que, pour
-+ les destinataires pour lesquels nous voulons imposer le <br>
-+ chiffrement et l'authentification, la consultation de MX doit être ignorée avec
-+ une entrée appropriée dans la table /etc/postfix/transport<br>
-+ <br>
-+ domaine.tres.important smtp:[server.du.domaine.important]</p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/setup.html postfix-2.0.16-ti1.20/pfixtls/doc_french/setup.html
-*** postfix-2.0.16/pfixtls/doc_french/setup.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/setup.html Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,162 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>Postfix/TLS - Paramétrer les certificats</p>
-+ <p>Ce paragraphe explique quels types de certificats sont nécessaires pour utiliser
-+ postfix avec TLS. Les certificats (et peut être les clefs) peuvent être
-+ obtenus auprès de tierces parties, qui peuvent être une autorité
-+ de certification commerciale ou votre FAI. Tout le long vous aurez besoin de
-+ certificats acceptés par d'autres entités sur internet, vous avez
-+ donc à être d'accord sur les entités de certifications,
-+ quelque soit leurs types.</p>
-+ <p>certificat serveur</p>
-+ <p>Pour utiliser SMTP avec TLS en mode serveur, votre serveur DOIT avoir une paire
-+ de clefs (privée et publique).<br>
-+ Puisque la clé publique doit être distribuée de façon ou d'autre au client,
-+ elle est envoyée du serveur au client pendant la négociation de départ.
-+ Cependant,au début de la négociation, le client ne peut pas savoir que
-+ la clef publique appartient réellement au serveur et n'est pas contrefaite.
-+ Par conséquent un troisième composant est nécessaire : le certificat d'une autorité
-+ de certification (CA), qui est envoyé combiné avec la clef publique. Ce certificat
-+ de serveur contient le nom de votre hote. Le client contrôlera alors la signature
-+ du CA sur la clef publique pour décider si le certificat (et la clef publique)
-+ sont authentiques. <br>
-+ Ainsi pour le serveur nous avons besoin: <br>
-+ - 1 clef privée de serveur<br>
-+ - 1 clef publique de serveur signée par une autorité de certification,
-+ certifiant que la clef publique appartient à votre hôte
-+ <br>
-+ - 1 certificat CA avec la clef publique du CA<br>
-+ Pour cette liste je veux absolument préciser que le nombre de composants utilisés
-+ est 1, parce que vous devez en avoir 1, vous ne pouvez pas en avoir ni moins
-+ ni plus!</p>
-+ <p>Politique de certificat serveur</p>
-+ <p>A partir de maintenant vous avez à vous décider sur la politique.
-+ Le client qui va se connecter sur votre hôte va comparer le nom dans le
-+ certificat de votre serveur à son FQDN (Fully Qualified Domain Name). Si ils
-+ correspondent, l'identité de votre serveur est prouvée.<br>
-+ Pour voir, si le certificat lui-même est authentique, le client lui-même doit
-+ avoir le certificat du CA. Ainsi, si vous voulez le rendre facilement accessible
-+ Ã d'autres, parties inconnues, vous devez avoir un certificat issu d'un CA connu
-+ et digne de confiance. Rappelez vous que votre serveur ne peut avoir qu'un certificat
-+ à la fois.<br>
-+ Il y a des fournisseurs commerciaux (Thawte, Verisign, pour n'en citer que quelques
-+ uns), leurs certificats CA sont bien distribués. Je ne sais pas pour
-+ les autres pays mais en Allemagne le organisation de la recherche reseaux (DFN) a commencé
-+ un programme pour les universités.<br>
-+ Si vous ne portez pas d'importance à ceci (vous pourrez le changer plus
-+ tard), vous pouvez devenir votre propre CA et distribuer vos certificat de CA
-+ aux parties qui devront le connaitre, et vous êtes prêts. Ce n'est
-+ pas difficile de le faire.<br>
-+ <a href="http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/doc/myownca.html">Le
-+ cours tres bref de Lutz pour être votre propre CA</a> (toujours en anglais ..)</p>
-+ <p>Utiliser les certificats</p>
-+ <p>Pour rendre la clef et les certificats utilisables par Postfix/TLS, ils doivent
-+ être au format "PEM". Puis vous avez à indiquer à
-+ postfix où les trouver:<br>
-+ - La clef privée:<br>
-+ <br>
-+ smtpd_tls_key_file = /etc/postfix/key.pem<br>
-+ <br>
-+ comme la clef publique est publique y compris le certificat (tout le monde peut
-+ la récupérer), une personne disposant d'une copie de votre clef
-+ privée peut usurper votre identitée. Ce n'est pas si facile que
-+ ça, du fait qu'il doit être capable d'intercepter ou de rediriger
-+ les paquets envoyés vers votre serveur, mais j'ai déja vu bien
-+ de choses arriver. Donc protégez cette clef avec :<br>
-+ <br>
-+ chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem <br>
-+ <br>
-+ Une autre possibilité de protection est la 'phrase clef'. Ceci est toutefois
-+ un problème, du fait que vous ayez à le taper à chaque fois que
-+ le server est démarré. Ceci a des inconvenients : premièrement
-+ vous devez le taper dans postfix à chaque fois que vous le redémarrez.
-+ Deuxièmement les process smtpd sont lancés indépendamment
-+ à partir de master, dans ce cas master doit passer la 'phrase clef' aux
-+ clients d'une façon ou d'une autre. Tout cela fait que je pense que cette
-+ méthode n'est pas pratique et donc n'est pas supportée par le programme.<br>
-+ <br>
-+ - Le certificat serveur : ce certificat n'est pas secret, du fait qu'il est
-+ présenté à chaque client de toutes façons, ainsi
-+ nommez le juste a postfix :<br>
-+ <br>
-+ smtpd_tls_cert_file = /etc/postfix/cert.pem<br>
-+ <br>
-+ Si vous voulez vous pouvez concaténer la clef privée et le certificat
-+ dans le même fichier.<br>
-+ <br>
-+ - Le certificat CA: pour avoir également le certificat CA disponible,
-+ écrivez le dans un fichier et donnez le nom à postfix/TLS. Nous reviendrons
-+ plus tard sur ce fichier.<br>
-+ <br>
-+ smtpd_tls_CAfile = /etc/postfix/CAcert.pem <br>
-+ <br>
-+ Avec ces certificats vous devez être en mesure de faire tourner Postfix/TLS.</p>
-+ <p>Postfix/TLS en mode client<br>
-+ <br>
-+ Quand il se connecte à un serveur offrant TLS postfix peut présenter
-+ un certificat client de lui même. Du fait de la réalisation actuelle,
-+ seulement un certificat ne peut être contrôlé, ainsi il devrait être émis depuis
-+ votre propre nom d'hôte. Par défaut aucun certificat n'est présenté,
-+ Ã moins que vous placiez explicitement le certificat dans la configuration.
-+ Vous pouvez utiliser le même certificat que pour le serveur: <br>
-+ <br>
-+ smtp_tls_key_file = /etc/postfix/key.pem <br>
-+ chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem <br>
-+ <br>
-+ smtp_tls_cert_file = /etc/postfix/cert.pem <br>
-+ smtp_tls_CAfile = /etc/postfix/CAcert.pem<br>
-+ </p>
-+ <p>Certificats clients:<br>
-+ <br>
-+ Une des raisons pour laquelle j'ai fait ce travail est que je voulais faire
-+ du relayage basé sur les certificats clients. Le client présente
-+ un certificat d'un CA, qui est unique et ne peut être usurpé.<br>
-+ Des clients peuvent avoir plusieus certificats émis par diffèrents CA.
-+ Lors de la connexion le serveur passera au client la liste de CA qu'il connait
-+ (les certificats de CA) et le client peut alors choisir le certificat à
-+ passer. Avec Netscape cela signifie qu'une fenêtre est ouverte et seulement
-+ le certificat client est listé.<br>
-+ Donc si vos clients ont déjà des certificats émanant de
-+ sources de confiances ce n'est pas nécessaire de se créer des
-+ problémes. Vous avez juste à récupérer les certificats
-+ CA et les rendre disponibles à Postfix/TLS. Si ce n'est pas suffisant,
-+ vous pouvez toujours devenir votre propre CA pour créer facilement vos
-+ certificats clients pour vos usagers (qui sont naturellement inutiles en dehors
-+ de votre portée)</p>
-+ <p>Lister les certificats CA<br>
-+ <br>
-+ Vous avez deux possibilité de faire ceci:<br>
-+ 1- Concaténez les certificats CA au fichier smtp[d]_tls_CAfile que vous
-+ avez créé. Ce fichier n'est certainement pas très lisible
-+ mais a l'avantage d'être lu par smtpd avant le changement dans la cage
-+ chroot et par conséquent fonctionne en mode chrooté.<br>
-+ 2- Vous pouvez ajouter les certificats CA dans plusieurs fichiers avec des noms
-+ adéquats dans un répertoire de certificats spécifié
-+ par:<br>
-+ smtpd_tls_CApath = /etc/postfix/certs<br>
-+ N'oubliez pas de faire un $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs après
-+ tout changement, car les tables de hachages sont utilisées pour trouver
-+ le bon certificat CA. Cette methode ne doit pas fonctionner en mode chrooté.</p>
-+ <p>Ajouter des certificats client:<br>
-+ <br>
-+ Les certificats de client sont délivrés pour un DN (Distinguished Name) (Nom
-+ Complet) composé de la compagnie, service, le nom, l'email... Du fait qu'ils
-+ peuvent contenir des blancs, des @, des signes et des colonnes, il est tout à fait
-+ difficile de les manipuler avec les outils standards de postfix. <br>
-+ Une chose tout à fait pratique est que chaque certificat de client a une " empreinte
-+ digitale " il est extrêmement difficile truquer que (à ma connaissance,
-+ elle pourrait prendre des années même sur les ordinateurs rapides). Je dois
-+ faire encore plus de recherche au sujet de la sécurité de l'empreinte digitale,
-+ mais au moins pour relayer cela doit être suffisament sécurisé.
-+ Je trouverai plus facilement une machine avec une mauvaise sécurité
-+ pour envoyer mon spam au lieu de truquer un certificat de client avec une empreinte
-+ digitale assortie (que d'ailleurs je ne connais pas depuis l'extérieur,
-+ même depuis l'interieur vous pouvez protéger la base "d'empreintes
-+ digitales" par un chmod 400)</p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/pfixtls/doc_french/test.html postfix-2.0.16-ti1.20/pfixtls/doc_french/test.html
-*** postfix-2.0.16/pfixtls/doc_french/test.html Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/pfixtls/doc_french/test.html Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,118 ----
-+ <html>
-+ <head>
-+ <title>Untitled Document</title>
-+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-+ </head>
-+
-+ <body bgcolor="#FFFFFF">
-+ <p>tester Postfix/TLS</p>
-+ <p>Le test du module est un peu difficile, car la transmission est chiffrée, de
-+ sorte que vous ne puissiez pas "imiter" la <br>
-+ conversation juste par un telnet sur le port smtp. Vous ne pouvez pas également
-+ capturer les paquets (vous pouvez, <br>
-+ mais si tout fonctionne comme annoncé, cela ne vous aidera pas :-). <br>
-+ <br>
-+ Outils de mise au point inclus:<br>
-+ Comme tous les messages générés par postfix sont envoyés
-+ au système de journalisation, la mise au point doit être faite<br>
-+ en utilisant vos fichier de journalisation. Postfix/TLS supporte les niveaux
-+ de journalisation de 0 (très calme) à 4 (vidange<br>
-+ mémoire de la conversation complète, non recommandé). Dans un premier temps
-+ placez smpt[d]_tls_loglevel=2 et <br>
-+ observez le fichier journal. Typiquement vous aurez des problèmes avec l'accès
-+ aux clés ou aux certificats, ainsi vous <br>
-+ trouverez des messages d'erreur ici. Vous pouvez toujours essayer d'envoyer
-+ un email à postfix_tls-bounce@serv01.aet.tu-cottbus.de <br>
-+ avec le TLS activé de votre côté et regardez ce qui se produit
-+ :-).<br>
-+ Tout en testant l'interopérabilité avec ZMailer nous avons appris qu'un certificat
-+ incorrect (qui doit être le serveur pour le serveur :-) peut <br>
-+ mener à des erreurs de connexions sans messages clairs. cela peut nous
-+ aider d'utiliser Netscape 4.5x en tant que client et d'étudier<br>
-+ soigneusement les informations ainsi que les boites de dialogue.<br>
-+ Je n'ai pas encore trouvé comment identifier le problème de postfix
-+ à afficher un message approprié dans le fichier de journalisation.<br>
-+ Si tout va bien ce sera possible sans modifier les bibliothèques d'OpenSSL.</p>
-+ <p>Plateformes:</p>
-+ <p>Plateformes de développement:<br>
-+ OS: HP-UX 10.20 <br>
-+ OS: Linux 2.x (SuSE Linux) <br>
-+ <br>
-+ Succés enregistrés:<br>
-+ OS: Solaris 2.5 - Walcir Fontanini <walcir@densis.fee.unicamp.br> </p>
-+ <p>Clients de test:<br>
-+ Software: Netscape 4.5x, Netscape 4.6x, Netscape 4.7x <br>
-+ OS: HP-UX 10.20, Linux 2.x, Win95 </p>
-+ <p>Intéropérabilité:<br>
-+ Sans compter le support par les solutions génériques d'emballage, il existe
-+ des extensions particulièrement travaillés pour<br>
-+ d'autres MTA:</p>
-+ <p>Qmail il y a un patch en sources libres disponible, étendant le MTA de Qmail
-+ pour supporter la RFC2487,<br>
-+ écrit par Frederik Vermeulen . L'envoi et la réception fonctionne des deux côtés.<br>
-+ Test: envoyez le courrier à ping@linux.student.kuleuven.ac.be (renverra l'email
-+ complet comprenant des en-têtes).<br>
-+ Zmailer l'autheur/développeur de ZMailer, Matti Aarnio, a incorporé le
-+ support serveur et client de TLS .<br>
-+ Zmailer - > Postfix très bien, <br>
-+ Postfix - > Zmailer ne fonctionne pas, puisqu'Esmtp n'est pas identifié (problème
-+ signalé). <br>
-+ Test: envoyez un courrier à autoanswer@mea.tmt.tele.fi (renverra des en-têtes).
-+ <br>
-+ Sendmail la verson commerciale supporte le client et le serveur TLS,
-+ les deux côtés fonctionnent avec Postfix/TLS.<br>
-+ En date de sendmail-8.11, TLS est également inclus avec la version opensource
-+ . <br>
-+ Test: envoyez le courrier à bounce@esmtp.org (reverra le message d'erreur comprenant
-+ de vieux en-têtes). <br>
-+ Postfix: peut s'envoyer des messages à lui-même :-)<br>
-+ Test: envoyez le courrier à postfix_tls-bounce@serv01.aet.tu-cottbus.de (reviendra,
-+ en incluant de vieux en-têtes). <br>
-+ <br>
-+ D'autres retour sont les bienvenus</p>
-+ <p>Problèmes connus:<br>
-+ Ce logiciel en est qu'à ses débuts, soyez donc patients. À ce
-+ jour j'ai ces points: </p>
-+ <p>Côté de serveur: Sous Win95/NT j'ai quelques problèmes avec les certificats
-+ de client. En ouvrant la première connexion <br>
-+ (Netscape demande le mot de passe pour accéder à la base de données de certificat),
-+ la connexion s'arrête. Ceci semble <br>
-+ être provoqué par Netscape: une vidange mémoire de la transmission montre que
-+ Netscape ne reprend pas la poignée de main<br>
-+ (TLS handshake) de TLS.<br>
-+ Remarque: je n'ai pas pu reproduire cette anomalie récemment après évolution
-+ d'OpenSSL 0.9.4. J'espère qu'elle a disparue,<br>
-+ mais peut-être est elle juste une conséquence du jeu autour avec les options
-+ de la sécurité de Netscape. Plus de test exigé... <br>
-+ Solution: détruisez cette connexion, la prochaine fonctionnera immédiatement
-+ ou utilisez SSLv2 seulement (deuxième solution<br>
-+ non recommandée).</p>
-+ <p>Doit être résolu avec OpenSSL 0.9.5<br>
-+ Coté serveur: Outlook Express tout comme Internet explorer 5 fonctionneront
-+ avec Postfix/TLS mais aucun certificat<br>
-+ client ne seront présentés. Ainsi vous pouvez chiffrer votre transfert
-+ de courrier mais vous ne pouvez pas vous authentifier <br>
-+ (et relayer) avec des certificats clients. Cela fonctionne seulement sur le
-+ port 25 (smtp); sur d'autres ports vous devez <br>
-+ utiliser le smtpd_tls_wrappermode à la place. <br>
-+ Coté serveur: Outlook Express tout comme Internet explorer 4 semble
-+ ne pas supporter la RFC2487. Utilisez <br>
-+ smtpd_tls_wrappermode=yes sur un autre port.<br>
-+ Coté serveur: Outlook Express (Mac) semble ne pas supporter la RFC2487.
-+ Utilisez smtpd_tls_wrappermode=yes<br>
-+ sur un autre port.<br>
-+ Coté client: MS Exchange même en version récente offre STARTTLS
-+ même si ce dernier n'est pas configuré (la liste <br>
-+ de diffusion[IETF-APPS-TLS]). Je ne pourrais pas tester ceci sans accès à un
-+ tel serveur, je ne peux donc pas prévoir<br>
-+ ce qui va se produire. <br>
-+ Coté client: Les connexions de TLS à un serveur de CommunigatePro échouent
-+ avec une erreur de poignée de main <br>
-+ avec des versions plus anciennes de CommunigatePro. La raison est une violation
-+ de protocole de CommunigatePro <br>
-+ en ce qui concerne la numérotation de version de protocole SSL. (cf RFC 2246
-+ section 7.4.7.1)<br>
-+ Ce problème a été fixé dans CommunigatePro 3.3b?? (je ne connais pas la numérotation
-+ exacte) autour du 9 juin 2000. .</p>
-+ </body>
-+ </html>
-diff -Pcr postfix-2.0.16/src/global/Makefile.in postfix-2.0.16-ti1.20/src/global/Makefile.in
-*** postfix-2.0.16/src/global/Makefile.in Sun Sep 14 02:03:59 2003
---- postfix-2.0.16-ti1.20/src/global/Makefile.in Mon Jan 5 16:58:06 2004
-***************
-*** 20,26 ****
- 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 virtual8_maps.c hold_message.c dict_proxy.c mail_dict.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 \
---- 20,27 ----
- 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 virtual8_maps.c hold_message.c dict_proxy.c mail_dict.c \
-! pfixtls.o 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,48 ****
- 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 virtual8_maps.o hold_message.o dict_proxy.o mail_dict.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 \
---- 43,50 ----
- 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 virtual8_maps.o hold_message.o dict_proxy.o mail_dict.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 \
-***************
-*** 61,67 ****
- 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 virtual8_maps.h hold_message.h dict_proxy.h \
-! mail_dict.h
- TESTSRC = rec2stream.c stream2rec.c recdump.c
- WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
- -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
---- 63,70 ----
- 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 virtual8_maps.h hold_message.h dict_proxy.h \
-! mail_dict.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 \
-***************
-*** 1262,1264 ****
---- 1265,1280 ----
- 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 -Pcr postfix-2.0.16/src/global/mail_params.c postfix-2.0.16-ti1.20/src/global/mail_params.c
-*** postfix-2.0.16/src/global/mail_params.c Fri Dec 13 23:04:31 2002
---- postfix-2.0.16-ti1.20/src/global/mail_params.c Mon Jan 5 16:58:06 2004
-***************
-*** 46,51 ****
---- 46,52 ----
- /* int var_message_limit;
- /* char *var_mail_release;
- /* char *var_mail_version;
-+ /* char *var_tlsipv6_version;
- /* int var_ipc_idle_limit;
- /* char *var_db_type;
- /* char *var_hash_queue_names;
-***************
-*** 200,205 ****
---- 201,209 ----
- int var_message_limit;
- char *var_mail_release;
- char *var_mail_version;
-+ #ifdef INET6
-+ char *var_tlsipv6_version;
-+ #endif
- int var_ipc_idle_limit;
- char *var_db_type;
- char *var_hash_queue_names;
-***************
-*** 225,230 ****
---- 229,259 ----
- 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;
-***************
-*** 445,450 ****
---- 474,482 ----
- VAR_ALIAS_DB_MAP, DEF_ALIAS_DB_MAP, &var_alias_db_map, 0, 0,
- VAR_MAIL_RELEASE, DEF_MAIL_RELEASE, &var_mail_release, 1, 0,
- VAR_MAIL_VERSION, DEF_MAIL_VERSION, &var_mail_version, 1, 0,
-+ #ifdef INET6
-+ VAR_TLSIPV6_VERSION, DEF_TLSIPV6_VERSION, &var_tlsipv6_version, 1, 0,
-+ #endif
- VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
- VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
- VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
-***************
-*** 467,472 ****
---- 499,524 ----
- 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,494 ****
---- 541,549 ----
- 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,504 ****
---- 554,561 ----
- 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 -Pcr postfix-2.0.16/src/global/mail_params.h postfix-2.0.16-ti1.20/src/global/mail_params.h
-*** postfix-2.0.16/src/global/mail_params.h Mon Mar 3 23:07:03 2003
---- postfix-2.0.16-ti1.20/src/global/mail_params.h Mon Jan 5 16:58:06 2004
-***************
-*** 487,492 ****
---- 487,520 ----
- #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.
- */
-***************
-*** 711,716 ****
---- 739,748 ----
- #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;
-***************
-*** 767,772 ****
---- 799,810 ----
- #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;
-***************
-*** 800,805 ****
---- 838,847 ----
- #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;
-***************
-*** 828,833 ****
---- 870,1019 ----
- #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.
- */
-***************
-*** 839,844 ****
---- 1025,1034 ----
- #define DEF_SMTPD_SASL_OPTS "noanonymous"
- extern char *var_smtpd_sasl_opts;
-
-+ #define VAR_SMTPD_SASL_TLS_OPTS "smtpd_sasl_tls_security_options"
-+ #define DEF_SMTPD_SASL_TLS_OPTS "$smtpd_sasl_security_options"
-+ extern char *var_smtpd_sasl_opts;
-+
- #define VAR_SMTPD_SASL_REALM "smtpd_sasl_local_domain"
- #define DEF_SMTPD_SASL_REALM ""
- extern char *var_smtpd_sasl_realm;
-***************
-*** 864,869 ****
---- 1054,1067 ----
- #define DEF_SMTP_SASL_OPTS "noplaintext, noanonymous"
- extern char *var_smtp_sasl_opts;
-
-+ #define VAR_SMTP_SASL_TLS_OPTS "smtp_sasl_tls_security_options"
-+ #define DEF_SMTP_SASL_TLS_OPTS "$var_smtp_sasl_opts"
-+ extern char *var_smtp_sasl_tls_opts;
-+
-+ #define VAR_SMTP_SASL_TLSV_OPTS "smtp_sasl_tls_verified_security_options"
-+ #define DEF_SMTP_SASL_TLSV_OPTS "$var_smtp_sasl_tls_opts"
-+ extern char *var_smtp_sasl_tls_verified_opts;
-+
- /*
- * LMTP server. The soft error limit determines how many errors an LMTP
- * client may make before we start to slow down; the hard error limit
-***************
-*** 986,991 ****
---- 1184,1199 ----
- #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.
-***************
-*** 1137,1142 ****
---- 1345,1354 ----
- #define DEF_RELAY_RCPT_CODE 550
- extern int var_relay_rcpt_code;
-
-+ #define VAR_RELAY_CCERTS "relay_clientcerts"
-+ #define DEF_RELAY_CCERTS ""
-+ extern char *var_relay_ccerts;
-+
- #define VAR_CLIENT_CHECKS "smtpd_client_restrictions"
- #define DEF_CLIENT_CHECKS ""
- extern char *var_client_checks;
-***************
-*** 1229,1234 ****
---- 1441,1448 ----
- #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 -Pcr postfix-2.0.16/src/global/mail_proto.h postfix-2.0.16-ti1.20/src/global/mail_proto.h
-*** postfix-2.0.16/src/global/mail_proto.h Sun Jan 12 18:45:43 2003
---- postfix-2.0.16-ti1.20/src/global/mail_proto.h Mon Jan 5 16:58:06 2004
-***************
-*** 41,46 ****
---- 41,47 ----
- #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 -Pcr postfix-2.0.16/src/global/mail_version.h postfix-2.0.16-ti1.20/src/global/mail_version.h
-*** postfix-2.0.16/src/global/mail_version.h Sat Sep 13 03:16:51 2003
---- postfix-2.0.16-ti1.20/src/global/mail_version.h Mon Jan 5 16:59:11 2004
-***************
-*** 26,31 ****
---- 26,37 ----
- #define DEF_MAIL_VERSION "2.0.16"
- extern char *var_mail_version;
-
-+ #ifdef INET6
-+ #define VAR_TLSIPV6_VERSION "tls_ipv6_version"
-+ #define DEF_TLSIPV6_VERSION "1.20"
-+ extern char *var_tlsipv6_version;
-+ #endif
-+
- /*
- * Release date.
- */
-diff -Pcr postfix-2.0.16/src/global/mynetworks.c postfix-2.0.16-ti1.20/src/global/mynetworks.c
-*** postfix-2.0.16/src/global/mynetworks.c Sun Feb 25 02:46:07 2001
---- postfix-2.0.16-ti1.20/src/global/mynetworks.c Mon Jan 5 16:58:06 2004
-***************
-*** 28,33 ****
---- 28,40 ----
- /* IBM T.J. Watson Research
- /* P.O. Box 704
- /* Yorktown Heights, NY 10598, USA
-+ /*
-+ /* Dean C. Strik
-+ /* Department ICT Services
-+ /* Eindhoven University of Technology
-+ /* P.O. Box 513
-+ /* 5600 MB Eindhoven, Netherlands
-+ /* E-mail: <dean@ipnet6.org>
- /*--*/
-
- /* System library. */
-***************
-*** 42,48 ****
- #define IN_CLASSD_NSHIFT 28
- #endif
-
-! #define BITS_PER_ADDR 32
-
- /* Utility library. */
-
---- 49,56 ----
- #define IN_CLASSD_NSHIFT 28
- #endif
-
-! #define BITS_PER_ADDR_V4 32
-! #define BITS_PER_ADDR_V6 128
-
- /* Utility library. */
-
-***************
-*** 50,55 ****
---- 58,69 ----
- #include <vstring.h>
- #include <inet_addr_list.h>
- #include <name_mask.h>
-+ #ifdef INET6
-+ #include <string.h>
-+ #include <sys/socket.h>
-+ #include <netinet/in.h>
-+ #include <netdb.h>
-+ #endif
-
- /* Global library. */
-
-***************
-*** 75,92 ****
- const char *mynetworks(void)
- {
- static VSTRING *result;
-
- if (result == 0) {
- char *myname = "mynetworks";
- INET_ADDR_LIST *my_addr_list;
- INET_ADDR_LIST *my_mask_list;
-! unsigned long addr;
-! unsigned long mask;
- struct in_addr net;
-! int shift;
- int junk;
- int i;
- int mask_style;
-
- mask_style = name_mask("mynetworks mask style", mask_styles,
- var_mynetworks_style);
---- 89,113 ----
- const char *mynetworks(void)
- {
- static VSTRING *result;
-+ int bits_per_addr;
-+ #ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ #endif
-
- if (result == 0) {
- char *myname = "mynetworks";
- INET_ADDR_LIST *my_addr_list;
- INET_ADDR_LIST *my_mask_list;
-! unsigned long addr = 0;
-! unsigned long mask = 0;
- struct in_addr net;
-! int shift = 0;
- 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,103 ****
---- 117,139 ----
- 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 && sa->sa_family != AF_INET6) {
-+ msg_warn("%s: unknown family in address list", myname);
-+ continue;
-+ }
-+ if (sa->sa_family == AF_INET) {
-+ bits_per_addr = BITS_PER_ADDR_V4;
-+ 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
-+ bits_per_addr = BITS_PER_ADDR_V6;
-+ #else
- addr = ntohl(my_addr_list->addrs[i].s_addr);
- mask = ntohl(my_mask_list->addrs[i].s_addr);
-+ #endif
-
- switch (mask_style) {
-
-***************
-*** 106,111 ****
---- 142,150 ----
- * ISP who gave you a small portion of their network.
- */
- case MASK_STYLE_CLASS:
-+ #ifdef INET6
-+ if (sa->sa_family == AF_INET) {
-+ #endif
- if (IN_CLASSA(addr)) {
- mask = IN_CLASSA_NET;
- shift = IN_CLASSA_NSHIFT;
-***************
-*** 119,142 ****
- mask = IN_CLASSD_NET;
- shift = IN_CLASSD_NSHIFT;
- } else {
- msg_fatal("%s: bad address class: %s",
- myname, inet_ntoa(my_addr_list->addrs[i]));
- }
- break;
-
- /*
- * Subnet mask. This is safe, but breaks backwards
- * compatibility when used as default setting.
- */
- case MASK_STYLE_SUBNET:
-! for (junk = mask, shift = BITS_PER_ADDR; junk != 0; shift--, (junk <<= 1))
-! /* void */ ;
- break;
-
- /*
- * Host only. Do not relay authorize other hosts.
- */
- case MASK_STYLE_HOST:
- mask = ~0;
- shift = 0;
- break;
---- 158,230 ----
- 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;
-+ #ifdef INET6
-+ } /* if AF_INET */
-+ /*
-+ * There are no classes for IPv6, we default to subnets instead.
-+ */
-+ /* FALLTHROUGH */
-+ #endif
-
- /*
- * Subnet mask. This is safe, but breaks backwards
- * compatibility when used as default setting.
- */
- case MASK_STYLE_SUBNET:
-! #ifdef INET6
-! if (sa->sa_family == AF_INET6) {
-! unsigned char *ac, *end;
-! ac = (unsigned char *)&(((struct sockaddr_in6 *)&my_mask_list->addrs[i])->sin6_addr);
-! end = ac + bits_per_addr / 8;
-! shift = bits_per_addr;
-! while (ac < end) {
-! switch (*(ac++)) {
-! case 0xff: shift -= 8; break;
-! case 0xfe: shift -= 7; break;
-! case 0xfc: shift -= 6; break;
-! case 0xf8: shift -= 5; break;
-! case 0xf0: shift -= 4; break;
-! case 0xe0: shift -= 3; break;
-! case 0xc0: shift -= 2; break;
-! case 0x80: shift -= 1; break;
-! case 0x00: break;
-! default: msg_fatal("%s: inconsistent prefixlen",
-! myname);
-! }
-! }
-! break;
-! }
-! #endif
-! /* AF_INET */
-! junk = mask;
-! shift = bits_per_addr;
-! while (junk != 0) {
-! shift--;
-! junk <<= 1;
-! }
- break;
-
- /*
- * Host only. Do not relay authorize other hosts.
- */
- case MASK_STYLE_HOST:
-+ #ifdef INET6
-+ if (sa->sa_family == AF_INET6) {
-+ shift = 0;
-+ break;
-+ }
-+ #endif
- mask = ~0;
- shift = 0;
- break;
-***************
-*** 145,153 ****
- msg_panic("unknown mynetworks mask style: %s",
- var_mynetworks_style);
- }
- net.s_addr = htonl(addr & mask);
- vstring_sprintf_append(result, "%s/%d ",
-! inet_ntoa(net), BITS_PER_ADDR - shift);
- }
- if (msg_verbose)
- msg_info("%s: %s", myname, vstring_str(result));
---- 233,252 ----
- msg_panic("unknown mynetworks mask style: %s",
- var_mynetworks_style);
- }
-+ #ifdef INET6
-+ if (sa->sa_family == AF_INET6) {
-+ if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
-+ NI_NUMERICHOST))
-+ msg_fatal("%s: bad address to getnameinfo()", myname);
-+ vstring_sprintf_append(result, "[%s]/%d ",
-+ hbuf, bits_per_addr - shift);
-+ continue;
-+ }
-+ #endif
-+ /* AF_INET */
- net.s_addr = htonl(addr & mask);
- vstring_sprintf_append(result, "%s/%d ",
-! inet_ntoa(net), bits_per_addr - shift);
- }
- if (msg_verbose)
- msg_info("%s: %s", myname, vstring_str(result));
-diff -Pcr postfix-2.0.16/src/global/own_inet_addr.c postfix-2.0.16-ti1.20/src/global/own_inet_addr.c
-*** postfix-2.0.16/src/global/own_inet_addr.c Fri Oct 25 01:19:19 2002
---- postfix-2.0.16-ti1.20/src/global/own_inet_addr.c Mon Jan 5 16:58:06 2004
-***************
-*** 50,55 ****
---- 50,59 ----
- #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>
-***************
-*** 113,122 ****
- */
- else {
- bufp = hosts = mystrdup(var_inet_interfaces);
-! 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);
-
- /*
---- 117,127 ----
- */
- else {
- bufp = hosts = mystrdup(var_inet_interfaces);
-! 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);
-
- /*
-***************
-*** 133,147 ****
- 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)
- msg_fatal("parameter %s: no local interface found for %s",
- VAR_INET_INTERFACES,
- inet_ntoa(addr_list->addrs[nvirtual]));
- if (addr_list->addrs[nvirtual].s_addr
- == local_addrs.addrs[nlocal].s_addr) {
- inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
- break;
- }
- }
- }
- inet_addr_list_free(&local_addrs);
---- 138,177 ----
- 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) {
-! #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);
-***************
-*** 151,156 ****
---- 181,229 ----
-
- /* own_inet_addr - is this my own internet address */
-
-+ #ifdef INET6
-+
-+ #ifdef __KAME__
-+ #define SA6_ARE_ADDR_EQUAL(a, b) ( \
-+ ((a)->sin6_scope_id == 0 || (b)->sin6_scope_id == 0 || \
-+ (a)->sin6_scope_id == (b)->sin6_scope_id) && \
-+ (memcmp(&(a)->sin6_addr, &(b)->sin6_addr, \
-+ sizeof(struct in6_addr)) == 0))
-+ #else
-+ #define SA6_ARE_ADDR_EQUAL(a, b) \
-+ (memcmp(&(a)->sin6_addr, &(b)->sin6_addr, \
-+ sizeof(struct in6_addr)) == 0)
-+ #endif
-+
-+ int own_inet_addr(struct sockaddr *addr)
-+ {
-+ int i;
-+
-+ if (addr_list.used == 0)
-+ own_inet_addr_init(&addr_list, &mask_list);
-+
-+ for (i = 0; i < addr_list.used; i++) {
-+ if (((struct sockaddr *)&addr_list.addrs[i])->sa_family !=
-+ addr->sa_family)
-+ continue;
-+ switch (addr->sa_family) {
-+ case AF_INET:
-+ if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
-+ ((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr.s_addr)
-+ return (1);
-+ break;
-+ case AF_INET6:
-+ if (SA6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
-+ (struct sockaddr_in6 *)&addr_list.addrs[i]))
-+ return (1);
-+ break;
-+ default:
-+ continue;
-+ }
-+ return (0);
-+ }
-+ }
-+ #else
- int own_inet_addr(struct in_addr * addr)
- {
- int i;
-***************
-*** 163,168 ****
---- 236,242 ----
- return (1);
- return (0);
- }
-+ #endif
-
- /* own_inet_addr_list - return list of addresses */
-
-***************
-*** 224,231 ****
---- 298,312 ----
- proxy_inet_addr_init(&proxy_list);
-
- for (i = 0; i < proxy_list.used; i++)
-+ #ifdef INET6
-+ if (proxy_list.addrs[i].ss_family == AF_INET && addr->s_addr ==
-+ ((struct sockaddr_in *)&(proxy_list.addrs[i]))->
-+ sin_addr.s_addr)
-+ return (1);
-+ #else
- if (addr->s_addr == proxy_list.addrs[i].s_addr)
- return (1);
-+ #endif
- return (0);
- }
-
-diff -Pcr postfix-2.0.16/src/global/own_inet_addr.h postfix-2.0.16-ti1.20/src/global/own_inet_addr.h
-*** postfix-2.0.16/src/global/own_inet_addr.h Fri Oct 25 01:07:05 2002
---- postfix-2.0.16-ti1.20/src/global/own_inet_addr.h Mon Jan 5 16:58:06 2004
-***************
-*** 15,25 ****
---- 15,32 ----
- * 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);
- extern int proxy_inet_addr(struct in_addr *);
-diff -Pcr postfix-2.0.16/src/global/peer_name.c postfix-2.0.16-ti1.20/src/global/peer_name.c
-*** postfix-2.0.16/src/global/peer_name.c Sun Jan 28 16:23:02 2001
---- postfix-2.0.16-ti1.20/src/global/peer_name.c Mon Jan 5 16:58:06 2004
-***************
-*** 69,80 ****
- PEER_NAME *peer_name(int sock)
- {
- static PEER_NAME peer;
-! struct sockaddr_in sin;
-! SOCKADDR_SIZE len = sizeof(sin);
- struct hostent *hp;
-
-! if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
-! switch (sin.sin_family) {
- case AF_INET:
- peer.type = PEER_TYPE_INET;
- hp = gethostbyaddr((char *) &(sin.sin_addr),
---- 69,100 ----
- PEER_NAME *peer_name(int sock)
- {
- static PEER_NAME peer;
-! 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 *)&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,88 ****
---- 103,126 ----
- 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 -Pcr postfix-2.0.16/src/global/peer_name.h postfix-2.0.16-ti1.20/src/global/peer_name.h
-*** postfix-2.0.16/src/global/peer_name.h Fri Dec 11 19:55:32 1998
---- postfix-2.0.16-ti1.20/src/global/peer_name.h Mon Jan 5 16:58:06 2004
-***************
-*** 22,27 ****
---- 22,30 ----
- #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 -Pcr postfix-2.0.16/src/global/pfixtls.c postfix-2.0.16-ti1.20/src/global/pfixtls.c
-*** postfix-2.0.16/src/global/pfixtls.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/global/pfixtls.c Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,2804 ----
-+ /*++
-+ /* 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, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
-+ };
-+
-+ #ifdef USE_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/x509v3.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;
-+ int hostname_matched;
-+ } 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);
-+ }
-+
-+
-+ /*
-+ * match_hostname: match name provided in "buf" against the expected
-+ * hostname. Comparison is case-insensitive, wildcard certificates are
-+ * supported.
-+ * "buf" may be come from some OpenSSL data structures, so we copy before
-+ * modifying.
-+ */
-+ static int match_hostname(const char *buf, TLScontext_t *TLScontext)
-+ {
-+ char *hostname_lowercase;
-+ char *peername_left;
-+ int hostname_matched = 0;
-+ int buf_len;
-+
-+ buf_len = strlen(buf);
-+ if (!(hostname_lowercase = (char *)mymalloc(buf_len + 1)))
-+ return 0;
-+ memcpy(hostname_lowercase, buf, buf_len + 1);
-+
-+ hostname_lowercase = lowercase(hostname_lowercase);
-+ if (!strcmp(TLScontext->peername_save, hostname_lowercase)) {
-+ hostname_matched = 1;
-+ } else {
-+ if ((buf_len > 2) &&
-+ (hostname_lowercase[0] == '*') && (hostname_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, hostname_lowercase + 2))
-+ hostname_matched = 1;
-+ }
-+ }
-+ }
-+ myfree(hostname_lowercase);
-+ return hostname_matched;
-+ }
-+
-+ /*
-+ * 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 *peername_left;
-+ X509 *err_cert;
-+ int err;
-+ int depth;
-+ int verify_depth;
-+ 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) {
-+ int i, r;
-+ int hostname_matched;
-+ int dNSName_found;
-+ STACK_OF(GENERAL_NAME) *gens;
-+
-+ /*
-+ * 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.
-+ * Standards are not always clear with respect to the handling of
-+ * dNSNames. RFC3207 does not specify the handling. We therefore follow
-+ * the strict rules in RFC2818 (HTTP over TLS), Section 3.1:
-+ * The Subject Alternative Name/dNSName has precedence over CommonName
-+ * (CN). If dNSName entries are provided, CN is not checked anymore.
-+ */
-+ hostname_matched = dNSName_found = 0;
-+
-+ gens = X509_get_ext_d2i(err_cert, NID_subject_alt_name, 0, 0);
-+ if (gens) {
-+ for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i) {
-+ const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
-+ if (gn->type == GEN_DNS) {
-+ dNSName_found++;
-+ if ((hostname_matched =
-+ match_hostname((char *)gn->d.ia5->data, TLScontext)))
-+ break;
-+ }
-+ }
-+ sk_GENERAL_NAME_free(gens);
-+ }
-+ if (dNSName_found) {
-+ if (!hostname_matched)
-+ msg_info("Peer verification: %d dNSNames in certificate found, but no one does match %s", dNSName_found, TLScontext->peername_save);
-+ } else {
-+ 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();
-+ }
-+ else {
-+ hostname_matched = match_hostname(buf, TLScontext);
-+ if (!hostname_matched)
-+ msg_info("Peer verification: CommonName in certificate does not match: %s != %s", buf, TLScontext->peername_save);
-+ }
-+ }
-+
-+ if (!hostname_matched) {
-+ if (TLScontext->enforce_verify_errors && TLScontext->enforce_CN) {
-+ err = X509_V_ERR_CERT_REJECTED;
-+ X509_STORE_CTX_set_error(ctx, err);
-+ msg_info("Verify failure: Hostname mismatch");
-+ ok = 0;
-+ }
-+ }
-+ else
-+ TLScontext->hostname_matched = 1;
-+ }
-+
-+ 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;
-+ }
-+ TLScontext->hostname_matched = 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;
-+
-+ tls_info->hostname_matched = TLScontext->hostname_matched;
-+ TLScontext->peer_CN[0] = '\0';
-+ if (!X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
-+ NID_commonName, TLScontext->peer_CN, 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 /* USE_SSL */
-diff -Pcr postfix-2.0.16/src/global/pfixtls.h postfix-2.0.16-ti1.20/src/global/pfixtls.h
-*** postfix-2.0.16/src/global/pfixtls.h Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/global/pfixtls.h Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,81 ----
-+ /*++
-+ /* NAME
-+ /* pfixtls 3h
-+ /* SUMMARY
-+ /* TLS routines
-+ /* SYNOPSIS
-+ /* include "pfixtls.h"
-+ /* DESCRIPTION
-+ /* .nf
-+ /*--*/
-+
-+ #ifndef PFIXTLS_H_INCLUDED
-+ #define PFIXTLS_H_INCLUDED
-+
-+ #if defined(HAS_SSL) && !defined(USE_SSL)
-+ #define USE_SSL
-+ #endif
-+
-+ typedef struct {
-+ int peer_verified;
-+ int hostname_matched;
-+ char *peer_subject;
-+ char *peer_issuer;
-+ char *peer_fingerprint;
-+ char *peer_CN;
-+ char *issuer_CN;
-+ const char *protocol;
-+ const char *cipher_name;
-+ int cipher_usebits;
-+ int cipher_algbits;
-+ } tls_info_t;
-+
-+ extern const tls_info_t tls_info_zero;
-+
-+ #ifdef USE_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 -Pcr postfix-2.0.16/src/global/resolve_local.c postfix-2.0.16-ti1.20/src/global/resolve_local.c
-*** postfix-2.0.16/src/global/resolve_local.c Fri Oct 25 01:21:20 2002
---- postfix-2.0.16-ti1.20/src/global/resolve_local.c Mon Jan 5 16:58:06 2004
-***************
-*** 43,48 ****
---- 43,49 ----
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string.h>
-+ #include <netdb.h>
-
- #ifndef INADDR_NONE
- #define INADDR_NONE 0xffffffff
-***************
-*** 80,86 ****
---- 81,92 ----
- {
- 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); }
-***************
-*** 118,126 ****
---- 124,151 ----
- 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;
-+ hints.ai_flags = AI_NUMERICHOST;
-+ error = getaddrinfo(dest, NULL, &hints, &res0);
-+ if (!error) {
-+ for (res = res0; res; res = res->ai_next) {
-+ if (own_inet_addr(res->ai_addr) ||
-+ (res->ai_family == AF_INET &&
-+ proxy_inet_addr((struct in_addr *)&res->ai_addr))) {
-+ freeaddrinfo(res0);
-+ RETURN(1);
-+ }
-+ }
-+ freeaddrinfo(res0);
-+ }
-+ #else
- if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
- && (own_inet_addr(&ipaddr) || proxy_inet_addr(&ipaddr)))
- RETURN(1);
-+ #endif
- }
-
- /*
-diff -Pcr postfix-2.0.16/src/global/wildcard_inet_addr.c postfix-2.0.16-ti1.20/src/global/wildcard_inet_addr.c
-*** postfix-2.0.16/src/global/wildcard_inet_addr.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/global/wildcard_inet_addr.c Mon Jan 5 16:58:06 2004
-***************
-*** 0 ****
---- 1,78 ----
-+ /* 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;
-+ const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
-+
-+ 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 | AI_NUMERICHOST;
-+ 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 -Pcr postfix-2.0.16/src/global/wildcard_inet_addr.h postfix-2.0.16-ti1.20/src/global/wildcard_inet_addr.h
-*** postfix-2.0.16/src/global/wildcard_inet_addr.h Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/global/wildcard_inet_addr.h Mon Jan 5 16:58:06 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/lmtp/lmtp.c postfix-2.0.16-ti1.20/src/lmtp/lmtp.c
-*** postfix-2.0.16/src/lmtp/lmtp.c Thu Sep 11 02:13:30 2003
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp.c Mon Jan 5 16:58:07 2004
-***************
-*** 190,195 ****
---- 190,201 ----
- /* .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,281 ****
---- 282,289 ----
- 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.
-***************
-*** 526,531 ****
---- 534,543 ----
- 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 -Pcr postfix-2.0.16/src/lmtp/lmtp_addr.c postfix-2.0.16-ti1.20/src/lmtp/lmtp_addr.c
-*** postfix-2.0.16/src/lmtp/lmtp_addr.c Mon Nov 20 19:05:33 2000
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp_addr.c Mon Jan 5 16:58:07 2004
-***************
-*** 166,172 ****
---- 166,176 ----
- /*
- * Append the addresses for this host to the address list.
- */
-+ #ifdef INET6
-+ switch (dns_lookup_types(host, RES_DEFNAMES, &addr, (VSTRING *) 0, why, T_AAAA, T_A, NULL)) {
-+ #else
- switch (dns_lookup(host, T_A, RES_DEFNAMES, &addr, (VSTRING *) 0, why)) {
-+ #endif
- case DNS_OK:
- for (rr = addr; rr; rr = rr->next)
- rr->pref = pref;
-diff -Pcr postfix-2.0.16/src/lmtp/lmtp_connect.c postfix-2.0.16-ti1.20/src/lmtp/lmtp_connect.c
-*** postfix-2.0.16/src/lmtp/lmtp_connect.c Sat Sep 13 02:35:38 2003
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp_connect.c Mon Jan 5 20:45:20 2004
-***************
-*** 94,109 ****
---- 94,116 ----
- #include <stringops.h>
- #include <host_port.h>
- #include <sane_connect.h>
-+ #include <inet_addr_list.h>
-
- /* Global library. */
-
- #include <mail_params.h>
- #include <mail_proto.h>
-+ #include <own_inet_addr.h>
-
- /* DNS library. */
-
- #include <dns.h>
-
-+ #ifdef INET6
-+ #define GAI_STRERROR(error) \
-+ ((error == EAI_SYSTEM) ? strerror(errno) : gai_strerror(error))
-+ #endif
-+
- /* Application-specific. */
-
- #include "lmtp.h"
-***************
-*** 162,180 ****
- addr, addr, destination, why));
- }
-
- /* lmtp_connect_addr - connect to explicit address */
-
- static LMTP_SESSION *lmtp_connect_addr(DNS_RR *addr, unsigned port,
- const char *destination, VSTRING *why)
- {
- char *myname = "lmtp_connect_addr";
-! struct sockaddr_in sin;
-! int sock;
-
- /*
- * Sanity checks.
- */
-! if (addr->data_len > sizeof(sin.sin_addr)) {
- msg_warn("%s: skip address with length %d", myname, addr->data_len);
- lmtp_errno = LMTP_RETRY;
- return (0);
---- 169,389 ----
- addr, addr, destination, why));
- }
-
-+ /* lmtp_force_bind: bind() address */
-+
-+ static void lmtp_force_bind(const char *bind_addr,
-+ const char *bind_var,
-+ int sock,
-+ int af)
-+ {
-+ /*
-+ * If the bind() call fails, this is considered a non-fatal error.
-+ * All address conversion errors are fatal.
-+ */
-+ char *myname = "lmtp_force_bind";
-+ #ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ int aierr;
-+ struct addrinfo hints, *res;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-+ snprintf(hbuf, sizeof(hbuf), "%s", bind_addr);
-+ aierr = getaddrinfo(hbuf, NULL, &hints, &res);
-+ if (aierr == EAI_NONAME)
-+ msg_fatal("%s: bad %s parameter: \"%s\"",
-+ myname, bind_var, bind_addr);
-+ if (aierr != 0) {
-+ if (msg_verbose)
-+ msg_warn("%s: getaddrinfo(%s): %s",
-+ myname, hbuf, GAI_STRERROR(aierr));
-+ return;
-+ }
-+ aierr = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
-+ if (aierr != 0) {
-+ msg_warn("%s: getnameinfo(): %s",
-+ myname, GAI_STRERROR(aierr));
-+ freeaddrinfo(res);
-+ return;
-+ }
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbuf);
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbuf);
-+ freeaddrinfo(res);
-+ #else /* 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, bind_var, bind_addr);
-+ return;
-+ }
-+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
-+ msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+ #endif /* INET6 */
-+ }
-+
-+ /* lmtp_virtual_bind - bind() when acting as virtual host */
-+
-+ static void lmtp_virtual_bind(int sock, int af)
-+ {
-+ char *myname = "lmtp_virtual_bind";
-+ INET_ADDR_LIST *addr_list;
-+ int count;
-+
-+ #ifdef INET6
-+ int i;
-+ char hbuf[NI_MAXHOST];
-+ int aierr;
-+ struct sockaddr *sa;
-+ struct addrinfo hints, *loopback = NULL, *res = NULL;
-+
-+ /*
-+ * Check whether we are acting as a virtual host
-+ */
-+ count = 0;
-+ addr_list = own_inet_addr_list();
-+ for (i = 0; count < 2 && i < addr_list->used; i++)
-+ if (((struct sockaddr *)&addr_list->addrs[i])->sa_family == af)
-+ count++;
-+ if (count != 1)
-+ return;
-+
-+ /*
-+ * Bind the source address.
-+ */
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ aierr = getaddrinfo(NULL, "0", &hints, &loopback);
-+ if (aierr != 0) {
-+ loopback = NULL;
-+ msg_warn("%s: getaddrinfo(\"0\"): %s",
-+ myname, GAI_STRERROR(aierr));
-+ }
-+
-+ sa = (struct sockaddr *)&addr_list->addrs[i - 1];
-+ aierr = getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
-+ if (aierr != 0)
-+ msg_fatal("%s: getnameinfo() (AF=%d): %s",
-+ myname, af, GAI_STRERROR(aierr));
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
-+ aierr = getaddrinfo(hbuf, NULL, &hints, &res);
-+ if (aierr != 0)
-+ msg_fatal("%s: getaddrinfo(\"%s\"): %s",
-+ myname, hbuf, GAI_STRERROR(aierr));
-+
-+ if (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, hbuf);
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbuf);
-+ } else if (msg_verbose) {
-+ msg_info("%s: not calling bind(): unusable source "
-+ "address from \"%s\"", myname, hbuf);
-+ }
-+ if (res)
-+ freeaddrinfo(res);
-+ if (loopback)
-+ freeaddrinfo(loopback);
-+
-+ #else /* INET6 */
-+
-+ struct sockaddr_in sin;
-+ unsigned long inaddr; /*XXX BAD!*/
-+
-+ /*
-+ * Check whether we are acting as a virtual host
-+ */
-+ addr_list = own_inet_addr_list();
-+ count = addr_list->used;
-+ if (count != 1)
-+ return;
-+
-+ /*
-+ * Bind the source address.
-+ */
-+ 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)
-+ || !(((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));
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+ }
-+ #endif /* INET6 */
-+ }
-+
- /* lmtp_connect_addr - connect to explicit address */
-
- static LMTP_SESSION *lmtp_connect_addr(DNS_RR *addr, unsigned port,
- const char *destination, VSTRING *why)
- {
- char *myname = "lmtp_connect_addr";
-! #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;
-! char *bind_var;
-! #ifdef INET6
-! char *addr6_ptr = NULL;
-! #endif
-!
-! sa = (struct sockaddr *)&ss;
-! sin = (struct sockaddr_in *)&ss;
-! #ifdef INET6
-! sin6 = (struct sockaddr_in6 *)&ss;
-! #endif
-
- /*
- * Sanity checks.
- */
-! #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);
-***************
-*** 183,207 ****
- /*
- * 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);
-
- /*
- * Connect to the LMTP server.
- */
-! sin.sin_port = port;
-! memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-
- if (msg_verbose)
- msg_info("%s: trying: %s[%s] port %d...",
-! myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
-
-! return (lmtp_connect_sock(sock, (struct sockaddr *) & sin, sizeof(sin),
-! addr->name, inet_ntoa(sin.sin_addr),
-! destination, why));
- }
-
- /* lmtp_connect_sock - connect a socket over some transport */
---- 392,484 ----
- /*
- * Initialize.
- */
-! switch (addr->type) {
-! #ifdef INET6
-! case T_AAAA:
-! bind_addr = "";
-! bind_var = VAR_LMTP_BIND_ADDR6;
-! if (*var_lmtp_bind_addr6) {
-! addr6_ptr = mystrdup(var_lmtp_bind_addr6);
-! if (*addr6_ptr == '[' && addr6_ptr[strlen(addr6_ptr) - 1] == ']') {
-! addr6_ptr[strlen(addr6_ptr) - 1] = 0;
-! bind_addr = addr6_ptr + 1;
-! } else {
-! msg_warn("%s: skip incorrectly bracketed IPv6 address in %s",
-! myname, 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;
-! bind_var = VAR_SMTP_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(sa->sa_family, SOCK_STREAM, 0)) < 0)
- msg_fatal("%s: socket: %m", myname);
-
- /*
-+ * Allow the sysadmin to specify the source address
-+ */
-+
-+ if (bind_addr && *bind_addr) {
-+ lmtp_force_bind(bind_addr, bind_var, sock, sa->sa_family);
-+ #ifdef INET6
-+ if (addr6_ptr)
-+ myfree(addr6_ptr);
-+ #endif
-+ } else {
-+ /*
-+ * When running as a virtual host, bind to the virtual interface so that
-+ * the mail appears to come from the "right" machine address.
-+ */
-+ lmtp_virtual_bind(sock, sa->sa_family);
-+ }
-+
-+ /*
- * Connect to the LMTP server.
- */
-! 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, hbuf, ntohs(port));
-
-! return (lmtp_connect_sock(sock, (struct sockaddr *)sa, salen,
-! addr->name, hbuf, destination, why));
- }
-
- /* lmtp_connect_sock - connect a socket over some transport */
-diff -Pcr postfix-2.0.16/src/lmtp/lmtp_sasl.h postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl.h
-*** postfix-2.0.16/src/lmtp/lmtp_sasl.h Fri Jan 19 22:03:50 2001
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl.h Mon Jan 5 16:58:07 2004
-***************
-*** 14,20 ****
- extern void lmtp_sasl_initialize(void);
- extern void lmtp_sasl_connect(LMTP_STATE *);
- extern int lmtp_sasl_passwd_lookup(LMTP_STATE *);
-! extern void lmtp_sasl_start(LMTP_STATE *);
- extern int lmtp_sasl_authenticate(LMTP_STATE *, VSTRING *);
- extern void lmtp_sasl_cleanup(LMTP_STATE *);
-
---- 14,20 ----
- extern void lmtp_sasl_initialize(void);
- extern void lmtp_sasl_connect(LMTP_STATE *);
- extern int lmtp_sasl_passwd_lookup(LMTP_STATE *);
-! extern void lmtp_sasl_start(LMTP_STATE *, const char *, const char *);
- extern int lmtp_sasl_authenticate(LMTP_STATE *, VSTRING *);
- extern void lmtp_sasl_cleanup(LMTP_STATE *);
-
-diff -Pcr postfix-2.0.16/src/lmtp/lmtp_sasl_glue.c postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl_glue.c
-*** postfix-2.0.16/src/lmtp/lmtp_sasl_glue.c Wed Sep 10 02:52:53 2003
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl_glue.c Mon Jan 5 16:58:07 2004
-***************
-*** 11,17 ****
- /* void lmtp_sasl_connect(state)
- /* LMTP_STATE *state;
- /*
-! /* void lmtp_sasl_start(state)
- /* LMTP_STATE *state;
- /*
- /* int lmtp_sasl_passwd_lookup(state)
---- 11,17 ----
- /* void lmtp_sasl_connect(state)
- /* LMTP_STATE *state;
- /*
-! /* void lmtp_sasl_start(state, sasl_opts_name, sasl_opts_var)
- /* LMTP_STATE *state;
- /*
- /* int lmtp_sasl_passwd_lookup(state)
-***************
-*** 33,39 ****
- /*
- /* lmtp_sasl_start() performs per-session initialization. This
- /* routine must be called once per session before doing any SASL
-! /* authentication.
- /*
- /* lmtp_sasl_passwd_lookup() looks up the username/password
- /* for the current LMTP server. The result is zero in case
---- 33,41 ----
- /*
- /* lmtp_sasl_start() performs per-session initialization. This
- /* routine must be called once per session before doing any SASL
-! /* authentication. The sasl_opts_name and sasl_opts_var parameters are
-! /* the postfix configuration parameters setting the security
-! /* policy of the SASL authentication.
- /*
- /* lmtp_sasl_passwd_lookup() looks up the username/password
- /* for the current LMTP server. The result is zero in case
-***************
-*** 122,129 ****
- 0,
- };
-
-- static int lmtp_sasl_sec_opts;
--
- /*
- * Silly little macros.
- */
---- 124,129 ----
-***************
-*** 319,329 ****
- if (sasl_client_init(callbacks) != SASL_OK)
- msg_fatal("SASL library initialization");
-
-- /*
-- * Configuration parameters.
-- */
-- lmtp_sasl_sec_opts = name_mask(VAR_LMTP_SASL_OPTS, lmtp_sasl_sec_mask,
-- var_lmtp_sasl_opts);
- }
-
- /* lmtp_sasl_connect - per-session client initialization */
---- 319,324 ----
-***************
-*** 341,347 ****
-
- /* lmtp_sasl_start - per-session SASL initialization */
-
-! void lmtp_sasl_start(LMTP_STATE *state)
- {
- static sasl_callback_t callbacks[] = {
- {SASL_CB_USER, &lmtp_sasl_get_user, 0},
---- 336,343 ----
-
- /* lmtp_sasl_start - per-session SASL initialization */
-
-! void lmtp_sasl_start(LMTP_STATE *state, const char *sasl_opts_name,
-! const char *sasl_opts_var)
- {
- static sasl_callback_t callbacks[] = {
- {SASL_CB_USER, &lmtp_sasl_get_user, 0},
-***************
-*** 383,389 ****
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = lmtp_sasl_sec_opts;
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
---- 379,386 ----
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = name_mask(sasl_opts_name, lmtp_sasl_sec_mask,
-! sasl_opts_var);
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
-diff -Pcr postfix-2.0.16/src/lmtp/lmtp_sasl_proto.c postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl_proto.c
-*** postfix-2.0.16/src/lmtp/lmtp_sasl_proto.c Tue May 22 20:36:42 2001
---- postfix-2.0.16-ti1.20/src/lmtp/lmtp_sasl_proto.c Mon Jan 5 16:58:07 2004
-***************
-*** 114,120 ****
- * required, and assume that an authentication error is recoverable.
- */
- if (lmtp_sasl_passwd_lookup(state) != 0) {
-! lmtp_sasl_start(state);
- if (lmtp_sasl_authenticate(state, why) <= 0)
- ret = lmtp_site_fail(state, 450, "Authentication failed: %s",
- vstring_str(why));
---- 114,120 ----
- * required, and assume that an authentication error is recoverable.
- */
- if (lmtp_sasl_passwd_lookup(state) != 0) {
-! lmtp_sasl_start(state, VAR_LMTP_SASL_OPTS, var_lmtp_sasl_opts);
- if (lmtp_sasl_authenticate(state, why) <= 0)
- ret = lmtp_site_fail(state, 450, "Authentication failed: %s",
- vstring_str(why));
-diff -Pcr postfix-2.0.16/src/master/master.h postfix-2.0.16-ti1.20/src/master/master.h
-*** postfix-2.0.16/src/master/master.h Sat Jan 26 02:58:10 2002
---- postfix-2.0.16-ti1.20/src/master/master.h Mon Jan 5 16:58:07 2004
-***************
-*** 95,100 ****
---- 95,101 ----
- extern void end_master_ent(void);
- extern void print_master_ent(MASTER_SERV *);
- extern MASTER_SERV *get_master_ent(void);
-+ extern void fix_master_ent(MASTER_SERV *);
- extern void free_master_ent(MASTER_SERV *);
-
- /*
-diff -Pcr postfix-2.0.16/src/master/master_conf.c postfix-2.0.16-ti1.20/src/master/master_conf.c
-*** postfix-2.0.16/src/master/master_conf.c Tue Mar 27 23:52:50 2001
---- postfix-2.0.16-ti1.20/src/master/master_conf.c Mon Jan 5 16:58:07 2004
-***************
-*** 114,119 ****
---- 114,120 ----
- entry->next = master_head;
- master_head = entry;
- master_start_service(entry);
-+ fix_master_ent(entry);
- }
-
- /*
-***************
-*** 134,139 ****
---- 135,141 ----
- SWAP(char *, serv->path, entry->path);
- SWAP(ARGV *, serv->args, entry->args);
- master_restart_service(serv);
-+ fix_master_ent(serv);
- free_master_ent(entry);
- }
- }
-diff -Pcr postfix-2.0.16/src/master/master_ent.c postfix-2.0.16-ti1.20/src/master/master_ent.c
-*** postfix-2.0.16/src/master/master_ent.c Wed Jun 18 21:19:46 2003
---- postfix-2.0.16-ti1.20/src/master/master_ent.c Mon Jan 5 16:58:07 2004
-***************
-*** 86,91 ****
---- 86,94 ----
- #include <inet_addr_list.h>
- #include <inet_util.h>
- #include <inet_addr_host.h>
-+ #ifdef INET6
-+ #include <wildcard_inet_addr.h>
-+ #endif
-
- /* Global library. */
-
-***************
-*** 307,314 ****
---- 310,322 ----
- inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
- serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
- } else if (strcasecmp(saved_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 */
- inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
-***************
-*** 437,446 ****
- argv_add(serv->args, "-u", (char *) 0);
- if (chroot)
- argv_add(serv->args, "-c", (char *) 0);
-- if (serv->listen_fd_count > 1)
-- argv_add(serv->args, "-s",
-- vstring_str(vstring_sprintf(junk, "%d", serv->listen_fd_count)),
-- (char *) 0);
- while ((cp = mystrtok(&bufp, master_blanks)) != 0)
- argv_add(serv->args, cp, (char *) 0);
- argv_terminate(serv->args);
---- 445,450 ----
-***************
-*** 451,456 ****
---- 455,474 ----
- vstring_free(buf);
- vstring_free(junk);
- return (serv);
-+ }
-+
-+ /* fix_master_ent - fix configuration parameters after run-time setup */
-+
-+ void fix_master_ent(MASTER_SERV *serv)
-+ {
-+ VSTRING *junk = vstring_alloc(100);
-+
-+ if (serv->listen_fd_count > 1)
-+ argv_add(serv->args, "-s",
-+ vstring_str(vstring_sprintf(junk, "%d", serv->listen_fd_count)),
-+ (char *) 0);
-+
-+ vstring_free(junk);
- }
-
- /* print_master_ent - show service entry contents */
-diff -Pcr postfix-2.0.16/src/master/master_listen.c postfix-2.0.16-ti1.20/src/master/master_listen.c
-*** postfix-2.0.16/src/master/master_listen.c Tue May 1 00:47:57 2001
---- postfix-2.0.16-ti1.20/src/master/master_listen.c Mon Jan 5 16:58:07 2004
-***************
-*** 64,76 ****
-
- #include "master.h"
-
- /* master_listen_init - enable connection requests */
-
- void master_listen_init(MASTER_SERV *serv)
- {
- char *myname = "master_listen_init";
- char *end_point;
-! int n;
-
- /*
- * Find out what transport we should use, then create one or more
---- 64,85 ----
-
- #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,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,128 ****
- serv->listen_fd[0] =
- inet_listen(MASTER_INET_PORT(serv),
- serv->max_proc > var_proc_limit ?
-! serv->max_proc : var_proc_limit, NON_BLOCKING);
- close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
- } else { /* virtual or host:port */
-! for (n = 0; n < serv->listen_fd_count; n++) {
- end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
- ":", MASTER_INET_PORT(serv), (char *) 0);
-! serv->listen_fd[n]
- = 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);
- myfree(end_point);
- }
- }
- break;
- default:
---- 120,150 ----
- serv->listen_fd[0] =
- inet_listen(MASTER_INET_PORT(serv),
- serv->max_proc > var_proc_limit ?
-! 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 (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);
-! #endif
-! tmpfd
- = inet_listen(end_point, serv->max_proc > var_proc_limit ?
-! 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 -Pcr postfix-2.0.16/src/qmqpd/qmqpd_peer.c postfix-2.0.16-ti1.20/src/qmqpd/qmqpd_peer.c
-*** postfix-2.0.16/src/qmqpd/qmqpd_peer.c Thu Jul 5 22:09:35 2001
---- postfix-2.0.16-ti1.20/src/qmqpd/qmqpd_peer.c Mon Jan 5 16:58:07 2004
-***************
-*** 70,85 ****
- )
- #endif
-
- /* Utility library. */
-
- #include <msg.h>
- #include <mymalloc.h>
- #include <valid_hostname.h>
- #include <stringops.h>
-
- /* Global library. */
-
--
- /* Application-specific. */
-
- #include "qmqpd.h"
---- 70,92 ----
- )
- #endif
-
-+ #ifdef INET6
-+ #define GAI_STRERROR(error) \
-+ ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
-+ #endif
-+
- /* Utility library. */
-
- #include <msg.h>
- #include <mymalloc.h>
- #include <valid_hostname.h>
- #include <stringops.h>
-+ #ifdef INET6
-+ #include <inet_addr_list.h> /* for NI_WITHSCOPEID */
-+ #endif
-
- /* Global library. */
-
- /* Application-specific. */
-
- #include "qmqpd.h"
-***************
-*** 88,103 ****
-
- void qmqpd_peer_init(QMQPD_STATE *state)
- {
-! struct sockaddr_in sin;
-! SOCKADDR_SIZE len = sizeof(sin);
- struct hostent *hp;
-! int i;
-
- /*
- * Look up the peer address information.
- */
-! if (getpeername(vstream_fileno(state->client),
-! (struct sockaddr *) & sin, &len) >= 0) {
- errno = 0;
- }
-
---- 95,118 ----
-
- void qmqpd_peer_init(QMQPD_STATE *state)
- {
-! char *myname = "qmqpd_peer_init";
-! #ifdef INET6
-! struct sockaddr_storage ss;
-! #else
-! struct sockaddr ss;
-! struct in_addr *in;
- struct hostent *hp;
-! #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), sa, &len) >= 0) {
- errno = 0;
- }
-
-***************
-*** 112,127 ****
- /*
- * 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) {
- state->name = mystrdup("unknown");
-! } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- } else {
-! state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
-
- /*
- * Reject the hostname if it does not list the peer address.
---- 127,197 ----
- /*
- * Look up and "verify" the client hostname.
- */
-! 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];
-! char rabuf[NI_MAXHOST];
-! struct addrinfo hints, *res0 = NULL, *res;
-! char *colonp;
-! #else
-! char abuf[sizeof("255.255.255.255") + 1];
-! char *hbuf;
-! #endif
-! int error = -1;
-!
-! #ifdef INET6
-! error = getnameinfo(sa, len, abuf, sizeof(abuf), NULL, 0,
-! NI_NUMERICHOST | NI_WITHSCOPEID);
-! if (error)
-! msg_fatal("%s: numeric getnameinfo lookup for peer: error %s",
-! myname, GAI_STRERROR(error));
-! /*
-! * Convert IPv4-mapped IPv6 address to 'true' IPv4 address
-! * early on. We have no need for the mapped form in logging
-! * or access checks.
-! */
-! if (sa->sa_family == AF_INET6
-! && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)
-! && (colonp = strrchr(abuf, ':')) != NULL) {
-! if (msg_verbose > 1)
-! msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
-! myname, abuf, colonp + 1);
-! state->addr = mystrdup(colonp + 1);
-! } else {
-! state->addr = mystrdup(abuf);
-! }
-!
-! error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
-! #else
-! in = &((struct sockaddr_in *)sa)->sin_addr;
-! inet_ntop(AF_INET, in, abuf, sizeof(abuf));
-! state->addr = mystrdup(abuf);
-! 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");
-! #ifdef INET6
-! if (error != EAI_NONAME)
-! msg_warn("%s: getnameinfo(%s,,,,,,NI_NAMEREQD) error %s",
-! myname, abuf, GAI_STRERROR(error));
-! #endif
-! } else if (!valid_hostname(hbuf, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- } else {
-! state->name = mystrdup(hbuf);
-
- /*
- * Reject the hostname if it does not list the peer address.
-***************
-*** 131,146 ****
- state->name = mystrdup("unknown"); \
- }
-
- 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)) {
- msg_warn("%s: hostname %s verification failed: bad address size %d",
- state->addr, state->name, hp->h_length);
- REJECT_PEER_NAME(state);
- } else {
- for (i = 0; /* void */ ; i++) {
- if (hp->h_addr_list[i] == 0) {
- msg_warn("%s: address not listed for hostname %s",
---- 201,252 ----
- 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, &res0);
-+ if (error) {
-+ msg_warn("%s: hostname %s verification failed: %s",
-+ state->addr, state->name, GAI_STRERROR(error));
-+ REJECT_PEER_NAME(state);
-+ } else {
-+ for (res = res0; res; res = res->ai_next) {
-+ if (res->ai_family != sa->sa_family)
-+ continue;
-+ error = getnameinfo(res->ai_addr, res->ai_addrlen,
-+ rabuf, sizeof(rabuf), NULL, 0,
-+ NI_NUMERICHOST | NI_WITHSCOPEID);
-+ if (error) {
-+ msg_warn("%s: %s: hostname %s verification failed: %s",
-+ myname, state->addr, state->name,
-+ GAI_STRERROR(error));
-+ REJECT_PEER_NAME(state);
-+ break;
-+ }
-+ if (strcmp(state->addr, rabuf) == 0)
-+ break; /* keep peer name */
-+ }
-+ if (res == NULL) {
-+ msg_warn("%s: %s: address not listed for hostname %s",
-+ myname, state->addr, state->name);
-+ REJECT_PEER_NAME(state);
-+ }
-+ }
-+ if (res0)
-+ freeaddrinfo(res0);
-+ #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(*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,159 ****
- REJECT_PEER_NAME(state);
- break;
- }
-! if (memcmp(hp->h_addr_list[i],
-! (char *) &sin.sin_addr,
-! sizeof(sin.sin_addr)) == 0)
- break; /* keep peer name */
- }
- }
- }
- }
-
---- 254,265 ----
- REJECT_PEER_NAME(state);
- break;
- }
-! if (memcmp(hp->h_addr_list[i], (char *)in,
-! sizeof(*in)) == 0)
- break; /* keep peer name */
- }
- }
-+ #endif
- }
- }
-
-diff -Pcr postfix-2.0.16/src/smtp/Makefile.in postfix-2.0.16-ti1.20/src/smtp/Makefile.in
-*** postfix-2.0.16/src/smtp/Makefile.in Sun Sep 14 02:04:13 2003
---- postfix-2.0.16-ti1.20/src/smtp/Makefile.in Mon Jan 5 16:58:07 2004
-***************
-*** 84,89 ****
---- 84,90 ----
- 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,108 ****
---- 104,110 ----
- 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,128 ****
---- 125,131 ----
- 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
-***************
-*** 141,150 ****
---- 144,155 ----
- 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
-***************
-*** 176,181 ****
---- 181,187 ----
- 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
-***************
-*** 221,229 ****
---- 227,238 ----
- 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
-***************
-*** 237,242 ****
---- 246,252 ----
- 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
-***************
-*** 256,261 ****
---- 266,272 ----
- 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
-***************
-*** 268,270 ****
---- 279,282 ----
- 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 -Pcr postfix-2.0.16/src/smtp/smtp.c postfix-2.0.16-ti1.20/src/smtp/smtp.c
-*** postfix-2.0.16/src/smtp/smtp.c Tue Jul 1 22:54:15 2003
---- postfix-2.0.16-ti1.20/src/smtp/smtp.c Mon Jan 5 16:58:07 2004
-***************
-*** 103,109 ****
- /* .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.
- /* .IP \fBsmtp_line_length_limit\fR
- /* Length limit for SMTP message content lines. Zero means no limit.
- /* Some SMTP servers misbehave on long lines.
---- 103,113 ----
- /* .IP \fBsmtp_never_send_ehlo\fR
- /* Never send EHLO at the start of a connection.
- /* .IP \fBsmtp_bind_address\fR
-! /* 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.
-***************
-*** 243,248 ****
---- 247,253 ----
- #include <debug_peer.h>
- #include <mail_error.h>
- #include <deliver_pass.h>
-+ #include <pfixtls.h>
-
- /* Single server skeleton. */
-
-***************
-*** 259,264 ****
---- 264,270 ----
- */
- 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,290 ****
---- 283,307 ----
- int var_smtp_always_ehlo;
- int var_smtp_never_ehlo;
- char *var_smtp_sasl_opts;
-+ char *var_smtp_sasl_tls_opts;
-+ char *var_smtp_sasl_tls_verified_opts;
- 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
-***************
-*** 394,399 ****
---- 411,417 ----
-
- static void pre_init(char *unused_name, char **unused_argv)
- {
-+
- debug_peer_init();
-
- if (var_smtp_sasl_enable)
-***************
-*** 403,408 ****
---- 421,434 ----
- 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 USE_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 */
-***************
-*** 436,443 ****
---- 462,475 ----
- VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
- VAR_SMTP_SASL_PASSWD, DEF_SMTP_SASL_PASSWD, &var_smtp_sasl_passwd, 0, 0,
- VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
-+ VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
-+ VAR_SMTP_SASL_TLSV_OPTS, DEF_SMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tls_verified_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[] = {
-***************
-*** 451,460 ****
---- 483,494 ----
- 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[] = {
- VAR_SMTP_LINE_LIMIT, DEF_SMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0,
-+ VAR_SMTP_TLS_SCERT_VD, DEF_SMTP_TLS_SCERT_VD, &var_smtp_tls_scert_vd, 0, 0,
- 0,
- };
- static CONFIG_BOOL_TABLE bool_table[] = {
-***************
-*** 466,471 ****
---- 500,509 ----
- 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 -Pcr postfix-2.0.16/src/smtp/smtp.h postfix-2.0.16-ti1.20/src/smtp/smtp.h
-*** postfix-2.0.16/src/smtp/smtp.h Thu May 23 21:18:02 2002
---- postfix-2.0.16-ti1.20/src/smtp/smtp.h Mon Jan 5 16:58:07 2004
-***************
-*** 27,32 ****
---- 27,33 ----
- * Global library.
- */
- #include <deliver_request.h>
-+ #include <pfixtls.h>
-
- /*
- * State information associated with each SMTP delivery. We're bundling the
-***************
-*** 79,87 ****
- char *addr; /* mail exchanger */
- char *namaddr; /* mail exchanger */
- int best; /* most preferred host */
- } SMTP_SESSION;
-
-! extern SMTP_SESSION *smtp_session_alloc(VSTREAM *, char *, char *);
- extern void smtp_session_free(SMTP_SESSION *);
-
- /*
---- 80,93 ----
- 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 void smtp_tls_list_init(void);
-! extern SMTP_SESSION *smtp_session_alloc(char *, VSTREAM *, char *, char *);
- extern void smtp_session_free(SMTP_SESSION *);
-
- /*
-diff -Pcr postfix-2.0.16/src/smtp/smtp_addr.c postfix-2.0.16-ti1.20/src/smtp/smtp_addr.c
-*** postfix-2.0.16/src/smtp/smtp_addr.c Fri Oct 25 01:03:11 2002
---- postfix-2.0.16-ti1.20/src/smtp/smtp_addr.c Mon Jan 5 16:58:07 2004
-***************
-*** 134,151 ****
- static void smtp_print_addr(char *what, DNS_RR *addr_list)
- {
- DNS_RR *addr;
-! struct in_addr in_addr;
-
- 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));
- }
- }
- msg_info("end %s address list", what);
- }
---- 134,207 ----
- static void smtp_print_addr(char *what, DNS_RR *addr_list)
- {
- DNS_RR *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 (
-! #ifdef INET6
-! addr->class && addr->class != C_IN
-! #else
-! addr->class != C_IN
-! #endif
-! ) {
-! 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,169 ****
- static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
- {
- char *myname = "smtp_addr_one";
- struct in_addr inaddr;
-- DNS_FIXED fixed;
- DNS_RR *addr = 0;
- DNS_RR *rr;
- struct hostent *hp;
-
- if (msg_verbose)
- msg_info("%s: host %s", myname, host);
-
- /*
- * Interpret a numerical name as an address.
- */
---- 211,233 ----
- 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_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,221 ****
---- 280,327 ----
- 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,256 ****
---- 357,365 ----
- 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,271 ****
-
- self = own_inet_addr_list();
- for (addr = addr_list; addr; addr = addr->next) {
-! for (i = 0; i < self->used; i++)
- 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);
- }
- }
-
- /*
---- 369,404 ----
-
- self = own_inet_addr_list();
- for (addr = addr_list; addr; addr = addr->next) {
-! 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
-+ }
- }
-
- /*
-***************
-*** 274,284 ****
---- 407,440 ----
- self = proxy_inet_addr_list();
- for (addr = addr_list; addr; addr = addr->next) {
- 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
- }
-
- /*
-***************
-*** 319,324 ****
---- 475,503 ----
- return (a->pref - b->pref);
- }
-
-+ #ifdef INET6
-+ static int smtp_compare_pref_aaaa_first(DNS_RR *a, DNS_RR *b)
-+ {
-+ if (a->pref != b->pref)
-+ return (a->pref - b->pref);
-+ if (a->type == T_AAAA)
-+ return -1;
-+ else if (b->type == T_AAAA)
-+ return 1;
-+ return 0;
-+ }
-+
-+ static int smtp_compare_host_aaaa_first(DNS_RR *a, DNS_RR *b)
-+ {
-+ if (a->type == b->type)
-+ return 0;
-+ if (a->type == T_AAAA)
-+ return -1;
-+ return 1;
-+ }
-+
-+ #endif
-+
- /* smtp_domain_addr - mail exchanger address lookup */
-
- DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
-***************
-*** 418,424 ****
---- 597,607 ----
- }
- if (addr_list && addr_list->next && var_smtp_rand_addr) {
- addr_list = dns_rr_shuffle(addr_list);
-+ #ifdef INET6
-+ addr_list = dns_rr_sort(addr_list, smtp_compare_pref_aaaa_first);
-+ #else
- addr_list = dns_rr_sort(addr_list, smtp_compare_pref);
-+ #endif
- }
- break;
- case DNS_NOTFOUND:
-***************
-*** 447,452 ****
---- 630,639 ----
- addr_list = smtp_addr_one((DNS_RR *) 0, host, PREF0, why);
- if (addr_list && addr_list->next && var_smtp_rand_addr)
- addr_list = dns_rr_shuffle(addr_list);
-+ #ifdef INET6
-+ if (addr_list && addr_list->next)
-+ addr_list = dns_rr_sort(addr_list, smtp_compare_host_aaaa_first);
-+ #endif
- if (msg_verbose)
- smtp_print_addr(host, addr_list);
- return (addr_list);
-diff -Pcr postfix-2.0.16/src/smtp/smtp_connect.c postfix-2.0.16-ti1.20/src/smtp/smtp_connect.c
-*** postfix-2.0.16/src/smtp/smtp_connect.c Sat Sep 13 02:35:53 2003
---- postfix-2.0.16-ti1.20/src/smtp/smtp_connect.c Mon Jan 5 16:58:35 2004
-***************
-*** 81,86 ****
---- 81,87 ----
- /* System library. */
-
- #include <sys_defs.h>
-+ #include <stdlib.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-***************
-*** 118,152 ****
-
- #include <mail_params.h>
- #include <own_inet_addr.h>
-
- /* DNS library. */
-
- #include <dns.h>
-
- /* Application-specific. */
-
- #include "smtp.h"
- #include "smtp_addr.h"
-
- /* smtp_connect_addr - connect to explicit address */
-
-! static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
- VSTRING *why)
- {
- char *myname = "smtp_connect_addr";
-! struct sockaddr_in sin;
-! int sock;
- INET_ADDR_LIST *addr_list;
- int conn_stat;
- int saved_errno;
- VSTREAM *stream;
- int ch;
-! unsigned long inaddr;
-
- /*
- * Sanity checks.
- */
-! if (addr->data_len > sizeof(sin.sin_addr)) {
- msg_warn("%s: skip address with length %d", myname, addr->data_len);
- smtp_errno = SMTP_RETRY;
- return (0);
---- 119,359 ----
-
- #include <mail_params.h>
- #include <own_inet_addr.h>
-+ #include <pfixtls.h>
-
- /* DNS library. */
-
- #include <dns.h>
-
-+ #ifdef INET6
-+ #define GAI_STRERROR(error) \
-+ ((error == EAI_SYSTEM) ? strerror(errno) : gai_strerror(error))
-+ #endif
-+
- /* Application-specific. */
-
- #include "smtp.h"
- #include "smtp_addr.h"
-
-+ /* smtp_force_bind: bind() address */
-+
-+ static void smtp_force_bind(const char *bind_addr,
-+ const char *bind_var,
-+ int sock,
-+ int af)
-+ {
-+ /*
-+ * If the bind() call fails, this is considered a non-fatal error.
-+ * All address conversion errors are fatal.
-+ */
-+ char *myname = "smtp_force_bind";
-+ #ifdef INET6
-+ char hbuf[NI_MAXHOST];
-+ int aierr;
-+ struct addrinfo hints, *res;
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-+ snprintf(hbuf, sizeof(hbuf), "%s", bind_addr);
-+ aierr = getaddrinfo(hbuf, NULL, &hints, &res);
-+ if (aierr == EAI_NONAME)
-+ msg_fatal("%s: bad %s parameter: \"%s\"",
-+ myname, bind_var, bind_addr);
-+ if (aierr != 0) {
-+ if (msg_verbose)
-+ msg_warn("%s: getaddrinfo(%s): %s",
-+ myname, hbuf, GAI_STRERROR(aierr));
-+ return;
-+ }
-+ aierr = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
-+ if (aierr != 0) {
-+ msg_warn("%s: getnameinfo(): %s",
-+ myname, GAI_STRERROR(aierr));
-+ freeaddrinfo(res);
-+ return;
-+ }
-+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
-+ msg_warn("%s: bind %s: %m", myname, hbuf);
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbuf);
-+ freeaddrinfo(res);
-+ #else /* 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, bind_var, bind_addr);
-+ return;
-+ }
-+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
-+ msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+ #endif /* INET6 */
-+ }
-+
-+ /* smtp_virtual_bind - bind() when acting as virtual host */
-+
-+ static void smtp_virtual_bind(int sock, int af)
-+ {
-+ char *myname = "smtp_virtual_bind";
-+ INET_ADDR_LIST *addr_list;
-+ int count;
-+
-+ #ifdef INET6
-+ int i;
-+ char hbuf[NI_MAXHOST];
-+ int aierr;
-+ struct sockaddr *sa;
-+ struct addrinfo hints, *loopback = NULL, *res = NULL;
-+
-+ /*
-+ * Check whether we are acting as a virtual host
-+ */
-+ count = 0;
-+ addr_list = own_inet_addr_list();
-+ for (i = 0; count < 2 && i < addr_list->used; i++)
-+ if (((struct sockaddr *)&addr_list->addrs[i])->sa_family == af)
-+ count++;
-+ if (count != 1)
-+ return;
-+
-+ /*
-+ * Bind the source address.
-+ */
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ aierr = getaddrinfo(NULL, "0", &hints, &loopback);
-+ if (aierr != 0) {
-+ loopback = NULL;
-+ msg_warn("%s: getaddrinfo(\"0\"): %s",
-+ myname, GAI_STRERROR(aierr));
-+ }
-+
-+ sa = (struct sockaddr *)&addr_list->addrs[i - 1];
-+ aierr = getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
-+ if (aierr != 0)
-+ msg_fatal("%s: getnameinfo() (AF=%d): %s",
-+ myname, af, GAI_STRERROR(aierr));
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = af;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
-+ aierr = getaddrinfo(hbuf, NULL, &hints, &res);
-+ if (aierr != 0)
-+ msg_fatal("%s: getaddrinfo(\"%s\"): %s",
-+ myname, hbuf, GAI_STRERROR(aierr));
-+
-+ if (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, hbuf);
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, hbuf);
-+ } else if (msg_verbose) {
-+ msg_info("%s: not calling bind(): unusable source "
-+ "address from \"%s\"", myname, hbuf);
-+ }
-+ if (res)
-+ freeaddrinfo(res);
-+ if (loopback)
-+ freeaddrinfo(loopback);
-+
-+ #else /* INET6 */
-+
-+ struct sockaddr_in sin;
-+ unsigned long inaddr; /*XXX BAD!*/
-+
-+ /*
-+ * Check whether we are acting as a virtual host
-+ */
-+ addr_list = own_inet_addr_list();
-+ count = addr_list->used;
-+ if (count != 1)
-+ return;
-+
-+ /*
-+ * Bind the source address.
-+ */
-+ 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)
-+ || !(((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));
-+ else if (msg_verbose)
-+ msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
-+ }
-+ #endif /* INET6 */
-+ }
-+
- /* smtp_connect_addr - connect to explicit address */
-
-! static SMTP_SESSION *smtp_connect_addr(char *dest, DNS_RR *addr, unsigned port,
- VSTRING *why)
- {
- char *myname = "smtp_connect_addr";
-! #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;
-! char *bind_addr;
-! char *bind_var;
-! #ifdef INET6
-! char *addr6_ptr = NULL;
-! #endif
-!
-! sa = (struct sockaddr *)&ss;
-! sin = (struct sockaddr_in *)&ss;
-! #ifdef INET6
-! sin6 = (struct sockaddr_in6 *)&ss;
-! #endif
-
- /*
- * Sanity checks.
- */
-! #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);
-***************
-*** 155,219 ****
- /*
- * 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);
-!
- /*
- * 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 (sin.sin_addr.s_addr == INADDR_NONE)
-! msg_fatal("%s: bad %s parameter: %s",
-! myname, VAR_SMTP_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));
-! }
-!
-! /*
-! * When running as a virtual host, bind to the virtual interface so that
-! * the mail appears to come from the "right" machine address.
-! */
-! else if ((addr_list = own_inet_addr_list())->used == 1) {
-! memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
-! inaddr = 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)
-! 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));
-! }
- }
-
- /*
- * Connect to the SMTP server.
- */
-! sin.sin_port = port;
-! memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-
- if (msg_verbose)
- msg_info("%s: trying: %s[%s] port %d...",
-! myname, addr->name, inet_ntoa(sin.sin_addr), 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);
- saved_errno = errno;
- non_blocking(sock, BLOCKING);
- errno = saved_errno;
- } else {
-! conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
- }
- if (conn_stat < 0) {
- vstring_sprintf(why, "connect to %s[%s]: %m",
-! addr->name, inet_ntoa(sin.sin_addr));
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
---- 362,465 ----
- /*
- * Initialize.
- */
-! switch (addr->type) {
-! #ifdef INET6
-! case T_AAAA:
-! bind_addr = "";
-! bind_var = VAR_SMTP_BIND_ADDR6;
-! if (*var_smtp_bind_addr6) {
-! addr6_ptr = mystrdup(var_smtp_bind_addr6);
-! if (*addr6_ptr == '[' && addr6_ptr[strlen(addr6_ptr) - 1] == ']') {
-! addr6_ptr[strlen(addr6_ptr) - 1] = 0;
-! bind_addr = addr6_ptr + 1;
-! } else {
-! msg_warn("%s: skip incorrectly bracketed IPv6 address in %s",
-! myname, 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;
-! bind_var = 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);
-! smtp_errno = SMTP_RETRY;
-! return (0);
-! }
-!
- /*
- * 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 (bind_addr && *bind_addr) {
-! smtp_force_bind(bind_addr, bind_var, sock, sa->sa_family);
-! #ifdef INET6
-! if (addr6_ptr)
-! myfree(addr6_ptr);
-! #endif
-! } else {
-! /*
-! * When running as a virtual host, bind to the virtual interface so that
-! * the mail appears to come from the "right" machine address.
-! */
-! smtp_virtual_bind(sock, sa->sa_family);
- }
-
- /*
- * Connect to the SMTP server.
- */
-! 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, hbuf, ntohs(port));
- if (var_smtp_conn_tmout > 0) {
- non_blocking(sock, NON_BLOCKING);
-! conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
- saved_errno = errno;
- non_blocking(sock, BLOCKING);
- errno = saved_errno;
- } else {
-! conn_stat = sane_connect(sock, sa, salen);
- }
- if (conn_stat < 0) {
- vstring_sprintf(why, "connect to %s[%s]: %m",
-! addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
-***************
-*** 223,230 ****
- * 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));
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
---- 469,476 ----
- * 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, hbuf);
- smtp_errno = SMTP_RETRY;
- close(sock);
- return (0);
-***************
-*** 235,242 ****
- */
- stream = vstream_fdopen(sock, O_RDWR);
- if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
-! vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial greeting",
-! addr->name, inet_ntoa(sin.sin_addr));
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
---- 481,488 ----
- */
- 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, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
-***************
-*** 248,254 ****
- */
- 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));
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
---- 494,500 ----
- */
- if (ch == '4' && var_smtp_skip_4xx_greeting) {
- vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
-! addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
-***************
-*** 259,270 ****
- */
- 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));
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
- }
-! return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
- }
-
- /* smtp_connect_host - direct connection to host */
---- 505,516 ----
- */
- if (ch == '5' && var_smtp_skip_5xx_greeting) {
- vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
-! addr->name, hbuf);
- smtp_errno = SMTP_RETRY;
- vstream_fclose(stream);
- return (0);
- }
-! return (smtp_session_alloc(dest, stream, addr->name, hbuf));
- }
-
- /* smtp_connect_host - direct connection to host */
-***************
-*** 274,280 ****
- 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
---- 520,526 ----
- 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
-***************
-*** 282,288 ****
- */
- addr_list = smtp_host_addr(host, why);
- for (addr = addr_list; addr; addr = addr->next) {
-! if ((session = smtp_connect_addr(addr, port, why)) != 0) {
- session->best = 1;
- break;
- }
---- 528,534 ----
- */
- addr_list = smtp_host_addr(host, why);
- for (addr = addr_list; addr; addr = addr->next) {
-! if ((session = smtp_connect_addr(host, addr, port, why)) != 0) {
- session->best = 1;
- break;
- }
-***************
-*** 311,317 ****
- */
- 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) {
- session->best = (addr->pref == addr_list->pref);
- break;
- }
---- 557,563 ----
- */
- addr_list = smtp_domain_addr(name, why, found_myself);
- for (addr = addr_list; addr; addr = addr->next) {
-! if ((session = smtp_connect_addr(name, addr, port, why)) != 0) {
- session->best = (addr->pref == addr_list->pref);
- break;
- }
-***************
-*** 353,358 ****
---- 599,605 ----
- msg_fatal("unknown service: %s/%s", service, protocol);
- *portp = sp->s_port;
- }
-+
- return (buf);
- }
-
-diff -Pcr postfix-2.0.16/src/smtp/smtp_proto.c postfix-2.0.16-ti1.20/src/smtp/smtp_proto.c
-*** postfix-2.0.16/src/smtp/smtp_proto.c Fri Apr 18 16:28:57 2003
---- postfix-2.0.16-ti1.20/src/smtp/smtp_proto.c Mon Jan 5 16:58:08 2004
-***************
-*** 103,108 ****
---- 103,109 ----
- #include <quote_821_local.h>
- #include <mail_proto.h>
- #include <mime_state.h>
-+ #include <pfixtls.h>
-
- /* Application-specific. */
-
-***************
-*** 170,175 ****
---- 171,178 ----
- char *words;
- char *word;
- int n;
-+ int oldfeatures;
-+ int rval;
-
- /*
- * Prepare for disaster.
-***************
-*** 232,238 ****
- translit(resp->str, "\n", " ")));
- return (0);
- }
-!
- /*
- * 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
---- 235,242 ----
- translit(resp->str, "\n", " ")));
- return (0);
- }
-! 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
-***************
-*** 244,249 ****
---- 248,254 ----
- * 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)
-***************
-*** 260,265 ****
---- 265,272 ----
- 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);
-***************
-*** 277,282 ****
---- 284,411 ----
- msg_info("server features: 0x%x size %.0f",
- state->features, (double) state->size_limit);
-
-+ #ifdef USE_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 -Pcr postfix-2.0.16/src/smtp/smtp_sasl.h postfix-2.0.16-ti1.20/src/smtp/smtp_sasl.h
-*** postfix-2.0.16/src/smtp/smtp_sasl.h Mon Apr 17 23:49:23 2000
---- postfix-2.0.16-ti1.20/src/smtp/smtp_sasl.h Mon Jan 5 16:58:08 2004
-***************
-*** 14,20 ****
- extern void smtp_sasl_initialize(void);
- extern void smtp_sasl_connect(SMTP_STATE *);
- extern int smtp_sasl_passwd_lookup(SMTP_STATE *);
-! extern void smtp_sasl_start(SMTP_STATE *);
- extern int smtp_sasl_authenticate(SMTP_STATE *, VSTRING *);
- extern void smtp_sasl_cleanup(SMTP_STATE *);
-
---- 14,20 ----
- extern void smtp_sasl_initialize(void);
- extern void smtp_sasl_connect(SMTP_STATE *);
- extern int smtp_sasl_passwd_lookup(SMTP_STATE *);
-! extern void smtp_sasl_start(SMTP_STATE *, const char *, const char *);
- extern int smtp_sasl_authenticate(SMTP_STATE *, VSTRING *);
- extern void smtp_sasl_cleanup(SMTP_STATE *);
-
-diff -Pcr postfix-2.0.16/src/smtp/smtp_sasl_glue.c postfix-2.0.16-ti1.20/src/smtp/smtp_sasl_glue.c
-*** postfix-2.0.16/src/smtp/smtp_sasl_glue.c Fri Mar 29 23:24:22 2002
---- postfix-2.0.16-ti1.20/src/smtp/smtp_sasl_glue.c Mon Jan 5 16:58:08 2004
-***************
-*** 11,17 ****
- /* void smtp_sasl_connect(state)
- /* SMTP_STATE *state;
- /*
-! /* void smtp_sasl_start(state)
- /* SMTP_STATE *state;
- /*
- /* int smtp_sasl_passwd_lookup(state)
---- 11,17 ----
- /* void smtp_sasl_connect(state)
- /* SMTP_STATE *state;
- /*
-! /* void smtp_sasl_start(state, sasl_opts_name, sasl_opts_var)
- /* SMTP_STATE *state;
- /*
- /* int smtp_sasl_passwd_lookup(state)
-***************
-*** 33,39 ****
- /*
- /* smtp_sasl_start() performs per-session initialization. This
- /* routine must be called once per session before doing any SASL
-! /* authentication.
- /*
- /* smtp_sasl_passwd_lookup() looks up the username/password
- /* for the current SMTP server. The result is zero in case
---- 33,41 ----
- /*
- /* smtp_sasl_start() performs per-session initialization. This
- /* routine must be called once per session before doing any SASL
-! /* authentication. The sasl_opts_name and sasl_opts_var parameters are
-! /* the postfix configuration parameters setting the security
-! /* policy of the SASL authentication.
- /*
- /* smtp_sasl_passwd_lookup() looks up the username/password
- /* for the current SMTP server. The result is zero in case
-***************
-*** 122,129 ****
- 0,
- };
-
-- static int smtp_sasl_sec_opts;
--
- /*
- * Silly little macros.
- */
---- 124,129 ----
-***************
-*** 319,329 ****
- if (sasl_client_init(callbacks) != SASL_OK)
- msg_fatal("SASL library initialization");
-
-- /*
-- * Configuration parameters.
-- */
-- smtp_sasl_sec_opts = name_mask(VAR_SMTP_SASL_OPTS, smtp_sasl_sec_mask,
-- var_smtp_sasl_opts);
- }
-
- /* smtp_sasl_connect - per-session client initialization */
---- 319,324 ----
-***************
-*** 341,347 ****
-
- /* smtp_sasl_start - per-session SASL initialization */
-
-! void smtp_sasl_start(SMTP_STATE *state)
- {
- static sasl_callback_t callbacks[] = {
- {SASL_CB_USER, &smtp_sasl_get_user, 0},
---- 336,343 ----
-
- /* smtp_sasl_start - per-session SASL initialization */
-
-! void smtp_sasl_start(SMTP_STATE *state, const char *sasl_opts_name,
-! const char *sasl_opts_var)
- {
- static sasl_callback_t callbacks[] = {
- {SASL_CB_USER, &smtp_sasl_get_user, 0},
-***************
-*** 383,389 ****
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = smtp_sasl_sec_opts;
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
---- 379,386 ----
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = name_mask(sasl_opts_name, smtp_sasl_sec_mask,
-! sasl_opts_var);
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
-diff -Pcr postfix-2.0.16/src/smtp/smtp_sasl_proto.c postfix-2.0.16-ti1.20/src/smtp/smtp_sasl_proto.c
-*** postfix-2.0.16/src/smtp/smtp_sasl_proto.c Tue May 22 20:27:06 2001
---- postfix-2.0.16-ti1.20/src/smtp/smtp_sasl_proto.c Mon Jan 5 16:58:08 2004
-***************
-*** 114,120 ****
- * required, and assume that an authentication error is recoverable.
- */
- if (smtp_sasl_passwd_lookup(state) != 0) {
-! smtp_sasl_start(state);
- if (smtp_sasl_authenticate(state, why) <= 0)
- ret = smtp_site_fail(state, 450, "Authentication failed: %s",
- vstring_str(why));
---- 114,130 ----
- * required, and assume that an authentication error is recoverable.
- */
- if (smtp_sasl_passwd_lookup(state) != 0) {
-!
-! if (!state->session->tls_info.protocol)
-! smtp_sasl_start(state, VAR_SMTP_SASL_OPTS, var_smtp_sasl_opts);
-! else if (!state->session->tls_info.peer_verified ||
-! !state->session->tls_info.hostname_matched)
-! smtp_sasl_start(state, VAR_SMTP_SASL_TLS_OPTS,
-! var_smtp_sasl_tls_opts);
-! else
-! smtp_sasl_start(state, VAR_SMTP_SASL_TLSV_OPTS,
-! var_smtp_sasl_tls_verified_opts);
-!
- if (smtp_sasl_authenticate(state, why) <= 0)
- ret = smtp_site_fail(state, 450, "Authentication failed: %s",
- vstring_str(why));
-diff -Pcr postfix-2.0.16/src/smtp/smtp_session.c postfix-2.0.16-ti1.20/src/smtp/smtp_session.c
-*** postfix-2.0.16/src/smtp/smtp_session.c Mon Nov 20 19:06:05 2000
---- postfix-2.0.16-ti1.20/src/smtp/smtp_session.c Mon Jan 5 16:58:08 2004
-***************
-*** 42,56 ****
- #include <vstream.h>
- #include <stringops.h>
-
- /* Application-specific. */
-
- #include "smtp.h"
-
- /* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
-
-! SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, char *host, char *addr)
- {
- SMTP_SESSION *session;
-
- session = (SMTP_SESSION *) mymalloc(sizeof(*session));
- session->stream = stream;
---- 42,83 ----
- #include <vstream.h>
- #include <stringops.h>
-
-+ #include <mail_params.h>
-+ #include <maps.h>
-+ #include <pfixtls.h>
-+
- /* Application-specific. */
-
- #include "smtp.h"
-
-+ #ifdef USE_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(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,63 ****
---- 85,145 ----
- 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 USE_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,70 ****
---- 147,157 ----
-
- void smtp_session_free(SMTP_SESSION *session)
- {
-+ #ifdef USE_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 -Pcr postfix-2.0.16/src/smtp/smtp_unalias.c postfix-2.0.16-ti1.20/src/smtp/smtp_unalias.c
-*** postfix-2.0.16/src/smtp/smtp_unalias.c Thu Sep 28 19:06:09 2000
---- postfix-2.0.16-ti1.20/src/smtp/smtp_unalias.c Mon Jan 5 16:58:08 2004
-***************
-*** 86,92 ****
- 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)
- vstring_strcpy(fqdn, name);
- htable_enter(cache, name, result = vstring_export(fqdn));
- }
---- 86,96 ----
- 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,
-! #ifdef INET6
-! T_AAAA,
-! #endif
-! 0) != DNS_OK)
- vstring_strcpy(fqdn, name);
- htable_enter(cache, name, result = vstring_export(fqdn));
- }
-diff -Pcr postfix-2.0.16/src/smtpd/Makefile.in postfix-2.0.16-ti1.20/src/smtpd/Makefile.in
-*** postfix-2.0.16/src/smtpd/Makefile.in Sun Sep 14 02:04:06 2003
---- postfix-2.0.16-ti1.20/src/smtpd/Makefile.in Mon Jan 5 16:58:08 2004
-***************
-*** 148,153 ****
---- 148,154 ----
- smtpd.o: ../../include/lex_822.h
- smtpd.o: ../../include/namadr_list.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
-***************
-*** 176,181 ****
---- 177,183 ----
- 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
-***************
-*** 222,227 ****
---- 224,230 ----
- smtpd_check.o: ../../include/iostuff.h
- smtpd_check.o: ../../include/attr.h
- smtpd_check.o: ../../include/mail_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
-***************
-*** 238,243 ****
---- 241,247 ----
- 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
-***************
-*** 294,299 ****
---- 298,304 ----
- 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
-***************
-*** 303,305 ****
---- 308,311 ----
- 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 -Pcr postfix-2.0.16/src/smtpd/smtpd.c postfix-2.0.16-ti1.20/src/smtpd/smtpd.c
-*** postfix-2.0.16/src/smtpd/smtpd.c Thu Sep 11 01:42:19 2003
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd.c Mon Jan 5 16:58:08 2004
-***************
-*** 356,361 ****
---- 356,362 ----
- #include <quote_822_local.h>
- #include <lex_822.h>
- #include <namadr_list.h>
-+ #include <pfixtls.h>
-
- /* Single-threaded server skeleton. */
-
-***************
-*** 380,385 ****
---- 381,387 ----
- */
- 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 */
-***************
-*** 438,443 ****
---- 440,455 ----
- int var_relay_rcpt_code;
- char *var_verp_clients;
- int var_show_unk_rcpt_table;
-+ 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;
-+ char *var_smtpd_sasl_tls_opts;
-
- /*
- * Silly little macros.
-***************
-*** 546,556 ****
---- 558,578 ----
- if (var_disable_vrfy_cmd == 0)
- smtpd_chat_reply(state, "250-VRFY");
- smtpd_chat_reply(state, "250-ETRN");
-+ #ifdef USE_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 USE_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 USE_SSL
-+ }
-+ #endif
- }
- #endif
- if (namadr_list_match(verp_clients, state->name, state->addr))
-***************
-*** 989,999 ****
---- 1011,1086 ----
- 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 *err;
-+ char *peer_CN;
-+ char *issuer_CN;
- char *start;
- int len;
- int curr_rec_type;
-***************
-*** 1035,1043 ****
- rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc);
- rec_fputs(state->cleanup, REC_TYPE_MESG, "");
- rec_fprintf(state->cleanup, REC_TYPE_NORM,
-! "Received: from %s (%s [%s])",
- state->helo_name ? state->helo_name : state->name,
-! state->name, state->addr);
- if (state->rcpt_count == 1 && state->recipient) {
- rec_fprintf(state->cleanup, REC_TYPE_NORM,
- "\tby %s (%s) with %s id %s",
---- 1122,1159 ----
- rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc);
- rec_fputs(state->cleanup, REC_TYPE_MESG, "");
- rec_fprintf(state->cleanup, REC_TYPE_NORM,
-! "Received: from %s (%s [%s%s])",
- state->helo_name ? state->helo_name : state->name,
-! state->name, state->addr_tag, 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",
-***************
-*** 1388,1393 ****
---- 1504,1593 ----
- }
- }
-
-+ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
-+ {
-+ char *err;
-+
-+ #ifdef USE_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);
-+ #ifdef USE_SASL_AUTH
-+ if (var_smtpd_sasl_enable) {
-+ /*
-+ * When TLS is enabled, another set of AUTH methods may be offered,
-+ * for example plain text methods that would not be offered without
-+ * encryption protection. Reconnect with a different set of options.
-+ */
-+ smtpd_sasl_disconnect(state);
-+ smtpd_sasl_connect(state, VAR_SMTPD_SASL_TLS_OPTS,
-+ var_smtpd_sasl_tls_opts);
-+ smtpd_sasl_auth_reset(state);
-+ }
-+ #endif
-+ 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 USE_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
-***************
-*** 1406,1411 ****
---- 1606,1615 ----
- "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT,
- "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT,
-
-+ #ifdef USE_SSL
-+ "STARTTLS", starttls_cmd, 0,
-+ #endif
-+
- #ifdef USE_SASL_AUTH
- "AUTH", smtpd_sasl_auth_cmd, 0,
- #endif
-***************
-*** 1524,1532 ****
- state->error_count++;
- continue;
- }
- state->where = cmdp->name;
-! if (cmdp->action(state, argc, argv) != 0)
- state->error_count++;
- if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT)
- && state->junk_cmds++ > var_smtpd_junk_cmd_limit)
- state->error_count++;
---- 1728,1755 ----
- 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) {
- 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++;
-***************
-*** 1552,1557 ****
---- 1775,1781 ----
- * 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)
-***************
-*** 1586,1591 ****
---- 1810,1852 ----
- smtpd_state_init(&state, stream);
- msg_info("connect from %s[%s]", state.name, state.addr);
-
-+ #ifdef USE_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
-+
- /*
- * See if we need to turn on verbose logging for this client.
- */
-***************
-*** 1619,1625 ****
-
- 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.
---- 1880,1885 ----
-***************
-*** 1637,1642 ****
---- 1897,1916 ----
- msg_warn("%s is true, but SASL support is not compiled in",
- VAR_SMTPD_SASL_ENABLE);
- #endif
-+
-+ #ifdef USE_SSL
-+ /*
-+ * Keys can only be loaded when running with superuser permissions.
-+ * When called from "sendmail -bs" this is not the case, but STARTTLS
-+ * is not used in this scenario anyhow.
-+ */
-+ if (geteuid() == 0) {
-+ 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 */
-***************
-*** 1664,1674 ****
---- 1938,1950 ----
- VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 0, 0,
- VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
- VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 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[] = {
- VAR_SMTPD_TMOUT, DEF_SMTPD_TMOUT, &var_smtpd_tmout, 1, 0,
- VAR_SMTPD_ERR_SLEEP, DEF_SMTPD_ERR_SLEEP, &var_smtpd_err_sleep, 0, 0,
-+ VAR_SMTPD_STARTTLS_TMOUT, DEF_SMTPD_STARTTLS_TMOUT, &var_smtpd_starttls_tmout, 1, 0,
- 0,
- };
- static CONFIG_BOOL_TABLE bool_table[] = {
-***************
-*** 1680,1685 ****
---- 1956,1968 ----
- 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_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
-+ 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[] = {
-***************
-*** 1711,1716 ****
---- 1994,2001 ----
- VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0,
- VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0,
- VAR_VERP_CLIENTS, DEF_VERP_CLIENTS, &var_verp_clients, 0, 0,
-+ VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_relay_ccerts, 0, 0,
-+ VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0,
- 0,
- };
- static CONFIG_RAW_TABLE raw_table[] = {
-***************
-*** 1732,1734 ****
---- 2017,2020 ----
- MAIL_SERVER_PRE_ACCEPT, pre_accept,
- 0);
- }
-+
-diff -Pcr postfix-2.0.16/src/smtpd/smtpd.h postfix-2.0.16-ti1.20/src/smtpd/smtpd.h
-*** postfix-2.0.16/src/smtpd/smtpd.h Wed Mar 19 16:35:49 2003
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd.h Mon Jan 5 16:58:08 2004
-***************
-*** 32,37 ****
---- 32,38 ----
- * Global library.
- */
- #include <mail_stream.h>
-+ #include <pfixtls.h>
-
- /*
- * Variables that keep track of conversation state. There is only one SMTP
-***************
-*** 52,57 ****
---- 53,59 ----
- time_t time;
- char *name;
- char *addr;
-+ char *addr_tag;
- char *namaddr;
- int peer_code; /* 2=ok, 4=soft, 5=hard */
- int error_count;
-***************
-*** 95,100 ****
---- 97,107 ----
- int defer_if_permit_sender; /* force permit into warning */
- int discard; /* discard message */
- VSTRING *expand_buf; /* scratch space for $name expansion */
-+ 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 -Pcr postfix-2.0.16/src/smtpd/smtpd_check.c postfix-2.0.16-ti1.20/src/smtpd/smtpd_check.c
-*** postfix-2.0.16/src/smtpd/smtpd_check.c Tue Aug 12 16:53:25 2003
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_check.c Mon Jan 5 16:58:08 2004
-***************
-*** 291,296 ****
---- 291,297 ----
- #include <string_list.h>
- #include <namadr_list.h>
- #include <domain_list.h>
-+ #include <string_list.h>
- #include <mail_params.h>
- #include <canon_addr.h>
- #include <resolve_clnt.h>
-***************
-*** 370,375 ****
---- 371,379 ----
- static DOMAIN_LIST *relay_domains;
- static NAMADR_LIST *mynetworks;
- static NAMADR_LIST *perm_mx_networks;
-+ #ifdef USE_SSL
-+ static MAPS *relay_ccerts;
-+ #endif
-
- /*
- * How to do parent domain wildcard matching, if any.
-***************
-*** 449,454 ****
---- 453,460 ----
- defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2))
- #define DEFER_IF_REJECT3(state, class, fmt, a1, a2, a3) \
- defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
-+ #define DEFER_IF_REJECT4(state, class, fmt, a1, a2, a3, a4) \
-+ defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3), (a4))
- #define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) do { \
- if ((state)->warn_if_reject == 0) \
- defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
-***************
-*** 627,632 ****
---- 633,642 ----
- perm_mx_networks =
- namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
- var_perm_mx_networks);
-+ #ifdef USE_SSL
-+ relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_relay_ccerts,
-+ DICT_FLAG_LOCK);
-+ #endif
-
- /*
- * Pre-parse and pre-open the recipient maps.
-***************
-*** 1131,1136 ****
---- 1141,1176 ----
-
- static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
-
-+ /* permit_tls_clientcerts - OK/DUNNO for message relaying */
-+
-+ #ifdef USE_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,
-***************
-*** 1270,1277 ****
- static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
- const char *reply_name, const char *reply_class)
- {
- char *myname = "all_auth_mx_addr";
-! struct in_addr addr;
- DNS_RR *rr;
- DNS_RR *addr_list;
- int dns_status;
---- 1310,1325 ----
- static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
- const char *reply_name, const char *reply_class)
- {
-+ size_t len;
- char *myname = "all_auth_mx_addr";
-! char *addr;
-! struct in_addr addr4;
-! #ifdef INET6
-! struct in6_addr addr6;
-! char hbuf[NI_MAXHOST];
-! #else
-! char *hbuf;
-! #endif
- DNS_RR *rr;
- DNS_RR *addr_list;
- int dns_status;
-***************
-*** 1288,1294 ****
- /*
- * Verify that all host addresses are within permit_mx_backup_networks.
- */
-! dns_status = dns_lookup(host, T_A, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0);
- if (dns_status != DNS_OK) {
- DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
- "450 <%s>: %s rejected: Unable to look up host %s as mail exchanger",
---- 1336,1344 ----
- /*
- * Verify that all host addresses are within permit_mx_backup_networks.
- */
-! dns_status = dns_lookup_types(host, 0, (DNS_RR **) &addr_list,
-! (VSTRING *) 0,
-! (VSTRING *) 0, RR_ADDR_TYPES, 0);
- if (dns_status != DNS_OK) {
- DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
- "450 <%s>: %s rejected: Unable to look up host %s as mail exchanger",
-***************
-*** 1296,1311 ****
- return (NOPE);
- }
- for (rr = addr_list; rr != 0; rr = rr->next) {
-! if (rr->data_len > sizeof(addr)) {
- msg_warn("%s: skipping address length %d for host %s",
- state->queue_id, rr->data_len, host);
- continue;
- }
-! memcpy((char *) &addr, rr->data, sizeof(addr));
- if (msg_verbose)
-! msg_info("%s: checking: %s", myname, inet_ntoa(addr));
-
-! if (!namadr_list_match(perm_mx_networks, host, inet_ntoa(addr))) {
-
- /*
- * Reject: at least one IP address is not listed in
---- 1346,1373 ----
- return (NOPE);
- }
- for (rr = addr_list; rr != 0; rr = rr->next) {
-! #ifdef INET6
-! if (rr->type == T_AAAA)
-! len = sizeof(addr6), addr = (char *) &addr6;
-! else /* T_A */
-! #endif
-! len = sizeof(addr4), addr = (char *) &addr4;
-! if (rr->data_len > len) {
- msg_warn("%s: skipping address length %d for host %s",
- state->queue_id, rr->data_len, host);
- continue;
- }
-! memcpy(addr, rr->data, len);
-! #ifdef INET6
-! inet_ntop(rr->type == T_AAAA ? AF_INET6 : AF_INET,
-! addr, hbuf, sizeof(hbuf));
-! #else
-! hbuf = inet_ntoa(*(struct in_addr *)addr);
-! #endif
- if (msg_verbose)
-! msg_info("%s: checking: %s", myname, hbuf);
-
-! if (!namadr_list_match(perm_mx_networks, host, hbuf)) {
-
- /*
- * Reject: at least one IP address is not listed in
-***************
-*** 1313,1319 ****
- */
- if (msg_verbose)
- msg_info("%s: address %s for %s does not match %s",
-! myname, inet_ntoa(addr), host, VAR_PERM_MX_NETWORKS);
- dns_rr_free(addr_list);
- return (NOPE);
- }
---- 1375,1381 ----
- */
- if (msg_verbose)
- msg_info("%s: address %s for %s does not match %s",
-! myname, hbuf, host, VAR_PERM_MX_NETWORKS);
- dns_rr_free(addr_list);
- return (NOPE);
- }
-***************
-*** 1327,1332 ****
---- 1389,1438 ----
- static int has_my_addr(SMTPD_STATE *state, const char *host,
- const char *reply_name, const char *reply_class)
- {
-+ #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, defer rather than reject
-+ */
-+ #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) {
-+ DEFER_IF_REJECT4(state, MAIL_ERROR_POLICY,
-+ "450 <%s>: %s rejected: Mail exchanger lookup error for %s: %s",
-+ reply_name, reply_class, host, gai_strerror(error));
-+ return (NOPE);
-+ }
-+ 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;
-***************
-*** 1365,1370 ****
---- 1471,1477 ----
- msg_info("%s: host %s: no match", myname, host);
-
- return (NOPE);
-+ #endif
- }
-
- /* i_am_mx - is this machine listed as MX relay */
-***************
-*** 1939,1944 ****
---- 2046,2055 ----
- char *addr;
- const char *value;
- DICT *dict;
-+ int delim;
-+ #ifdef INET6
-+ struct in6_addr a6;
-+ #endif
-
- if (msg_verbose)
- msg_info("%s: %s", myname, address);
-***************
-*** 1949,1954 ****
---- 2060,2071 ----
- #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
-
- addr = STR(vstring_strcpy(error_text, address));
-+ #ifdef INET6
-+ if (inet_pton(AF_INET6, addr, &a6) == 1)
-+ delim = ':';
-+ else
-+ #endif
-+ delim = '.';
-
- if ((dict = dict_handle(table)) == 0)
- msg_panic("%s: dictionary not found: %s", myname, table);
-***************
-*** 1962,1968 ****
- msg_fatal("%s: table lookup problem", table);
- }
- flags = PARTIAL;
-! } while (split_at_right(addr, '.'));
-
- CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
- }
---- 2079,2085 ----
- msg_fatal("%s: table lookup problem", table);
- }
- flags = PARTIAL;
-! } while (split_at_right(addr, delim));
-
- CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
- }
-***************
-*** 2261,2266 ****
---- 2378,2384 ----
- * Do the query. If the DNS lookup produces no definitive reply, give the
- * requestor the benefit of the doubt. We can't block all email simply
- * because an RBL server is unavailable.
-+ * Don't do this for AAAA records. Yet.
- */
- why = vstring_alloc(10);
- dns_status = dns_lookup(query, T_A, 0, (DNS_RR **) 0,
-***************
-*** 2396,2419 ****
- VSTRING *query;
- int i;
- SMTPD_RBL_STATE *rbl;
-
- if (msg_verbose)
- msg_info("%s: %s %s", myname, reply_class, addr);
-
- /*
-! * IPv4 only for now
- */
- #ifdef INET6
- if (inet_pton(AF_INET, addr, &a) != 1)
- return SMTPD_CHECK_DUNNO;
- #endif
-
- /*
- * Reverse the client IPV4 address, tack on the RBL domain name and query
- * the DNS for an A record.
- */
- query = vstring_alloc(100);
-- octets = argv_split(addr, ".");
- for (i = octets->argc - 1; i >= 0; i--) {
- vstring_strcat(query, octets->argv[i]);
- vstring_strcat(query, ".");
---- 2514,2541 ----
- VSTRING *query;
- int i;
- SMTPD_RBL_STATE *rbl;
-+ #ifdef INET6
-+ struct in_addr a;
-+ #endif
-
- if (msg_verbose)
- msg_info("%s: %s %s", myname, reply_class, addr);
-
- /*
-! * IPv4 / IPv6-mapped IPv4 (if supported) only for now
- */
- #ifdef INET6
- if (inet_pton(AF_INET, addr, &a) != 1)
- return SMTPD_CHECK_DUNNO;
-+ else
- #endif
-+ octets = argv_split(addr, ".");
-
- /*
- * Reverse the client IPV4 address, tack on the RBL domain name and query
- * the DNS for an A record.
- */
- query = vstring_alloc(100);
- for (i = octets->argc - 1; i >= 0; i--) {
- vstring_strcat(query, octets->argv[i]);
- vstring_strcat(query, ".");
-***************
-*** 2804,2809 ****
---- 2926,2937 ----
- #else
- msg_warn("restriction `%s' ignored: no SASL support", name);
- #endif
-+ #ifdef USE_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,
-***************
-*** 3394,3399 ****
---- 3522,3528 ----
- char *var_etrn_checks = "";
- char *var_data_checks = "";
- char *var_relay_domains = "";
-+ char *var_relay_ccerts = "";
- char *var_mynetworks = "";
- char *var_notify_classes = "";
-
-***************
-*** 3642,3648 ****
-
- /* smtpd_sasl_connect - stub */
-
-! void smtpd_sasl_connect(SMTPD_STATE *state)
- {
- msg_panic("smtpd_sasl_connect was called");
- }
---- 3771,3778 ----
-
- /* smtpd_sasl_connect - stub */
-
-! void smtpd_sasl_connect(SMTPD_STATE *state, const char *opts_name,
-! const char *opts_var)
- {
- msg_panic("smtpd_sasl_connect was called");
- }
-diff -Pcr postfix-2.0.16/src/smtpd/smtpd_peer.c postfix-2.0.16-ti1.20/src/smtpd/smtpd_peer.c
-*** postfix-2.0.16/src/smtpd/smtpd_peer.c Thu Aug 22 19:50:51 2002
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_peer.c Mon Jan 5 16:58:08 2004
-***************
-*** 63,68 ****
---- 63,80 ----
- #include <netdb.h>
- #include <string.h>
-
-+ /* Utility library. */
-+
-+ #include <msg.h>
-+ #include <mymalloc.h>
-+ #include <valid_hostname.h>
-+ #include <stringops.h>
-+ #ifdef INET6
-+ #include <inet_addr_list.h> /* for NI_WITHSCOPEID */
-+ #endif
-+
-+ /* Global library. */
-+
- /*
- * Older systems don't have h_errno. Even modern systems don't have
- * hstrerror().
-***************
-*** 84,99 ****
- )
- #endif
-
-! /* Utility library. */
-!
-! #include <msg.h>
-! #include <mymalloc.h>
-! #include <valid_hostname.h>
-! #include <stringops.h>
-!
-! /* Global library. */
-!
-!
- /* Application-specific. */
-
- #include "smtpd.h"
---- 96,106 ----
- )
- #endif
-
-! #ifdef INET6
-! #define GAI_STRERROR(error) \
-! ((error == EAI_SYSTEM) ? strerror(errno) : gai_strerror(error))
-! #endif
-!
- /* Application-specific. */
-
- #include "smtpd.h"
-***************
-*** 102,122 ****
-
- void smtpd_peer_init(SMTPD_STATE *state)
- {
-! struct sockaddr_in sin;
-! SOCKADDR_SIZE len = sizeof(sin);
- struct hostent *hp;
-! int i;
-
-! /*
-! * Avoid suprious complaints from Purify on Solaris.
-! */
-! memset((char *) &sin, 0, len);
-
- /*
- * Look up the peer address information.
- */
-! if (getpeername(vstream_fileno(state->client),
-! (struct sockaddr *) & sin, &len) >= 0) {
- errno = 0;
- }
-
---- 109,132 ----
-
- void smtpd_peer_init(SMTPD_STATE *state)
- {
-! char *myname = "smtpd_peer_init";
-! #ifdef INET6
-! struct sockaddr_storage ss;
-! #else
-! struct sockaddr ss;
-! struct in_addr *in;
- struct hostent *hp;
-! #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), sa, &len) >= 0) {
- errno = 0;
- }
-
-***************
-*** 132,154 ****
- /*
- * 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) {
- state->name = mystrdup("unknown");
- state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
-! } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
- msg_warn("numeric result %s in address->name lookup for %s",
-! hp->h_name, state->addr);
- state->name = mystrdup("unknown");
- state->peer_code = 5;
-! } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- state->peer_code = 5;
- } else {
-! state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
- state->peer_code = 2;
-
- /*
---- 142,249 ----
- /*
- * Look up and "verify" the client hostname.
- */
-! 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];
-! char rabuf[NI_MAXHOST];
-! struct addrinfo hints, *res0 = NULL, *res;
-! char *colonp;
-! #else
-! char abuf[sizeof("255.255.255.255") + 1];
-! char *hbuf;
-! #endif
-! int error = -1;
-!
-! #ifdef INET6
-! error = getnameinfo(sa, len, abuf, sizeof(abuf), NULL, 0,
-! NI_NUMERICHOST | NI_WITHSCOPEID);
-! if (error)
-! msg_fatal("%s: numeric getnameinfo lookup for peer: error %s",
-! myname, GAI_STRERROR(error));
-!
-! /*
-! * Convert an IPv4-mapped IPv6-address to 'true' IPv4 address
-! * early on. We have no need for the mapped form in logging,
-! * hostname verification and access checks.
-! */
-! if (sa->sa_family == AF_INET6
-! && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)
-! && (colonp = strrchr(abuf, ':')) != NULL) {
-! struct addrinfo hints, *res0;
-! if (msg_verbose > 1)
-! msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
-! myname, abuf, colonp + 1);
-! state->addr = mystrdup(colonp + 1);
-! /*
-! * We create new socket information so getnameinfo() will be
-! * performed on the rewritten IPv4 address.
-! */
-! memset(&hints, 0, sizeof(hints));
-! hints.ai_family = AF_INET;
-! hints.ai_socktype = SOCK_STREAM;
-! hints.ai_flags = AI_NUMERICHOST;
-! error = getaddrinfo(state->addr, NULL, &hints, &res0);
-! if (error)
-! msg_panic("%s: getaddrinfo(\"%s\", NULL, "
-! "{AF_INET,SOCK_STREAM,AI_NUMERICHOST}, "
-! "&res0): %s", myname, state->addr,
-! GAI_STRERROR(error));
-! memcpy((char *)sa, res0->ai_addr, res0->ai_addrlen);
-! } else {
-! state->addr = mystrdup(abuf);
-! }
-!
-! /*
-! * RFC 2821 section 4.1.3: IPv6 address literals in SMTP
-! * mail headers are prepended with tag 'IPv6' and a colon.
-! */
-! if (sa->sa_family == AF_INET6)
-! state->addr_tag = "IPv6:";
-!
-! error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
-! #else
-! in = &((struct sockaddr_in *)sa)->sin_addr;
-! state->addr = mystrdup(abuf);
-! inet_ntop(AF_INET, in, abuf, sizeof(abuf));
-! 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
-+ if (error != EAI_NONAME)
-+ msg_warn("%s: getnameinfo(%s,,,,,,NI_NAMEREQD) error %s",
-+ myname, abuf, GAI_STRERROR(error));
-+ /*
-+ * XXX: There are other error codes from GAI that should
-+ * result in only a temporary error code from this daemon.
-+ * This also applies to get{addr,name}info() results
-+ * below.
-+ */
-+ state->peer_code = (error == EAI_AGAIN ? 4 : 5);
-+ #else
- state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
-! #endif
-! } else if (valid_hostaddr(hbuf, DONT_GRIPE)) {
- msg_warn("numeric result %s in address->name lookup for %s",
-! hbuf, state->addr);
- state->name = mystrdup("unknown");
- state->peer_code = 5;
-! } else if (!valid_hostname(hbuf, DONT_GRIPE)) {
- state->name = mystrdup("unknown");
- state->peer_code = 5;
- } else {
-! state->name = mystrdup(hbuf);
- state->peer_code = 2;
-
- /*
-***************
-*** 160,175 ****
- state->peer_code = code; \
- }
-
-! 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)) {
- msg_warn("%s: hostname %s verification failed: bad address size %d",
- state->addr, state->name, hp->h_length);
- REJECT_PEER_NAME(state, 5);
- } else {
- for (i = 0; /* void */ ; i++) {
- if (hp->h_addr_list[i] == 0) {
- msg_warn("%s: address not listed for hostname %s",
---- 255,307 ----
- 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, &res0);
-! if (error) {
-! msg_warn("%s: %s: hostname %s verification failed: %s",
-! myname, state->addr, state->name,
-! GAI_STRERROR(error));
-! REJECT_PEER_NAME(state, (error == EAI_AGAIN ? 4 : 5));
-! } else {
-! for (res = res0; res; res = res->ai_next) {
-! if (res->ai_family != sa->sa_family)
-! continue;
-! error = getnameinfo(res->ai_addr, res->ai_addrlen,
-! rabuf, sizeof(rabuf), NULL, 0,
-! NI_NUMERICHOST | NI_WITHSCOPEID);
-! if (error) {
-! msg_warn("%s: %s: hostname %s verification failed: %s",
-! myname, state->addr, state->name,
-! GAI_STRERROR(error));
-! REJECT_PEER_NAME(state, 4);
-! break;
-! }
-! if (strcmp(state->addr, rabuf) == 0)
-! break; /* keep peer name */
-! }
-! if (res == NULL) {
-! msg_warn("%s: %s: address not listed for hostname %s",
-! myname, state->addr, state->name);
-! REJECT_PEER_NAME(state, 5);
-! }
-! }
-! if (res0)
-! freeaddrinfo(res0);
-! #else
-! hp = gethostbyname(state->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(*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",
-***************
-*** 177,188 ****
- REJECT_PEER_NAME(state, 5);
- break;
- }
-! if (memcmp(hp->h_addr_list[i],
-! (char *) &sin.sin_addr,
-! sizeof(sin.sin_addr)) == 0)
- break; /* keep peer name */
- }
- }
- }
- }
-
---- 309,319 ----
- REJECT_PEER_NAME(state, 5);
- break;
- }
-! if (memcmp(hp->h_addr_list[i], (char *)in, sizeof(*in)) == 0)
- break; /* keep peer name */
- }
- }
-+ #endif
- }
- }
-
-diff -Pcr postfix-2.0.16/src/smtpd/smtpd_sasl_glue.c postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_glue.c
-*** postfix-2.0.16/src/smtpd/smtpd_sasl_glue.c Mon Jan 27 15:06:14 2003
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_glue.c Mon Jan 5 16:58:08 2004
-***************
-*** 8,14 ****
- /*
- /* void smtpd_sasl_initialize()
- /*
-! /* void smtpd_sasl_connect(state)
- /* SMTPD_STATE *state;
- /*
- /* char *smtpd_sasl_authenticate(state, sasl_method, init_response)
---- 8,14 ----
- /*
- /* void smtpd_sasl_initialize()
- /*
-! /* void smtpd_sasl_connect(state, sasl_opts_name, sasl_opts_var)
- /* SMTPD_STATE *state;
- /*
- /* char *smtpd_sasl_authenticate(state, sasl_method, init_response)
-***************
-*** 32,38 ****
- /*
- /* smtpd_sasl_connect() performs per-connection initialization.
- /* This routine should be called once at the start of every
-! /* connection.
- /*
- /* smtpd_sasl_authenticate() implements the authentication dialog.
- /* The result is a null pointer in case of success, an SMTP reply
---- 32,40 ----
- /*
- /* smtpd_sasl_connect() performs per-connection initialization.
- /* This routine should be called once at the start of every
-! /* connection. The sasl_opts_name and sasl_opts_var parameters
-! /* are the postfix configuration parameters setting the security
-! /* policy of the SASL authentication.
- /*
- /* smtpd_sasl_authenticate() implements the authentication dialog.
- /* The result is a null pointer in case of success, an SMTP reply
-***************
-*** 201,208 ****
- 0,
- };
-
-- static int smtpd_sasl_opts;
--
- /* smtpd_sasl_initialize - per-process initialization */
-
- void smtpd_sasl_initialize(void)
---- 203,208 ----
-***************
-*** 214,229 ****
- if (sasl_server_init(callbacks, "smtpd") != SASL_OK)
- msg_fatal("SASL per-process initialization failed");
-
-- /*
-- * Configuration parameters.
-- */
-- smtpd_sasl_opts = name_mask(VAR_SMTPD_SASL_OPTS, smtpd_sasl_mask,
-- var_smtpd_sasl_opts);
- }
-
- /* smtpd_sasl_connect - per-connection initialization */
-
-! void smtpd_sasl_connect(SMTPD_STATE *state)
- {
- #if SASL_VERSION_MAJOR < 2
- unsigned sasl_mechanism_count;
---- 214,225 ----
- if (sasl_server_init(callbacks, "smtpd") != SASL_OK)
- msg_fatal("SASL per-process initialization failed");
-
- }
-
- /* smtpd_sasl_connect - per-connection initialization */
-
-! void smtpd_sasl_connect(SMTPD_STATE *state, const char *sasl_opts_name,
-! const char *sasl_opts_var)
- {
- #if SASL_VERSION_MAJOR < 2
- unsigned sasl_mechanism_count;
-***************
-*** 291,297 ****
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = smtpd_sasl_opts;
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
---- 287,294 ----
- sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
- * security layer */
-! sec_props.security_flags = name_mask(sasl_opts_name, smtpd_sasl_mask,
-! sasl_opts_var);
- sec_props.maxbufsize = 0;
- sec_props.property_names = 0;
- sec_props.property_values = 0;
-diff -Pcr postfix-2.0.16/src/smtpd/smtpd_sasl_glue.h postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_glue.h
-*** postfix-2.0.16/src/smtpd/smtpd_sasl_glue.h Mon Nov 26 01:12:28 2001
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_glue.h Mon Jan 5 16:58:08 2004
-***************
-*** 12,18 ****
- * SASL protocol interface
- */
- extern void smtpd_sasl_initialize(void);
-! extern void smtpd_sasl_connect(SMTPD_STATE *);
- extern void smtpd_sasl_disconnect(SMTPD_STATE *);
- extern char *smtpd_sasl_authenticate(SMTPD_STATE *, const char *, const char *);
- extern void smtpd_sasl_logout(SMTPD_STATE *);
---- 12,18 ----
- * SASL protocol interface
- */
- extern void smtpd_sasl_initialize(void);
-! extern void smtpd_sasl_connect(SMTPD_STATE *, const char *, const char *);
- extern void smtpd_sasl_disconnect(SMTPD_STATE *);
- extern char *smtpd_sasl_authenticate(SMTPD_STATE *, const char *, const char *);
- extern void smtpd_sasl_logout(SMTPD_STATE *);
-diff -Pcr postfix-2.0.16/src/smtpd/smtpd_sasl_proto.c postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_proto.c
-*** postfix-2.0.16/src/smtpd/smtpd_sasl_proto.c Tue Sep 12 00:45:40 2000
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_sasl_proto.c Mon Jan 5 16:58:08 2004
-***************
-*** 128,133 ****
---- 128,140 ----
- smtpd_chat_reply(state, "503 Error: authentication not enabled");
- return (-1);
- }
-+ #ifdef USE_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 -Pcr postfix-2.0.16/src/smtpd/smtpd_state.c postfix-2.0.16-ti1.20/src/smtpd/smtpd_state.c
-*** postfix-2.0.16/src/smtpd/smtpd_state.c Wed Mar 19 16:39:13 2003
---- postfix-2.0.16-ti1.20/src/smtpd/smtpd_state.c Mon Jan 5 16:58:08 2004
-***************
-*** 77,82 ****
---- 77,83 ----
- state->notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
- var_notify_classes);
- state->helo_name = 0;
-+ state->addr_tag = "";
- state->queue_id = 0;
- state->cleanup = 0;
- state->dest = 0;
-***************
-*** 99,110 ****
- state->defer_if_permit.reason = 0;
- state->discard = 0;
- state->expand_buf = 0;
-
- #ifdef USE_SASL_AUTH
- if (SMTPD_STAND_ALONE(state))
- var_smtpd_sasl_enable = 0;
- if (var_smtpd_sasl_enable)
-! smtpd_sasl_connect(state);
- #endif
-
- /*
---- 100,116 ----
- state->defer_if_permit.reason = 0;
- state->discard = 0;
- state->expand_buf = 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))
- var_smtpd_sasl_enable = 0;
- if (var_smtpd_sasl_enable)
-! smtpd_sasl_connect(state, VAR_SMTPD_SASL_OPTS, var_smtpd_sasl_opts);
- #endif
-
- /*
-diff -Pcr postfix-2.0.16/src/smtpstone/qmqp-sink.c postfix-2.0.16-ti1.20/src/smtpstone/qmqp-sink.c
-*** postfix-2.0.16/src/smtpstone/qmqp-sink.c Mon Jul 9 23:53:51 2001
---- postfix-2.0.16-ti1.20/src/smtpstone/qmqp-sink.c Mon Jan 5 16:58:08 2004
-***************
-*** 275,281 ****
- } else {
- if (strncmp(argv[optind], "inet:", 5) == 0)
- argv[optind] += 5;
-! sock = inet_listen(argv[optind], backlog, BLOCKING);
- }
-
- /*
---- 275,281 ----
- } else {
- if (strncmp(argv[optind], "inet:", 5) == 0)
- argv[optind] += 5;
-! sock = inet_listen(argv[optind], backlog, BLOCKING, 1);
- }
-
- /*
-diff -Pcr postfix-2.0.16/src/smtpstone/smtp-sink.c postfix-2.0.16-ti1.20/src/smtpstone/smtp-sink.c
-*** postfix-2.0.16/src/smtpstone/smtp-sink.c Sat Sep 13 02:46:56 2003
---- postfix-2.0.16-ti1.20/src/smtpstone/smtp-sink.c Mon Jan 5 16:58:08 2004
-***************
-*** 607,613 ****
- } else {
- if (strncmp(argv[optind], "inet:", 5) == 0)
- argv[optind] += 5;
-! sock = inet_listen(argv[optind], backlog, BLOCKING);
- }
-
- /*
---- 607,613 ----
- } else {
- if (strncmp(argv[optind], "inet:", 5) == 0)
- argv[optind] += 5;
-! sock = inet_listen(argv[optind], backlog, BLOCKING, 1);
- }
-
- /*
-diff -Pcr postfix-2.0.16/src/tlsmgr/Makefile.in postfix-2.0.16-ti1.20/src/tlsmgr/Makefile.in
-*** postfix-2.0.16/src/tlsmgr/Makefile.in Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/tlsmgr/Makefile.in Mon Jan 5 16:58:08 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/tlsmgr/tlsmgr.c postfix-2.0.16-ti1.20/src/tlsmgr/tlsmgr.c
-*** postfix-2.0.16/src/tlsmgr/tlsmgr.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/tlsmgr/tlsmgr.c Mon Jan 5 16:58:08 2004
-***************
-*** 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 USE_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 USE_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 USE_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 USE_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 USE_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 USE_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 -Pcr postfix-2.0.16/src/util/Makefile.in postfix-2.0.16-ti1.20/src/util/Makefile.in
-*** postfix-2.0.16/src/util/Makefile.in Sun Sep 14 02:03:54 2003
---- postfix-2.0.16-ti1.20/src/util/Makefile.in Mon Jan 5 16:58:08 2004
-***************
-*** 8,14 ****
- 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 \
- 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 \
---- 8,14 ----
- 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 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,32 ****
- 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 host_port.c sane_connect.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 \
---- 26,33 ----
- 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 host_port.c sane_connect.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,42 ****
- 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 \
- 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 \
---- 37,43 ----
- 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 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,66 ****
- 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 host_port.o sane_connect.o $(STRCASE)
- 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 \
- 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 \
---- 55,68 ----
- 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 host_port.o sane_connect.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 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,78 ****
- 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 host_port.h sane_connect.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 \
---- 74,81 ----
- 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 host_port.h sane_connect.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 \
-***************
-*** 609,614 ****
---- 612,618 ----
- 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
-***************
-*** 758,763 ****
---- 762,768 ----
- 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
-***************
-*** 884,889 ****
---- 889,895 ----
- 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
-***************
-*** 1277,1279 ****
---- 1283,1291 ----
- 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 -Pcr postfix-2.0.16/src/util/dict_open.c postfix-2.0.16-ti1.20/src/util/dict_open.c
-*** postfix-2.0.16/src/util/dict_open.c Sun Jan 5 02:07:25 2003
---- postfix-2.0.16-ti1.20/src/util/dict_open.c Mon Jan 5 16:58:09 2004
-***************
-*** 167,172 ****
---- 167,173 ----
- #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>
-***************
-*** 195,200 ****
---- 196,202 ----
- #if 0
- DICT_TYPE_TCP, dict_tcp_open,
- #endif
-+ "sdbm", dict_sdbm_open,
- #ifdef HAS_DBM
- DICT_TYPE_DBM, dict_dbm_open,
- #endif
-diff -Pcr postfix-2.0.16/src/util/dict_sdbm.c postfix-2.0.16-ti1.20/src/util/dict_sdbm.c
-*** postfix-2.0.16/src/util/dict_sdbm.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/dict_sdbm.c Mon Jan 5 16:58:09 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/util/dict_sdbm.h postfix-2.0.16-ti1.20/src/util/dict_sdbm.h
-*** postfix-2.0.16/src/util/dict_sdbm.h Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/dict_sdbm.h Mon Jan 5 16:58:09 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/util/get_port.c postfix-2.0.16-ti1.20/src/util/get_port.c
-*** postfix-2.0.16/src/util/get_port.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/get_port.c Mon Jan 5 16:58:09 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/util/get_port.h postfix-2.0.16-ti1.20/src/util/get_port.h
-*** postfix-2.0.16/src/util/get_port.h Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/get_port.h Mon Jan 5 16:58:09 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/util/inet_addr_host.c postfix-2.0.16-ti1.20/src/util/inet_addr_host.c
-*** postfix-2.0.16/src/util/inet_addr_host.c Fri Dec 11 19:55:35 1998
---- postfix-2.0.16-ti1.20/src/util/inet_addr_host.c Mon Jan 5 16:58:09 2004
-***************
-*** 38,44 ****
---- 38,47 ----
- #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
-***************
-*** 46,62 ****
---- 49,116 ----
-
- /* Utility library. */
-
-+ #include <mymalloc.h>
- #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;
-+ int error;
-+ char *hbuf, *hname;
-+ #else
- struct hostent *hp;
- struct in_addr addr;
-+ #endif
- int initial_count = addr_list->used;
-
-+ #ifdef INET6
-+
-+ /*
-+ * The use of square brackets around an IPv6 addresses is
-+ * required, even though we don't enforce it as it'd make
-+ * the code unnecessarily complicated.
-+ */
-+ hbuf = mystrdup(hostname);
-+ if (*hbuf == '[' && hbuf[strlen(hbuf) - 1] == ']') {
-+ hbuf[strlen(hbuf) - 1] = '\0';
-+ hname = hbuf + 1;
-+ } else {
-+ hname = hbuf;
-+ }
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ error = getaddrinfo(hname, 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
-+ * XXX is this socket necessary? --dean
-+ */
-+ s = socket(res->ai_family, SOCK_DGRAM, 0);
-+ if (s < 0)
-+ continue;
-+ if (close(s))
-+ msg_warn("inet_addr_host: close(): %m");
-+
-+ inet_addr_list_append(addr_list, res->ai_addr);
-+ }
-+ freeaddrinfo(res0);
-+ }
-+ myfree(hbuf);
-+ #else
- if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
- inet_addr_list_append(addr_list, &addr);
- } else {
-***************
-*** 65,73 ****
---- 119,130 ----
- 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,83 ****
---- 135,142 ----
- {
- INET_ADDR_LIST addr_list;
- int i;
-+ struct sockaddr *sa;
-+ char hbuf[NI_MAXHOST];
-
- msg_vstream_init(argv[0], VSTREAM_ERR);
-
-***************
-*** 89,96 ****
- 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]));
- vstream_fflush(VSTREAM_OUT);
- }
- inet_addr_list_free(&addr_list);
---- 148,159 ----
- if (inet_addr_host(&addr_list, *argv) == 0)
- msg_fatal("not found: %s", *argv);
-
-! 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 -Pcr postfix-2.0.16/src/util/inet_addr_list.c postfix-2.0.16-ti1.20/src/util/inet_addr_list.c
-*** postfix-2.0.16/src/util/inet_addr_list.c Tue Jul 31 20:13:41 2001
---- postfix-2.0.16-ti1.20/src/util/inet_addr_list.c Mon Jan 5 16:58:09 2004
-***************
-*** 51,56 ****
---- 51,63 ----
- #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,74 ****
---- 70,108 ----
- {
- 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,97 ****
---- 117,150 ----
- 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
-+ char ha[NI_MAXHOST], hb[NI_MAXHOST];
-+ int nierr;
-+ int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
-+ struct sockaddr *sa, *sb;
-+
-+ sa = (struct sockaddr *)a, sb = (struct sockaddr *)b;
-+ if (sa->sa_family != sb->sa_family)
-+ return (sa->sa_family - sb->sa_family);
-+ nierr = getnameinfo(sa, SA_LEN(sa), ha, sizeof(ha), NULL, 0, niflags);
-+ if (nierr)
-+ msg_fatal("inet_addr_list_comp: getnameinfo(ha) error %d", nierr);
-+ nierr = getnameinfo(sb, SA_LEN(sb), hb, sizeof(hb), NULL, 0, niflags);
-+ if (nierr)
-+ msg_fatal("inet_addr_list_comp: getnameinfo(hb) error %d", nierr);
-+ return strcmp(ha, hb);
-+ #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 */
-***************
-*** 136,142 ****
- */
- #include <inet_addr_host.h>
-
-! static void inet_addr_list_print(INET_ADDR_LIST *list)
- {
- int n;
-
---- 189,197 ----
- */
- #include <inet_addr_host.h>
-
-! #ifndef DEBUG6
-! static
-! #endif void inet_addr_list_print(INET_ADDR_LIST *list)
- {
- int n;
-
-diff -Pcr postfix-2.0.16/src/util/inet_addr_list.h postfix-2.0.16-ti1.20/src/util/inet_addr_list.h
-*** postfix-2.0.16/src/util/inet_addr_list.h Tue Jul 31 19:56:47 2001
---- postfix-2.0.16-ti1.20/src/util/inet_addr_list.h Mon Jan 5 16:58:09 2004
-***************
-*** 16,34 ****
---- 16,70 ----
- */
- #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
-+
-+ /*
-+ * NI_WITHSCOPEID is defined on most systems, but usually not implemented.
-+ * Only on KAME? Use without implementation will result in EAI_BADFLAGS.
-+ */
-+ #ifdef INET6
-+ # ifndef INET6_KAME
-+ # ifdef NI_WITHSCOPEID
-+ # undef NI_WITHSCOPEID
-+ # endif
-+ # define NI_WITHSCOPEID 0
-+ # endif
-+ #endif
-
- /* LICENSE
- /* .ad
-diff -Pcr postfix-2.0.16/src/util/inet_addr_local.c postfix-2.0.16-ti1.20/src/util/inet_addr_local.c
-*** postfix-2.0.16/src/util/inet_addr_local.c Sun Feb 25 19:20:19 2001
---- postfix-2.0.16-ti1.20/src/util/inet_addr_local.c Mon Jan 5 16:58:09 2004
-***************
-*** 30,35 ****
---- 30,42 ----
- /* IBM T.J. Watson Research
- /* P.O. Box 704
- /* Yorktown Heights, NY 10598, USA
-+ /*
-+ /* Dean C. Strik
-+ /* Department ICT Services
-+ /* Eindhoven University of Technology
-+ /* P.O. Box 513
-+ /* 5600 MB Eindhoven, Netherlands
-+ /* E-mail: <dean@ipnet6.org>
- /*--*/
-
- /* System library. */
-***************
-*** 47,52 ****
---- 54,66 ----
- #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. */
-
-***************
-*** 59,95 ****
- /*
- * Support for variable-length addresses.
- */
- #ifdef _SIZEOF_ADDR_IFREQ
- #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
- ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
- #define IFREQ_SIZE(ifr) _SIZEOF_ADDR_IFREQ(*ifr)
-! #else
- #ifdef HAS_SA_LEN
- #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
- ((char *) ifr + sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len))
- #define IFREQ_SIZE(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
-! #else
- #define NEXT_INTERFACE(ifr) (ifr + 1)
- #define IFREQ_SIZE(ifr) sizeof(ifr[0])
-! #endif
-! #endif
-
- /* inet_addr_local - find all IP addresses for this host */
-
- int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
- {
- char *myname = "inet_addr_local";
-- struct ifconf ifc;
-- struct ifreq *ifr;
-- struct ifreq *the_end;
- int sock;
-! VSTRING *buf = vstring_alloc(1024);
- int initial_count = addr_list->used;
- struct in_addr addr;
- struct ifreq *ifr_mask;
-
-! if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
- msg_fatal("%s: socket: %m", myname);
-
- /*
- * Get the network interface list. XXX The socket API appears to have no
---- 73,242 ----
- /*
- * Support for variable-length addresses.
- */
-+ #ifdef HAS_SIOCGLIF
-+ #define NEXT_INTERFACE(lifr) (lifr + 1)
-+ #define LIFREQ_SIZE(lifr) sizeof(lifr[0])
-+ #else /* HAS_SIOCGLIF */
- #ifdef _SIZEOF_ADDR_IFREQ
- #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
- ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
- #define IFREQ_SIZE(ifr) _SIZEOF_ADDR_IFREQ(*ifr)
-! #else /* _SIZEOF_ADDR_IFREQ */
- #ifdef HAS_SA_LEN
- #define NEXT_INTERFACE(ifr) ((struct ifreq *) \
- ((char *) ifr + sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len))
- #define IFREQ_SIZE(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
-! #else /* HAS_SA_LEN */
- #define NEXT_INTERFACE(ifr) (ifr + 1)
- #define IFREQ_SIZE(ifr) sizeof(ifr[0])
-! #endif /* HAS_SA_LEN */
-! #endif /* _SIZEOF_ADDR_IFREQ */
-! #endif /* HAS_SIOCGLIF */
-
- /* inet_addr_local - find all IP addresses for this host */
-
- 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(*(u_int16_t *)
-+ &addr6.sin6_addr.s6_addr[2]);
-+ 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) {
-+ /*
-+ * Unfortunately, sa_len/sa_family may be broken in
-+ * the netmask sockaddr structure. We must fix this
-+ * manually to have correct addresses. --dcs
-+ */
-+ #ifdef HAS_SA_LEN
-+ sam->sa_len = sa->sa_family == AF_INET6 ?
-+ sizeof(struct sockaddr_in6) :
-+ sizeof(struct sockaddr_in);
-+ #endif
-+ sam->sa_family = sa->sa_family;
-+ 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 /* GETIFADDRS */
-+
-+ /*
-+ * IF IPV6 SUPPORT IS ENABLED:
-+ *
-+ * In the non-getifaddrs() version, we determine the interface addresses
-+ * using the SIOCG(L)IFCONF. However, it is operating system dependent
-+ * whether this also results in IPv6 addresses configuration. Another
-+ * issue is that there is no good method to determine the netmask /
-+ * prefixlen for IPv6 addresses.
-+ * We will therefore use OS dependent methods. An overview:
-+ * - Use SIOCGLIFCONF when available -> this supports both IPv4/IPv6
-+ * addresses. Also, with SIOCGLIFNETMASK we can obtain the netmask /
-+ * prefixlen for either address family.
-+ * - On Linux, read IPv6 addresses / prefixlengths from a file in the
-+ * /proc filesystem. Linux does not return IPv6 addresses in
-+ * SIOCGIFCONF.
-+ * - On other systems without getifaddrs(), we expect SIOCGIFCONF
-+ * to return IPv6 addresses. Since SIOCGIFNETMASK does not work for
-+ * IPv6 addresses, we will always set the prefixlen to 64 (subnet)
-+ * However, it is suggested you set the mynetworks variable(s)
-+ * manually then.
-+ * XXX: We duplicate some code. In this case, I think this is better
-+ * than really drowning in the #ifdefs...
-+ * -- Dean Strik (dcs)
-+ */
-+
- char *myname = "inet_addr_local";
- int sock;
-! VSTRING *buf;
- int initial_count = addr_list->used;
-+ int af = AF_INET;
-+ #if defined(INET6) && defined(HAS_SIOCGLIF)
-+ struct lifconf lifc;
-+ struct lifreq *lifr;
-+ struct lifreq *lifr_mask;
-+ struct lifreq *the_end;
-+ #else
- struct in_addr addr;
-+ struct ifconf ifc;
-+ struct ifreq *ifr;
- struct ifreq *ifr_mask;
-+ struct ifreq *the_end;
-+ #endif
-+ #if defined(INET6) && defined(HAS_PROCNET_IFINET6)
-+ FILE *f;
-+ char addr6p[8][5], addr6res[40], devname[20];
-+ int plen, scope, dad_status, if_idx, gaierror;
-+ struct addrinfo hints, *res, *res0;
-+ #endif
-+ #ifdef INET6
-+ struct sockaddr_in6 addr6;
-+
-+ 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;
-! }
-! #endif
- msg_fatal("%s: socket: %m", myname);
-+ }
-
- /*
- * Get the network interface list. XXX The socket API appears to have no
-***************
-*** 106,111 ****
---- 253,272 ----
- * that the program can run out of memory due to a non-memory problem,
- * making it more difficult than necessary to diagnose the real problem.
- */
-+ #ifdef HAS_SIOCGLIF
-+ for (;;) {
-+ memset(&lifc, 0, sizeof(lifc));
-+ lifc.lifc_family = AF_UNSPEC;
-+ lifc.lifc_len = vstring_avail(buf);
-+ lifc.lifc_buf = vstring_str(buf);
-+ if (ioctl(sock, SIOCGLIFCONF, (char *) &lifc) < 0) {
-+ if (errno != EINVAL)
-+ msg_fatal("%s: ioctl SIOCGLIFCONF: %m", myname);
-+ } else if (lifc.lifc_len < vstring_avail(buf) / 2)
-+ break;
-+ VSTRING_SPACE(buf, vstring_avail(buf) * 2);
-+ }
-+ #else
- for (;;) {
- ifc.ifc_len = vstring_avail(buf);
- ifc.ifc_buf = vstring_str(buf);
-***************
-*** 116,121 ****
---- 277,283 ----
- break;
- VSTRING_SPACE(buf, vstring_avail(buf) * 2);
- }
-+ #endif
-
- /*
- * Get the address of each IP network interface. According to BIND we
-***************
-*** 124,155 ****
- * Having no way to verify this claim on every machine, I will give them
- * the benefit of the doubt.
- */
- 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 */
- addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
-! if (addr.s_addr != INADDR_ANY) { /* has IP address */
- inet_addr_list_append(addr_list, &addr);
- if (mask_list) {
- ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
- memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
- if (ioctl(sock, SIOCGIFNETMASK, ifr_mask) < 0)
- msg_fatal("%s: ioctl SIOCGIFNETMASK: %m", myname);
-! addr = ((struct sockaddr_in *) & ifr_mask->ifr_addr)->sin_addr;
- inet_addr_list_append(mask_list, &addr);
- myfree((char *) ifr_mask);
- }
- }
- }
- ifr = NEXT_INTERFACE(ifr);
- }
- vstring_free(buf);
- (void) close(sock);
- return (addr_list->used - initial_count);
- }
-
- #ifdef TEST
-
- #include <vstream.h>
- #include <msg_vstream.h>
-
---- 286,477 ----
- * Having no way to verify this claim on every machine, I will give them
- * the benefit of the doubt.
- */
-+
-+ #if defined(INET6) && defined(HAS_SIOCGLIF)
-+ the_end = (struct lifreq *) (lifc.lifc_buf + lifc.lifc_len);
-+ for (lifr = lifc.lifc_req; lifr < the_end;) {
-+ if (((struct sockaddr *)&lifr->lifr_addr)->sa_family != af) {
-+ lifr = NEXT_INTERFACE(lifr);
-+ continue;
-+ }
-+ if (af == AF_INET) {
-+ if (((struct sockaddr_in *)&lifr->lifr_addr)->sin_addr.s_addr
-+ == INADDR_ANY) {
-+ lifr = NEXT_INTERFACE(lifr);
-+ continue;
-+ }
-+ } else if (af == AF_INET6) {
-+ addr6 = *(struct sockaddr_in6 *)&lifr->lifr_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(*(u_int16_t *)
-+ &addr6.sin6_addr.s6_addr[2]);
-+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
-+ }
-+ #endif
-+ if (IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr)) {
-+ lifr = NEXT_INTERFACE(lifr);
-+ continue;
-+ }
-+ }
-+ inet_addr_list_append(addr_list, (struct sockaddr *)&lifr->lifr_addr);
-+ if (mask_list) {
-+ lifr_mask = (struct lifreq *) mymalloc(sizeof(struct lifreq));
-+ memcpy((char *)lifr_mask, (char *)lifr, sizeof(struct lifreq));
-+ if (ioctl(sock, SIOCGLIFNETMASK, lifr_mask) < 0)
-+ msg_fatal("%s: ioctl(SIOCGLIFNETMASK): %m", myname);
-+ /* XXX: Check whether sa_len/family are honoured --dcs */
-+ inet_addr_list_append(mask_list,
-+ (struct sockaddr *)&lifr_mask->lifr_addr);
-+ myfree((char *)lifr_mask);
-+ }
-+ lifr = NEXT_INTERFACE(lifr);
-+ }
-+
-+ #else /* INET6 && SIOCGLIF */
- 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) {
-! ifr = NEXT_INTERFACE(ifr);
-! continue;
-! }
-! if (af == AF_INET) {
- addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
-! if (addr.s_addr != INADDR_ANY) {
-! #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));
- if (ioctl(sock, SIOCGIFNETMASK, ifr_mask) < 0)
- msg_fatal("%s: ioctl SIOCGIFNETMASK: %m", myname);
-! #ifdef INET6
-! /*
-! * Note that this SIOCGIFNETMASK has truly screwed up
-! * the contents of sa_len/sa_family. We must fix this
-! * manually to have correct addresses. --dcs
-! */
-! #ifdef HAS_SA_LEN
-! ifr_mask->ifr_addr.sa_len = sizeof(struct sockaddr_in);
-! #endif
-! ifr_mask->ifr_addr.sa_family = af;
-! inet_addr_list_append(mask_list, &ifr_mask->ifr_addr);
-! #else
-! addr = ((struct sockaddr_in *) &ifr_mask->ifr_addr)->sin_addr;
- inet_addr_list_append(mask_list, &addr);
-+ #endif
- myfree((char *) ifr_mask);
- }
- }
- }
-+ #if defined(INET6) && !defined(HAS_PROCNET_IFINET6)
-+ else if (af == AF_INET6) {
-+ /* This isn't clean on alpha --dcs */
-+ 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(*(u_int16_t *)
-+ &addr6.sin6_addr.s6_addr[2]);
-+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
-+ }
-+ #endif /* KAME */
-+ if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr))) {
-+ inet_addr_list_append(addr_list, (struct sockaddr *)&addr6);
-+ if (mask_list) {
-+ /* We can't know, and assume /64 for everything */
-+ struct sockaddr_in6 mask6;
-+ struct in6_addr *maddr6;
-+ memcpy((char *)&mask6, (char *)&addr6,
-+ sizeof(struct sockaddr_in6));
-+ maddr6 = &mask6.sin6_addr;
-+ maddr6->s6_addr[0] = maddr6->s6_addr[1] =
-+ maddr6->s6_addr[2] = maddr6->s6_addr[3] =
-+ maddr6->s6_addr[4] = maddr6->s6_addr[5] =
-+ maddr6->s6_addr[6] = maddr6->s6_addr[7] = 0xff;
-+ maddr6->s6_addr[8] = maddr6->s6_addr[9] =
-+ maddr6->s6_addr[10] = maddr6->s6_addr[11] =
-+ maddr6->s6_addr[12] = maddr6->s6_addr[13] =
-+ maddr6->s6_addr[14] = maddr6->s6_addr[15] = 0x0;
-+ inet_addr_list_append(mask_list, (struct sockaddr *)&mask6);
-+ }
-+ }
-+ }
-+ #endif /* INET6 && !HAS_PROCNET_IFINET6 */
- ifr = NEXT_INTERFACE(ifr);
- }
-+ #endif /* INET6 && SIOCGLIF */
- vstring_free(buf);
- (void) close(sock);
-+
-+ #ifdef INET6
-+ end:
-+ #ifndef HAS_PROCNET_IFINET6
-+ if (af != AF_INET6) {
-+ af = AF_INET6;
-+ goto other_socket_type;
-+ }
-+ #else /* !HAS_PROCNET_IFINET6 */
-+ 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_INET6;
-+ hints.ai_socktype = SOCK_DGRAM;
-+ gaierror = getaddrinfo(addr6res, NULL, &hints, &res0);
-+ if (!gaierror) {
-+ for (res = res0; res; res = res->ai_next) {
-+ struct sockaddr_in6 mask;
-+ int i, rest;
-+ inet_addr_list_append(addr_list, res->ai_addr);
-+ memcpy((char *)&mask, res->ai_addr, res->ai_addrlen);
-+ /* s6_addr32 is available on linux */
-+ mask.sin6_addr.s6_addr32[0] =
-+ mask.sin6_addr.s6_addr32[1] =
-+ mask.sin6_addr.s6_addr32[2] =
-+ mask.sin6_addr.s6_addr32[3] = ~0;
-+ for (i = 3, rest = 128 - plen; i > -1; i--)
-+ if (rest > 31) {
-+ mask.sin6_addr.s6_addr32[i] = htonl(0);
-+ rest -= 32;
-+ } else {
-+ mask.sin6_addr.s6_addr32[i] =
-+ htonl(~((1 << rest) - 1));
-+ break;
-+ }
-+ inet_addr_list_append(mask_list, &mask);
-+ }
-+ freeaddrinfo(res0);
-+ }
-+ }
-+ } else if (msg_verbose) {
-+ msg_warn("%s: Couldn't open " _PATH_PROCNET_IFINET6
-+ " for reading: %m", myname);
-+ }
-+ #endif /* !HAS_PROCNET_IFINET6 */
-+ #endif /* INET6 */
- return (addr_list->used - initial_count);
-+ #endif /* GETIFADDRS */
- }
-
- #ifdef TEST
-
-+ #include <string.h>
- #include <vstream.h>
- #include <msg_vstream.h>
-
-***************
-*** 158,163 ****
---- 480,487 ----
- 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,179 ****
- 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]));
- }
- vstream_fflush(VSTREAM_OUT);
- inet_addr_list_free(&addr_list);
---- 496,512 ----
- msg_warn("found only one active network interface");
-
- for (i = 0; i < addr_list.used; 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 -Pcr postfix-2.0.16/src/util/inet_connect.c postfix-2.0.16-ti1.20/src/util/inet_connect.c
-*** postfix-2.0.16/src/util/inet_connect.c Sat Sep 13 03:04:12 2003
---- postfix-2.0.16-ti1.20/src/util/inet_connect.c Mon Jan 5 16:58:09 2004
-***************
-*** 55,60 ****
---- 55,63 ----
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
-+ #ifdef INET6
-+ #include <netdb.h>
-+ #endif
-
- /* Utility library. */
-
-***************
-*** 74,80 ****
---- 77,88 ----
- char *buf;
- char *host;
- char *port;
-+ #ifdef INET6
-+ struct addrinfo hints, *res, *res0;
-+ int error;
-+ #else
- struct sockaddr_in sin;
-+ #endif
- int sock;
-
- /*
-***************
-*** 82,95 ****
---- 90,147 ----
- * 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.
- */
-***************
-*** 122,125 ****
---- 174,178 ----
- }
- return (sock);
- }
-+ #endif
- }
-diff -Pcr postfix-2.0.16/src/util/inet_listen.c postfix-2.0.16-ti1.20/src/util/inet_listen.c
-*** postfix-2.0.16/src/util/inet_listen.c Sat Sep 13 01:50:50 2003
---- postfix-2.0.16-ti1.20/src/util/inet_listen.c Mon Jan 5 16:58:09 2004
-***************
-*** 6,12 ****
- /* SYNOPSIS
- /* #include <listen.h>
- /*
-! /* int inet_listen(addr, backlog, block_mode)
- /* const char *addr;
- /* int backlog;
- /* int block_mode;
---- 6,12 ----
- /* SYNOPSIS
- /* #include <listen.h>
- /*
-! /* int inet_listen(addr, backlog, block_mode, addinuse_fatal)
- /* const char *addr;
- /* int backlog;
- /* int block_mode;
-***************
-*** 51,61 ****
---- 51,67 ----
- #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,111 ****
-
- /* inet_listen - create inet-domain listener */
-
-! int inet_listen(const char *addr, int backlog, int block_mode)
- {
- struct sockaddr_in sin;
- int sock;
- int t = 1;
- char *buf;
- char *host;
- char *port;
-
- /*
- * Translate address information to internal form.
- */
- buf = inet_parse(addr, &host, &port);
-! memset((char *) &sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- 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));
- non_blocking(sock, block_mode);
- if (listen(sock, backlog) < 0)
- msg_fatal("listen: %m");
---- 83,198 ----
-
- /* inet_listen - create inet-domain listener */
-
-! 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);
-! #ifdef INET6
-! memset(&hints, 0, sizeof(hints));
-! hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-! 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);
-
-! 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, res->ai_protocol)) < 0) {
-! cause = "socket";
-! continue;
-! }
-! #ifdef IPV6_V6ONLY
-! if (res->ai_family == AF_INET6 && setsockopt(sock,
-! IPPROTO_IPV6, IPV6_V6ONLY, (char *)&t, sizeof(t)) < 0) {
-! #ifdef DEBUG6
-! cause = "setsockopt(IPV6_V6ONLY)";
-! close(sock);
-! sock = -1;
-! continue;
-! #endif
-! ;
-! }
-! #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 -Pcr postfix-2.0.16/src/util/inet_util.c postfix-2.0.16-ti1.20/src/util/inet_util.c
-*** postfix-2.0.16/src/util/inet_util.c Fri Dec 11 19:55:34 1998
---- postfix-2.0.16-ti1.20/src/util/inet_util.c Mon Jan 5 16:58:09 2004
-***************
-*** 37,42 ****
---- 37,43 ----
- /* System libraries. */
-
- #include <sys_defs.h>
-+ #include <string.h>
-
- /* Utility library. */
-
-***************
-*** 48,61 ****
-
- char *inet_parse(const char *addr, char **hostp, char **portp)
- {
-! char *buf;
-!
-! buf = mystrdup(addr);
-! if ((*portp = split_at_right(buf, ':')) != 0) {
- *hostp = buf;
- } else {
- *portp = buf;
- *hostp = "";
- }
- return (buf);
- }
---- 49,74 ----
-
- char *inet_parse(const char *addr, char **hostp, char **portp)
- {
-! char *buf, *brk;
-! #ifdef INET6
-! if (*addr == '[') {
-! buf = mystrdup(addr + 1);
-! brk = strchr(buf, ']');
-! if (brk == NULL)
-! brk = buf;
-! } else
-! #endif
-! brk = buf = mystrdup(addr);
-! if ((*portp = split_at_right(brk, ':')) != 0) {
- *hostp = buf;
-+ #ifdef INET6
-+ if (brk > buf)
-+ *brk = '\0';
-+ #endif
- } else {
- *portp = buf;
- *hostp = "";
- }
- return (buf);
- }
-+
-diff -Pcr postfix-2.0.16/src/util/listen.h postfix-2.0.16-ti1.20/src/util/listen.h
-*** postfix-2.0.16/src/util/listen.h Mon Mar 22 02:57:11 1999
---- postfix-2.0.16-ti1.20/src/util/listen.h Mon Jan 5 16:58:09 2004
-***************
-*** 20,26 ****
- * Listener external interface.
- */
- extern int unix_listen(const char *, int, int);
-! extern int inet_listen(const char *, int, int);
- extern int fifo_listen(const char *, int, int);
- extern int stream_listen(const char *, int, int);
-
---- 20,26 ----
- * Listener external interface.
- */
- extern int unix_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 -Pcr postfix-2.0.16/src/util/match_list.c postfix-2.0.16-ti1.20/src/util/match_list.c
-*** postfix-2.0.16/src/util/match_list.c Tue Nov 20 21:07:15 2001
---- postfix-2.0.16-ti1.20/src/util/match_list.c Mon Jan 5 16:58:09 2004
-***************
-*** 118,124 ****
- 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 */
- for (cp = pattern; *cp == '!'; cp++)
- /* void */ ;
- if (dict_handle(pattern) == 0)
---- 118,124 ----
- 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) && (strchr(pattern, ':') != 0)) { /* type:table */
- for (cp = pattern; *cp == '!'; cp++)
- /* void */ ;
- if (dict_handle(pattern) == 0)
-diff -Pcr postfix-2.0.16/src/util/match_ops.c postfix-2.0.16-ti1.20/src/util/match_ops.c
-*** postfix-2.0.16/src/util/match_ops.c Mon Apr 14 16:44:19 2003
---- postfix-2.0.16-ti1.20/src/util/match_ops.c Mon Jan 5 16:58:09 2004
-***************
-*** 54,59 ****
---- 54,68 ----
- /* IBM T.J. Watson Research
- /* P.O. Box 704
- /* Yorktown Heights, NY 10598, USA
-+ /*
-+ /* Takahiro Igarashi
-+ /*
-+ /* Dean C. Strik
-+ /* Department ICT Services
-+ /* Eindhoven University of Technology
-+ /* P.O. Box 513
-+ /* 5600 MB Eindhoven, Netherlands
-+ /* E-mail: <dean@ipnet6.org>
- /*--*/
-
- /* System library. */
-***************
-*** 63,68 ****
---- 72,82 ----
- #include <arpa/inet.h>
- #include <string.h>
- #include <stdlib.h>
-+ #include <errno.h>
-+
-+ #ifdef INT_MAX_IN_LIMITS_H
-+ #include <limits.h>
-+ #endif
-
- #ifdef STRCASECMP_IN_STRINGS_H
- #include <strings.h>
-***************
-*** 75,86 ****
---- 89,133 ----
- /* Utility library. */
-
- #include <msg.h>
-+ #include <msg_output.h>
- #include <mymalloc.h>
- #include <split_at.h>
- #include <dict.h>
- #include <match_ops.h>
- #include <stringops.h>
-
-+ #define BITS_PER_ADDR_V4 32
-+ #define BITS_PER_ADDR_V6 128
-+
-+ #ifdef INET6
-+
-+ /*
-+ * IPv6-enabled code was written by Takahiro Igarashi and Dean Strik.
-+ * Earlier IPv6-enabled code was added by the PLD maintainers, but most
-+ * of it wasn't used anywhere and had a more restrictive license. I'm
-+ * glad to see it gone. --dean
-+ */
-+
-+ #endif /* INET6 */
-+
-+ #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>
-+
-+ /* prototypes */
-+ static PRINTFLIKE(2,3) void warning_msg(VSTRING *, const char *, ...);
-+ #ifdef INET6
-+ static int mask_comp(void *, void *, int);
-+ #endif /* INET6 */
-+
- /* match_string - match a string literal */
-
- int match_string(int unused_flags, const char *string, const char *pattern)
-***************
-*** 177,182 ****
---- 224,230 ----
- return (0);
- }
-
-+ #ifndef INET6
- /* match_parse_mask - parse net/mask pattern */
-
- static int match_parse_mask(const char *pattern, unsigned long *net_bits,
-***************
-*** 185,195 ****
- char *saved_pattern;
- char *mask;
-
-- #define BITS_PER_ADDR 32
--
- saved_pattern = mystrdup(pattern);
- if ((mask = split_at(saved_pattern, '/')) != 0) {
-! if ((*mask_shift = atoi(mask)) <= 0 || *mask_shift > BITS_PER_ADDR
- || (*net_bits = inet_addr(saved_pattern)) == INADDR_NONE) {
- msg_fatal("bad net/mask pattern: %s", pattern);
- }
---- 233,241 ----
- char *saved_pattern;
- char *mask;
-
- saved_pattern = mystrdup(pattern);
- if ((mask = split_at(saved_pattern, '/')) != 0) {
-! if ((*mask_shift = atoi(mask)) <= 0 || *mask_shift > BITS_PER_ADDR_V4
- || (*net_bits = inet_addr(saved_pattern)) == INADDR_NONE) {
- msg_fatal("bad net/mask pattern: %s", pattern);
- }
-***************
-*** 198,208 ****
---- 244,607 ----
- return (mask != 0);
- }
-
-+ #endif
-+
-+ static void PRINTFLIKE(2,3) warning_msg(VSTRING *vp, const char *fmt,...)
-+ {
-+ va_list ap;
-+ if (vp) {
-+ va_start(ap, fmt);
-+ vstring_vsprintf(vp, fmt, ap);
-+ va_end(ap);
-+ } else {
-+ va_start(ap, fmt);
-+ msg_vprintf(MSG_WARN, fmt, ap);
-+ va_end(ap);
-+ }
-+ }
-+
-+ /* v6addr_literal - copy IPv6 literal address from bracketed version */
-+ /* Supports both plain addresses and addr/plen's */
-+
-+ static char *v6addr_literal(const char *pattern)
-+ {
-+ size_t patlen;
-+ char *mypattern, *ptr;
-+
-+ if (pattern == NULL)
-+ msg_panic("v6_addr_literal: called with NULL pattern pointer");
-+ if (msg_verbose > 1)
-+ msg_info("v6addr_literal: input pattern %s", pattern);
-+
-+ patlen = strlen(pattern);
-+
-+ /*
-+ * Note that we allow two different presentation/configuration
-+ * formats for literal IPv6 (address/prefixlen) combinations.
-+ * These are [v6addr]/plen and [v6addr/plen]. The second should
-+ * be avoided and will be deprecated in later Postfix/v6 versions.
-+ */
-+ if (*pattern == '[') {
-+ mypattern = mystrdup(pattern + 1);
-+ if (pattern[patlen - 1] == ']') {
-+ /*
-+ * Format: "[v6addr]" or "[v6addr/plen]".
-+ */
-+ mypattern[patlen - 2] = '\0';
-+ } else if ((ptr = strchr(mypattern + 1, '/')) != NULL
-+ && *--ptr == ']') {
-+ /*
-+ * Format: "[v6addr]/plen".
-+ */
-+ while (*ptr)
-+ ptr++[0] = ptr[1];
-+ }
-+ } else {
-+ mypattern = mystrdup(pattern);
-+ }
-+
-+ if (msg_verbose > 1)
-+ msg_info("v6addr_literal: debracketed to %s", mypattern);
-+
-+ return (mypattern);
-+ }
-+
-+ /* std_addr_pattern - standardize address pattern */
-+
-+ /*
-+ * Note: Vanilla Postfix (without IPv6 support) does not allow the use of
-+ * the unspecified address in address patterns. The reason for this
-+ * is that INADDR_NONE is also returned in case of errors, so it's
-+ * hard to differentiate. However, with IPv6 routines, this problem
-+ * is gone. Also, it is useful to be able to use the IPv6 unspecified
-+ * address, since some features, like per-prefix-length lookups (128
-+ * lookups per address max!) and RBLs can be disabled for IPv6 by
-+ * just matching [::/0]. -- dean
-+ */
-+
-+ int std_addr_pattern(int flags, const char *pattern,
-+ ADDR_PATTERN **result, VSTRING *warnings)
-+ {
-+ char *myname = "std_addr_pattern";
-+ #ifdef INET6
-+ int pf;
-+ char *mypattern, *plenp;
-+ int bits_per_addr, mask, aierr;
-+ struct addrinfo hints, *res0;
-+ struct sockaddr_storage *ss_pattern;
-+ ADDR_PATTERN *res;
-+
-+ pf = PF_UNSPEC;
-+ *result = NULL;
-+
-+ if (pattern == NULL)
-+ msg_panic("%s: pattern may not be NULL!", myname);
-+
-+ /*
-+ * IPv6 addresses passed as pattern to match_hostaddr should start
-+ * with a bracket '[' and have a ']' closing. This is as specific
-+ * as it can get.
-+ */
-+ mypattern = v6addr_literal(pattern);
-+ if (*pattern == '[') {
-+ pf = PF_INET6;
-+ } else if (!(flags & (MATCH_FLAG_STRICT_ADDR|MATCH_FLAG_NOLOOKUP))) {
-+ /*
-+ * Return if we find what appears to be a maptype:file entry.
-+ * It's up to the caller of this function to handle this.
-+ */
-+ if (strchr(pattern, ':') != NULL) {
-+ myfree(mypattern);
-+ return (1);
-+ }
-+ }
-+ plenp = split_at(mypattern, '/');
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = pf;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_NUMERICHOST;
-+ aierr = getaddrinfo(mypattern, NULL, &hints, &res0);
-+ /*
-+ * EAI_NONAME happens when the pattern was not supplied in a
-+ * valid printable form. This is a non-fatal error in strict
-+ * address pattern maps like the CIDR dictionary.
-+ */
-+ if (aierr == EAI_NONAME) {
-+ if (msg_verbose || (flags & MATCH_FLAG_STRICT_ADDR))
-+ warning_msg(warnings,
-+ "%s: invalid address pattern \"%s\"",
-+ myname, mypattern);
-+ myfree(mypattern);
-+ return (0);
-+ }
-+ if (aierr != 0 && aierr != EAI_NONAME)
-+ msg_fatal("%s: getaddrinfo(%s): %s", myname, mypattern,
-+ GAI_STRERROR(aierr));
-+ pf = res0->ai_family;
-+ switch (pf) {
-+ case AF_INET:
-+ bits_per_addr = BITS_PER_ADDR_V4;
-+ break;
-+ case AF_INET6:
-+ bits_per_addr = BITS_PER_ADDR_V6;
-+ break;
-+ default:
-+ warning_msg(warnings,
-+ "%s: unsupported address family %d in lookup result "
-+ "of \"%s\"", myname, pf, pattern);
-+ freeaddrinfo(res0);
-+ myfree(mypattern);
-+ return (0);
-+ }
-+ ss_pattern = (struct sockaddr_storage *)
-+ mymalloc(sizeof(struct sockaddr_storage));
-+ memcpy(ss_pattern, (const void *)res0->ai_addr, res0->ai_addrlen);
-+ freeaddrinfo(res0);
-+
-+ if (plenp != NULL) {
-+ /*
-+ * Split the pattern into an address and a prefix length
-+ * We explicitly allow "/0"
-+ */
-+ if (strcmp(plenp, "0")) {
-+ mask = atoi(plenp);
-+ if (mask <= 0 || mask > bits_per_addr) {
-+ warning_msg(warnings, "%s: bad net/mask pattern: %s",
-+ myname, pattern);
-+ myfree(mypattern);
-+ myfree((char *)ss_pattern);
-+ return (0);
-+ }
-+ } else {
-+ mask = 0;
-+ }
-+ } else {
-+ /*
-+ * A single address is considered a prefix with maximum prefix length.
-+ */
-+ switch (pf) {
-+ case AF_INET:
-+ mask = BITS_PER_ADDR_V4;
-+ break;
-+ case AF_INET6:
-+ mask = BITS_PER_ADDR_V6;
-+ break;
-+ default:
-+ msg_panic("%s: address family %d should not occur here",
-+ myname, pf);
-+ }
-+ }
-+
-+ if (flags & MATCH_FLAG_NONNULL_HOST) {
-+ /*
-+ * We require that the host portion of (address/plen) pairs be zero
-+ * to reduce the impact of configuration errors.
-+ */
-+ int non_null = 0;
-+
-+ if (mask != 0 && mask != bits_per_addr) {
-+ int bytesl, bits;
-+ char *addr = NULL, ac;
-+
-+ switch (ss_pattern->ss_family) {
-+ case AF_INET6:
-+ addr = (char *)(&((struct sockaddr_in6 *)ss_pattern)->sin6_addr);
-+ bits_per_addr = BITS_PER_ADDR_V6;
-+ break;
-+ case AF_INET:
-+ addr = (char *)(&((struct sockaddr_in *)ss_pattern)->sin_addr);
-+ bits_per_addr = BITS_PER_ADDR_V4;
-+ break;
-+ default:
-+ msg_panic("%s: address family %d should not occur here",
-+ myname, pf);
-+ }
-+ bytesl = mask / 8;
-+ bits = (bits_per_addr - mask) % 8;
-+ if (bytesl == bits_per_addr / 8)
-+ non_null = 1;
-+ else
-+ ac = addr[bytesl];
-+ if (bits == 0)
-+ bits = 8;
-+ if (!non_null && ac != (ac & 0xff << bits))
-+ non_null = 1;
-+ while (!non_null && ++bytesl < bits_per_addr / 8)
-+ non_null = addr[bytesl] != 0;
-+ }
-+ if (non_null) {
-+ warning_msg(warnings,
-+ "%s: net/mask pattern \"%s/%s\" "
-+ "with non-null host pattern",
-+ myname, mypattern, plenp);
-+ return (0);
-+ }
-+ }
-+
-+ #else /* INET6 */
-+
-+ char *mypattern, *plenp;
-+ int bits;
-+ unsigned long addr, addr0;
-+ struct sockaddr_in *ss_pattern;
-+
-+ *result = NULL;
-+
-+ if (!(flags & MATCH_FLAG_STRICT_ADDR) && strchr(pattern, ':') != 0)
-+ return (1);
-+
-+ mypattern = mystrdup(pattern);
-+ plenp = split_at(pattern, '/');
-+ if (plenp == NULL) {
-+ bits = BITS_PER_ADDR_V4;
-+ } else {
-+ bits = atoi(plenp);
-+ if (bits <= 0 || bits > BITS_PER_ADDR_V4)
-+ warning_msg(warnings,
-+ "%s: bad net/mask pattern: %s",
-+ myname, pattern);
-+ myfree(mypattern);
-+ myfree((char *)ss_pattern);
-+ return (0);
-+ }
-+
-+ addr = inet_addr(mypattern);
-+ addr0 = htonl(0xffffffff << (BITS_PER_ADDR_V4 - bits));
-+ if ((flags & MATCH_FLAG_NONNULL_HOST) && (addr & ~addr0)) {
-+ warning_msg(warnings,
-+ "%s: net/mask pattern \"%s/%s\" with "
-+ "non-null host portion",
-+ myname, mypattern, plenp);
-+ return (0);
-+ }
-+
-+ /*
-+ * We make a sockaddr_in, but we don't use any of the fields
-+ * except the sin_addr member. Sockaddrs are used to create
-+ * an API that's closer to AF-independence.
-+ */
-+ ss_pattern = mymalloc(sizeof(struct sockaddr_in));
-+ memset(ss_pattern, 0, sizeof(*sin));
-+ ss_pattern->sin_family = AF_INET;
-+ ss_pattern->sin_addr = addr;
-+
-+ #endif /* INET6 */
-+
-+ res = addr_pattern_init();
-+ res->addr = (struct sockaddr *)ss_pattern;
-+ res->masklen = mask;
-+ res->opattern = mystrdup(pattern);
-+ res->pattern = mypattern;
-+ *result = res;
-+
-+ return (1);
-+ }
-+
- /* match_hostaddr - match host by address */
-
-+ /* XXX: the IPv4-only version does not yet use std_addr_pattern --dean */
-+
- int match_hostaddr(int unused_flags, const char *addr, const char *pattern)
- {
- char *myname = "match_hostaddr";
-+ #ifdef INET6
-+ size_t patlen;
-+ char *plenp;
-+ int aierr, res, ret, mask;
-+ struct addrinfo hints, *res0;
-+ struct sockaddr_storage ss_addr, ss_mask;
-+ ADDR_PATTERN *mask_info;
-+
-+ ret = 0;
-+ if (msg_verbose)
-+ msg_info("%s: %s ~? %s", myname, addr, pattern);
-+
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_NUMERICHOST;
-+ aierr = getaddrinfo(addr, NULL, &hints, &res0);
-+ /*
-+ * The access maps checks run both hostname and address through this.
-+ * E.g. the CIDR map checks both the hostname and address. Checking the
-+ * hostname in a CIDR map will yield no result but may not give an
-+ * EAI_NONAME error since it is correct that the hostname cannot be
-+ * interpreted numerically.
-+ */
-+ if (aierr != 0 && aierr != EAI_NONAME)
-+ msg_fatal("%s: getaddrinfo(%s): %s", myname, addr, GAI_STRERROR(aierr));
-+ memcpy(&ss_addr, (const void *)res0->ai_addr, res0->ai_addrlen);
-+ freeaddrinfo(res0);
-+
-+ res = std_addr_pattern(MATCH_FLAG_NONE, pattern, &mask_info, NULL);
-+ if (mask_info == NULL) {
-+ /*
-+ * Try dictionary lookup. This can be case insensitive.
-+ */
-+ if (res && strchr(pattern, ':') != 0) {
-+ if (dict_lookup(pattern, addr) != NULL)
-+ return 1;
-+ }
-+ return 0;
-+ }
-+
-+ /*
-+ * Try an exact match with the host address (IPv4 only)
-+ */
-+ if (mask_info->addr->sa_family == AF_INET &&
-+ strcasecmp(pattern, addr) == 0) {
-+ addr_pattern_free(mask_info);
-+ return 1;
-+ }
-+
-+ res = match_sockaddr((struct sockaddr *)&ss_addr,
-+ mask_info->addr, mask_info->masklen);
-+ addr_pattern_free(mask_info);
-+ return (res != 0);
-+
-+
-+ #else
- int mask_shift;
- unsigned long mask_bits;
- unsigned long net_bits;
-***************
-*** 219,225 ****
- * Try dictionary lookup. This can be case insensitive. XXX Probably
- * should also try again after stripping least significant octets.
- */
-! if (strchr(pattern, ':') != 0) {
- if (dict_lookup(pattern, addr) != 0)
- return (1);
- if (dict_errno != 0)
---- 618,625 ----
- * Try dictionary lookup. This can be case insensitive. XXX Probably
- * should also try again after stripping least significant octets.
- */
-! if (strchr(pattern, ':') != 0)
-! {
- if (dict_lookup(pattern, addr) != 0)
- return (1);
- if (dict_errno != 0)
-***************
-*** 238,248 ****
- * In a net/mask pattern, the mask is specified as the number of bits of
- * the network part.
- */
- if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
- addr_bits = inet_addr(addr);
- if (addr_bits == INADDR_NONE)
- msg_fatal("%s: bad address argument: %s", myname, addr);
-! mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
- if ((addr_bits & mask_bits) == net_bits)
- return (1);
- if (net_bits & ~mask_bits) {
---- 638,649 ----
- * In a net/mask pattern, the mask is specified as the number of bits of
- * the network part.
- */
-+
- if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
- addr_bits = inet_addr(addr);
- if (addr_bits == INADDR_NONE)
- msg_fatal("%s: bad address argument: %s", myname, addr);
-! mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR_V4 - mask_shift));
- if ((addr_bits & mask_bits) == net_bits)
- return (1);
- if (net_bits & ~mask_bits) {
-***************
-*** 253,256 ****
---- 654,773 ----
- }
- }
- return (0);
-+ #endif
-+ }
-+
-+ int
-+ match_sockaddr(const struct sockaddr *addr, const struct sockaddr *mask,
-+ int masklen)
-+ {
-+ /*
-+ * I generally hate to do so, but this function just asks for
-+ * #ifdef INET6... address comparison in the IPv4 only case is
-+ * utterly trivial, completely unlike the mixed AF case.
-+ */
-+ #ifdef INET6
-+ if (addr->sa_family == AF_INET) {
-+ if (mask->sa_family == AF_INET6) {
-+ if (IN6_IS_ADDR_V4MAPPED(
-+ &((struct sockaddr_in6 *)mask)->sin6_addr)) {
-+ /* IPv4 address but IPv4-mapped-IPv6 netmask... */
-+ if (masklen < 0 || masklen > BITS_PER_ADDR_V4)
-+ return 0;
-+ return mask_comp(&((struct sockaddr_in *)addr)->sin_addr.s_addr,
-+ &((struct sockaddr_in6 *)mask)->sin6_addr.s6_addr[12],
-+ masklen);
-+ }
-+ /* IPv4 address yet IPv6 mask. No match */
-+ return 0;
-+ }
-+ /* IPv4 address, IPv4 netmask */
-+ if (masklen < 0 || masklen > BITS_PER_ADDR_V4)
-+ return 0;
-+ return mask_comp(&((struct sockaddr_in *)addr)->sin_addr.s_addr,
-+ &((struct sockaddr_in *)mask)->sin_addr.s_addr,
-+ masklen);
-+ } else if (addr->sa_family == AF_INET6) {
-+ /* IPv6 address, IPv6 netmask */
-+ struct sockaddr_in6 *addr6, *mask6;
-+ addr6 = (struct sockaddr_in6 *)addr;
-+ mask6 = (struct sockaddr_in6 *)mask;
-+
-+ if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
-+ /* V4-mapped IPv6 address */
-+ struct sockaddr_in addr4;
-+ memset(&addr4, 0, sizeof(addr4));
-+ #ifdef HAS_SA_LEN
-+ addr4.sin_len = sizeof(addr4);
-+ #endif
-+ addr4.sin_family = AF_INET;
-+ memcpy(&addr4.sin_addr.s_addr, &addr6->sin6_addr.s6_addr[12], 4);
-+ if (masklen > BITS_PER_ADDR_V4 && masklen <= BITS_PER_ADDR_V6)
-+ masklen -= BITS_PER_ADDR_V6 - BITS_PER_ADDR_V4;
-+ return match_sockaddr((struct sockaddr *)&addr4, mask, masklen);
-+ }
-+ /* True IPv6, finally... */
-+ if (masklen < 0 || masklen > BITS_PER_ADDR_V6)
-+ return 0;
-+ if (mask->sa_family != AF_INET6 ||
-+ IN6_IS_ADDR_V4MAPPED(&mask6->sin6_addr))
-+ return 0;
-+ #ifdef __KAME__
-+ if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr))
-+ if (!IN6_IS_ADDR_SITELOCAL(&mask6->sin6_addr) ||
-+ addr6->sin6_scope_id != mask6->sin6_scope_id)
-+ return 0;
-+ if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr))
-+ if (!IN6_IS_ADDR_LINKLOCAL(&mask6->sin6_addr) ||
-+ addr6->sin6_scope_id != mask6->sin6_scope_id)
-+ return 0;
-+ #endif
-+ return mask_comp(&addr6->sin6_addr.s6_addr,
-+ &mask6->sin6_addr.s6_addr,
-+ masklen);
-+ }
-+ /* Unsupported address family */
-+ return 0;
-+ #else /* INET6 */
-+ /*
-+ * Trivial for IPv4...
-+ */
-+ return (addr->sa_family == mask->sa_family &&
-+ ((struct sockaddr_in *)addr)->sin_addr.s_addr ==
-+ ((struct sockaddr_in *)mask)->sin_addr.s_addr);
-+ #endif /* INET6 */
-+ }
-+
-+ static int
-+ mask_comp(void *addr, void *mask, int masklen)
-+ {
-+ int bytes, bit;
-+
-+ bytes = masklen / 8;
-+ bit = 8 - masklen % 8;
-+ if (memcmp(addr, mask, bytes) != 0)
-+ return 0;
-+ if (bit != 8) {
-+ char *a = addr, *b = mask;
-+ if ((a[bytes] & (0xff << bit)) != (b[bytes] & (0xff << bit)))
-+ return 0;
-+ }
-+ return 1;
-+ }
-+
-+ ADDR_PATTERN *
-+ addr_pattern_init() {
-+ ADDR_PATTERN *p;
-+ p = (ADDR_PATTERN *)mymalloc(sizeof(ADDR_PATTERN));
-+ memset(p, 0, sizeof(ADDR_PATTERN));
-+ return p;
- }
-+
-+ void
-+ addr_pattern_free(ADDR_PATTERN *p) {
-+ if (p->addr) myfree((char *)p->addr);
-+ if (p->pattern) myfree(p->pattern);
-+ if (p->opattern) myfree(p->opattern);
-+ myfree((char *)p);
-+ }
-+
-diff -Pcr postfix-2.0.16/src/util/match_ops.h postfix-2.0.16-ti1.20/src/util/match_ops.h
-*** postfix-2.0.16/src/util/match_ops.h Tue Nov 20 21:03:07 2001
---- postfix-2.0.16-ti1.20/src/util/match_ops.h Mon Jan 5 16:58:09 2004
-***************
-*** 11,25 ****
- /* DESCRIPTION
- /* .nf
-
- /* External interface. */
-
- #define MATCH_FLAG_NONE 0
- #define MATCH_FLAG_PARENT (1<<0)
-! #define MATCH_FLAG_ALL (MATCH_FLAG_PARENT)
-
- extern int match_string(int, const char *, const char *);
- extern int match_hostname(int, const char *, const char *);
- extern int match_hostaddr(int, const char *, const char *);
-
- /* LICENSE
- /* .ad
---- 11,50 ----
- /* DESCRIPTION
- /* .nf
-
-+ /*
-+ * Utility library.
-+ */
-+ #include <vstring.h>
-+
- /* External interface. */
-
- #define MATCH_FLAG_NONE 0
- #define MATCH_FLAG_PARENT (1<<0)
-! #define MATCH_FLAG_STRICT_ADDR (1<<1)
-! #define MATCH_FLAG_NOLOOKUP (1<<2)
-! #define MATCH_FLAG_NONNULL_HOST (1<<3)
-! #define MATCH_FLAG_ALL (MATCH_FLAG_PARENT | MATCH_FLAG_NOLOOKUP | MATCH_FLAG_NONNULL_HOST)
-!
-! #define GAI_STRERROR(error) \
-! ((error == EAI_SYSTEM) ? strerror(errno) : gai_strerror(error))
-!
-! /* Data structures. */
-!
-! typedef struct ADDR_PATTERN {
-! struct sockaddr *addr; /* pointer to sockaddr(_storage) address */
-! size_t masklen; /* prefix length */
-! char *pattern; /* modified pattern */
-! char *opattern; /* original string pattern */
-! } ADDR_PATTERN;
-
- extern int match_string(int, const char *, const char *);
- extern int match_hostname(int, const char *, const char *);
- extern int match_hostaddr(int, const char *, const char *);
-+ extern int std_addr_pattern(int, const char *, ADDR_PATTERN **, VSTRING *);
-+ extern int match_sockaddr(const struct sockaddr *, const struct sockaddr *, int);
-+
-+ extern ADDR_PATTERN * addr_pattern_init(void);
-+ extern void addr_pattern_free(ADDR_PATTERN *);
-
- /* LICENSE
- /* .ad
-***************
-*** 30,35 ****
---- 55,67 ----
- /* IBM T.J. Watson Research
- /* P.O. Box 704
- /* Yorktown Heights, NY 10598, USA
-+ /*
-+ /* Dean C. Strik
-+ /* Department ICT Services
-+ /* Eindhoven University of Technology
-+ /* P.O. Box 513
-+ /* 5600 MB Eindhoven, Netherlands
-+ /* E-mail: <dean@ipnet6.org>
- /*--*/
-
- #endif
-diff -Pcr postfix-2.0.16/src/util/sdbm.c postfix-2.0.16-ti1.20/src/util/sdbm.c
-*** postfix-2.0.16/src/util/sdbm.c Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/sdbm.c Mon Jan 5 16:58:09 2004
-***************
-*** 0 ****
---- 1,973 ----
-+ /*++
-+ /* 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>
-+
-+ #include "mymalloc.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 -Pcr postfix-2.0.16/src/util/sdbm.h postfix-2.0.16-ti1.20/src/util/sdbm.h
-*** postfix-2.0.16/src/util/sdbm.h Thu Jan 1 01:00:00 1970
---- postfix-2.0.16-ti1.20/src/util/sdbm.h Mon Jan 5 16:58:09 2004
-***************
-*** 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 -Pcr postfix-2.0.16/src/util/sys_defs.h postfix-2.0.16-ti1.20/src/util/sys_defs.h
-*** postfix-2.0.16/src/util/sys_defs.h Thu Sep 11 02:33:31 2003
---- postfix-2.0.16-ti1.20/src/util/sys_defs.h Mon Jan 5 16:58:09 2004
-***************
-*** 73,78 ****
---- 73,86 ----
- #define DEF_MAILBOX_LOCK "flock, dotlock"
- #endif
-
-+ #if !defined(NOGETIFADDRS) && ( \
-+ (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) \
-+ || (defined(__FreeBSD__) && __FreeBSD__ >= 4) \
-+ || (defined(OpenBSD) && OpenBSD >= 200003) \
-+ || defined(USAGI_LIBINET6))
-+ #define HAVE_GETIFADDRS
-+ #endif
-+
- /*
- * UNIX on MAC.
- */
-***************
-*** 255,260 ****
---- 263,269 ----
- #define FIONREAD_IN_SYS_FILIO_H
- #define USE_STATVFS
- #define STATVFS_IN_SYS_STATVFS_H
-+ #define INT_MAX_IN_LIMITS_H
- #define STREAM_CONNECTIONS /* avoid UNIX-domain sockets */
- #define LOCAL_LISTEN stream_listen
- #define LOCAL_ACCEPT stream_accept
-***************
-*** 262,267 ****
---- 271,279 ----
- #define LOCAL_TRIGGER stream_trigger
- #define HAS_VOLATILE_LOCKS
- #define BROKEN_READ_SELECT_ON_TCP_SOCKET
-+ #ifdef INET6
-+ #define HAS_SIOCGLIF
-+ #endif
- /*
- * Allow build environment to override paths.
- */
-***************
-*** 506,511 ****
---- 518,527 ----
- #define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
- #define NATIVE_COMMAND_DIR "/usr/sbin"
- #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
-+ #ifdef INET6
-+ #define HAS_PROCNET_IFINET6
-+ #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
-+ #endif
- #endif
-
- #ifdef LINUX1
-***************
-*** 534,539 ****
---- 550,559 ----
- #define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
- #define NATIVE_COMMAND_DIR "/usr/sbin"
- #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
-+ #ifdef INET6
-+ #define HAS_PROCNET_IFINET6
-+ #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
-+ #endif
- #endif
-
- /*
-diff -Pcr postfix-2.0.16/src/util/valid_hostname.c postfix-2.0.16-ti1.20/src/util/valid_hostname.c
-*** postfix-2.0.16/src/util/valid_hostname.c Fri Dec 20 02:33:41 2002
---- postfix-2.0.16-ti1.20/src/util/valid_hostname.c Mon Jan 5 16:58:09 2004
-***************
-*** 53,58 ****
---- 53,65 ----
- #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"
-***************
-*** 109,115 ****
- msg_warn("%s: misplaced hyphen: %.100s", myname, name);
- return (0);
- }
-! } else {
- if (gripe)
- msg_warn("%s: invalid character %d(decimal): %.100s",
- myname, ch, name);
---- 116,138 ----
- msg_warn("%s: misplaced hyphen: %.100s", myname, name);
- return (0);
- }
-! }
-! #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);
-***************
-*** 141,146 ****
---- 164,172 ----
- int byte_count = 0;
- int byte_val = 0;
- int ch;
-+ #ifdef INET6
-+ struct addrinfo hints, *res;
-+ #endif
-
- #define BYTES_NEEDED 4
-
-***************
-*** 152,157 ****
---- 178,194 ----
- 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
-
- /*
- * Preliminary IPV6 support.