]> git.pld-linux.org Git - packages/postfix.git/commitdiff
- obsolete
authorTomek Orzechowski <orzech@pld-linux.org>
Wed, 28 Jan 2004 09:13:26 +0000 (09:13 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    tls+ipv6-1.20-pf-2.0.16.patch -> 1.2

tls+ipv6-1.20-pf-2.0.16.patch [deleted file]

diff --git a/tls+ipv6-1.20-pf-2.0.16.patch b/tls+ipv6-1.20-pf-2.0.16.patch
deleted file mode 100644 (file)
index cb0f88b..0000000
+++ /dev/null
@@ -1,25992 +0,0 @@
-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&auml;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 &lt; 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 &lt; 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 -&gt; Postfix works fine,<br>
-+ Postfix -&gt; 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 &eacute;galement le fichier conf/sample-tls.cf</p>
-+ <p>main.cf: smtpd (serveur) variables sp&eacute;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 &quot;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&eacute;n&eacute;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 &ecirc;tre disponible<br>
-+   # Vous devez ajouter ces certificats aux certificat du serveur, ce dernier en 
-+   premier puis ceux &eacute;mis par par le(s) CA(s)<br>
-+   #<br>
-+   # exemple: le certificat pour &quot;serveur.chez.moi&quot; a &eacute;t&eacute; 
-+   &eacute;mis par &quot;Intermediate CA&quot;<br>
-+   # qui lui m&ecirc;me a un certificat de &quot;root CA&quot;. Creez le fichier 
-+   server.pem en faisant 'cat server_cert.pem intermediate.pem &gt; 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&eacute;cessaire de les 
-+   avoir dans le fichier smtpd_tls_[d]cert_file<br>
-+   #<br>
-+   # Un certificat fourni ici doit &ecirc;tre utilisable comme SSL certificat serveur 
-+   et par cons&eacute;quent passer le test<br>
-+   # &quot;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 &ecirc;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&ecirc;mes CA sont offerts aux 
-+   clients pour la v&eacute;rification. N'oubliez pas de cr&eacute;er<br>
-+   # les tables de hachages n&eacute;cessaires avec $OPENSSL_HOME/bin/c_rehash 
-+   /etc/postfix/certs. Une place classique<br>
-+   # pour les certificats CA peut &ecirc;tre aussi $OPENSSL_HOME/certs, il n'y 
-+   a donc aucune valeur par d&eacute;faut et vous avez &agrave;<br>
-+   # le sp&eacute;cifier ici<br>
-+   #<br>
-+   # Pour utiliser cette option en mode chroot&eacute;, ce r&eacute;pertoire ou 
-+   une copie de celui-ci doit &ecirc;tre dans la 'cage'. Veuillez noter &eacute;galement<br>
-+   # que les CA list&eacute;s dans ce r&eacute;pertoire ne sont pas list&eacute;s 
-+   aux clients, Netscape ne peut donc pas offrir de certificats &eacute;mis par 
-+   ceux ci.<br>
-+   #<br>
-+   # Je n'encourage pas &agrave; l'utilisation de cette option<br>
-+   <br>
-+   smtpd_tls_CApath = /etc/postfix/certs <br>
-+   <br>
-+   # Pour obtenir des informations suppl&eacute;mentaires pendant la mise en place 
-+   et les n&eacute;gociations TLS<br>
-+   # vous pouvez augmenter le niveau de journalisation de 0 &agrave; 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&eacute;mes. L'utilisation 
-+   du niveau 4 est fortement d&eacute;conseillée.<br>
-+   #<br>
-+   # smtpd_tls_loglevel = 0 <br>
-+   # Afin d'inclure des informations sur le protocole et le cryptage utilis&eacute; 
-+   aussi bien que le client et l'émetteur <br>
-+   # dans l'ent&ecirc;te &quot;Received:&quot;, positionnez la variable smtpd_tls_received_header 
-+   &agrave; true. Par d&eacute;faut elle est a no, <br>
-+   # du fait que cette information n'est pas forc&eacute;ment authentique. Seulement 
-+   la destination finale est fiable, <br>
-+   # puisque les en-têtes pourraient avoir Ã©té modifi&eacute;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 &ecirc;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&egrave;re utiliser 
-+   un mode d'emballage non-standard et non les<br>
-+   # am&eacute;liorations STARTTLS de SMTP.<br>
-+   # Ceci est vrai pour outlook express ( Win32 &lt; 5.0 et Win 32 &gt;= 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 &ecirc;tre besoin du certificat si vous voulez faire du relayage 
-+   &agrave; 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&eacute;, 
-+   et n'a de sens que dans le cas<br>
-+   # de soumission normal desactiv&eacute;e (smtpd_enforce_tls). Autrement les 
-+   clients peuvent &eacute;viter ceci en n'utilisant pas du tout <br>
-+   # STARTTLS. Quand TLS n'est pas imposé, la connexion ne sera trait&eacute;e comme 
-+   si smtpd_tls_ask_ccert = yes <br>
-+   # &eacute;tait activ&eacute; et une information est journalis&eacute;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 &eacute;mis directement par un CA list&eacute; 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&eacute;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&eacute;e <br>
-+   # smtpd_recipient_restrictions<br>
-+   # postfix va relayer si<br>
-+   # (a) Un client valide (v&eacute;rification faite) est pr&eacute;sent&eacute; 
-+   et que son empreinte est inscrite dans la liste des certificats clients<br>
-+   # (relay_clientcerts), <br>
-+   # (b) n'importe quel client valide (v&eacute;rification faite) est pr&eacute;sent&eacute;.<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 &agrave; d'autres 
-+   CA tout propriétaire d'un certificat client valide <br>
-+   # peut &ecirc;tre relay&eacute;. L'option (b) peut Ãªtre pratique pour un relais 
-+   sp&eacute;cialement cr&eacute;&eacute;. Il est recommande cependant de rester 
-+   <br>
-+   # avec l'option (a) et d'énumérer tous les certificats, car (b) ne permet aucun 
-+   contr&ocirc;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&eacute;parateurs <br>
-+   # et s'emm&egrave;le sur les caract&egrave;res sp&eacute;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&eacute;lection du cryptage, vous pouvez donner une liste 
-+   de cryptage.<br>
-+   # Une description compl&egrave;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&egrave;tres DH pour &agrave; la fois le 
-+   1025&eacute;me et le 512&eacute;me bit disponible<br>
-+   # Il vaut mieux cependant avoir ses &quot;propres&quot; param&egrave;tres, puisqu'autrement 
-+   ce serait &quot;payant&quot; pour un<br>
-+   # 'pirates' d'attaquer en brute force ces param&egrave;tres qui sont utilis&eacute;s 
-+   commun&eacute;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&eacute;n&eacute;ration al&eacute;atoire peut varier; 
-+   sur des yst&egrave;mes linux c'est /dev/random<br>
-+   # Pour d'autres syst&egrave;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&egrave;tre la limite de temps en secondes pour 
-+   lire et &eacute;crire<br>
-+   # les op&eacute;rations pendant les proc&eacute;dures de 'serrages de mains' 
-+   (SSL handshake) <br>
-+   # <br>
-+   # smtpd_starttls_timeout = 300s <br>
-+   <br>
-+   # Main.cf smtp (client) variables sp&eacute;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 &agrave; 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&egrave;tre par defaut est de n'utiliser aucun certificat/clef a moins 
-+   de de le d&eacute;finir ici.<br>
-+   # Si un certificat est pr&eacute;sent il doit &ecirc;tre au format PEM, la clef 
-+   priv&eacute;e ne doit pas &ecirc;tre encrypt&eacute;e : concr&eacute;tement<br>
-+   # cela veut dire qu'elle doit &ecirc;tre accessible sans mot de passe. LA clef 
-+   et le certificats peuvent &ecirc;tre dans le m&ecirc;me fichier.<br>
-+   <br>
-+   # Afin de contr&ocirc;ler les certificats, le certificat CA doit &ecirc;tre 
-+   disponible (dans le cas d'une chaine de certificats, tous les <br>
-+   # certificats CA).<br>
-+   # Exemple: le certificat pour &quot;moi.chez.moi.fr&quot; a &eacute;t&eacute; 
-+   &eacute;mis par &quot;intermedaire CA&quot; qui lui-m&ecirc;me<br>
-+   # a un certificat de &quot;racine CA&quot;. Cr&eacute;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&ecirc;mes les certificats &eacute;mis par ces 
-+   CA, vous pouvez &eacute;galement ajouter<br>
-+   # les certificats CA au fichier smtp_tls_CAfile, dans ce cas il n'est pas n&eacute;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 &ecirc;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&eacute;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&eacute;er 
-+   les tables de hachage n&eacute;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 &ecirc;tre dans la cage<br>
-+   <br>
-+   smtp_tls_CApath = /etc/postfix/certs <br>
-+   <br>
-+   # Pour obtenir des informations supl&eacute;mentaires pendant la mise en place 
-+   et les n&eacute;gociations TLS<br>
-+   # vous pouvez augmenter le niveau de journalisation de 0 &agrave; 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&eacute;mes. L'utilisation 
-+   du niveau 4 est fortement d&eacute;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&eacute;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&eacute;sactiv&eacute;, ainsi aucune différence au Postfix 
-+   ordinaire n'est visible. Si vous l'activez <br>
-+   # TLS sera utilis&eacute; 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&ecirc;me si il n'est pas configur&eacute;, ainsi il pourrait Ãªtre sage de 
-+   ne pas utiliser ceci sur votre serveur central de messagerie<br>
-+   # car vous ne savez pas &agrave; l'avance si vous allez rencontrer ce genre 
-+   de serveur. Utilisez les options de recipient/site Ã  la place .<br>
-+   # Conseil: je l'ai activ&eacute; sur mes serveurs de courrier et je n'a eu qu'une 
-+   panne depuis que la version client de TLS <br>
-+   # est impl&eacute;ment&eacute;e (c'&eacute;tait un serveur EXCHANGE mal configur&eacute;, 
-+   j'ai contact&eacute; l'administrateur).<br>
-+   # Par cons&eacute;quent j'en suis satisfait  de l'utiliser tout le temps, mais 
-+   je suis toutefois int&eacute;ress&eacute; par des tests.<br>
-+   # Cependant vous aurez &eacute;t&eacute; pr&eacute;venu ;-)<br>
-+   <br>
-+   # Dans le cas d'un echec, un code &quot;4xx&quot; (ndt: erreur temporaire) est 
-+   &eacute;mis et le message reste dans la file d'attente<br>
-+   # Sp&eacute;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&eacute;es<br>
-+   # De plus, le nom de l'h&ocirc;te doit &ecirc;tre identique au nom contenu dans 
-+   le certificat. En outre, le certtificat doit <br>
-+   # passer avec succ&egrave;s la v&eacute;rification, le client doit faire confiance 
-+   &agrave; l'entit&eacute; de certification qui a &eacute;mis le certificat.<br>
-+   # Si le certificat ne correspond pas au nom de la machine ou si le test de v&eacute;rification 
-+   &eacute;choue un code &quot;4xx&quot; <br>
-+   # va &ecirc;tre envoy&eacute; et le message va rester en file d'attente.<br>
-+   # Le nom d'h&ocirc;te utilis&eacute; est &eacute;vident, en effet il doit &ecirc;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&eacute;faut peut &ecirc;tre une mauvaise id&eacute;ee 
-+   (quelques machines offre STARTTLS mais<br>
-+   # la n&eacute;gociation va &eacute;chouer avec des erreurs inexpliquables, il 
-+   peut &ecirc;tre une bonne id&eacute;e de d&eacute;cider selon<br>
-+   # le destinataire ou la machine distante sur laquelle vous vous connectez<br>
-+   <br>
-+   # D&eacute;cider par destinataire peut &ecirc;tre difficile, car un seul message 
-+   peut avoir plusieurs destinataires.<br>
-+   # Nous allons utiliser le m&eacute;canisme &quot;nexthop&quot; (prochain saut) 
-+   interne de Postfix.<br>
-+   # Quand un message va &ecirc;tre d&eacute;livr&eacute;, the &quot;nexthop&quot; 
-+   est obtenu. Si il correspond &agrave; une entr&eacute;e<br>
-+   # dans la liste smtp_tls_per_site, une action appropriée est effectu&eacute;e<br>
-+   # Une entr&eacute;e dans la table de transport ou l'utilisation de relay_host 
-+   r&eacute;ecrivent le param&egrave;tre &quot;nexthop&quot;<br>
-+   # dans ce cas l'h&ocirc;te de relayage doit &ecirc;tre indiqu&eacute; dans la 
-+   liste. Dans tous les cas le nom <br>
-+   # de l'hote &agrave; contacter est r&eacute;solu (en fait l'enregistrement MX 
-+   ou le nom de la machine si il n'y a pas de MX)<br>
-+   # Conseil sp&eacute;cial pour le renforcement: <br>
-+   # puisqu'il n'y a aucun moyen disponible pour s&eacute;curiser les r&eacute;solutions 
-+   DNS , le param&egrave;trage recommand&eacute; est:<br>
-+   # mettez les domaines sensibles dans une table de transport (vous pouvez ainsi 
-+   vous assurer de la s&eacute;curit&eacute;<br>
-+   # de cette table &agrave; la diff&eacute;rence de DNS), puis param&eacute;trez 
-+   &agrave; MUST cet h&ocirc;te de messagerie.<br>
-+   <br>
-+   # Format de la table:<br>
-+   # Le entr&eacute;es clefs sont sur le cot&eacute; gauche, les jokers ne sont 
-+   pas autoris&eacute;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&egrave;mes)<br>
-+   # MUST (force l'usage de TLS, v&eacute;rifie le nom du certificat server avec 
-+   le nom du serveur), MUST_NOPEERMATCH<br>
-+   # (force l'usage de TLS et v&eacute;rifie le certificat, mais ignore les diff&eacute;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&eacute;e ne correspond pas la politique par d&eacute;faut est 
-+   appliqu&eacute;e; si la politique par d&eacute;faut est &quot;enforce&quot;,<br>
-+   # NONE la d&eacute;sactive explicitement, sinon le mode &quot;enforce&quot; 
-+   est utilis&eacute; m&ecirc;me pour les entr&eacute;es &quot;MAY&quot;<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 &eacute;mis directement par un CA list&eacute; 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&eacute;cidé d'opter pour une politique &quot;par site&quot; 
-+   afin d'utiliser ou non TLS, il serait interessant<br>
-+   # d'avoir une liste de sites offrant STARTTLS. Nous pouvons la r&eacute;cup&eacute;rer 
-+   nous m&ecirc;mes avec cette option:<br>
-+   # Si ce param&egrave;tre est activ&eacute; et que TLS n'est pas activ&eacute; 
-+   pour cet h&ocirc;te, une ligne est ajout&eacute; 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&eacute;lection du cryptage, vous pouvez donner une liste 
-+   de cryptage.<br>
-+   # Une description compl&egrave;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&egrave;tre limite le temps en secondes pour 
-+   lire et &eacute;crire<br>
-+   # les op&eacute;rations pendant les proc&eacute;dures de 'serrages de mains' 
-+   (SSL handshake) <br>
-+   # <br>
-+   # smtp_starttls_timeout = 300s <br>
-+ </p>
-+ <p>main.cf : variables g&eacute;n&eacute;rales</p>
-+ <p># Afin d'alimenter le PRNG Pseude Random Number Generator (pseudo g&eacute;n&eacute;rateur 
-+   de nombres al&eacute;atoires),<br>
-+   # des donn&eacute;es al&eacute;atoires sont n&eacute;c&eacute;ssaires. Le 'stock' 
-+   de PRNG est mis &agrave; jour par le d&eacute;mon &quot;tlsmgr&quot; et est 
-+   utilis&eacute; (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&eacute;&eacute;crit par tlsmgr, est 
-+   cr&eacute;&eacute; si il n'existe pas. Une valeur par d&eacute;faut est donn&eacute;e<br>
-+   # et doit s&ucirc;rement &ecirc;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, 
-+   &agrave; la fois au d&eacute;marrage et pendant l'&eacute;xecution<br>
-+   # Sp&eacute;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 &agrave; chaque 'alimentation' (qui 
-+   est une quantit&eacute; de 256 bits et par conséquent <br>
-+   # assez bon pour des clefs sym&eacute;triques de 128bits)<br>
-+   # Vous devez sp&eacute;cifier la type de sources : &quot;dev:&quot; pour un 
-+   pour un fichier spécial de p&eacute;riph&eacute;rique ou &quot;egd:&quot; 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 &agrave; chaque &eacute;tape.<br>
-+   # Si vous sp&eacute;cifiez un fichier normal, un plus grand nombre de donn&eacute;es 
-+   peut &ecirc;tre lu.<br>
-+   <br>
-+   # La source d'entropie est interrog&eacute;e de nouveau apr&egrave;s un certains 
-+   temps. ce temps est calcul&eacute; en utilisant le PRNG,<br>
-+   # il est compris entre 0 et le temps sp&eacute;cifi&eacute;, un defaut est sp&eacute;cifi&eacute; 
-+   &agrave; 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&eacute; pour reg&eacute;n&eacute;rer 
-+   le fichier de 1024 octets qui est lu par smtp(d). Le temps, apr&egrave;s lequel<br>
-+   # le fichier d'&eacute;change se trouve reg&eacute;n&eacute;r&eacute; est calcul&eacute; 
-+   en utilisant le PRNG, il est compris entre 0 et le temps sp&eacute;cifi&eacute;, 
-+   <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&eacute;e 
-+   (comme /dev/urandom), les d&eacute;mons<br>
-+   # peuvent aussi charger une entropie suppl&eacute;mentaire au d&eacute;marrage 
-+   depuis une source sp&eacute;cifi&eacute;e. Par défaut une quantité<br>
-+   # de 32 octets est lue, Ã©quivalent Ã  256 bits. Ceci est plus que suffisant pour 
-+   g&eacute;n&eacute;rer une clef de session de 128 (ou 168) bits<br>
-+   # mais nous avons &agrave; en g&eacute;n&eacute;rer plus d'une. L'utilisation 
-+   de cette option peut vider EGD (en prenant le cas de 50 smtp <br>
-+   # d&eacute;marrant avec une file d'attente pleine en faisant &quot;postfix start&quot;, 
-+   ceci devrait requ&eacute;rir 1600 octets d'entropie). Ceci<br>
-+   # n'est cependant pas une cause d'arr&ecirc;t, du fait que les donn&eacute;es 
-+   d'entropie peuvent &ecirc;tre lues depuis le fichier d'&eacute;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&eacute;mon tlsmgr</p>
-+ <p>Si vous n'avez pas de p&eacute;riph&eacute;rique /dev/urandom ou si vous n'utilisez 
-+   pas le syst&egrave;me de cache de session, vous devez lancer <br>
-+   le d&eacute;mon tlsmgr (voir conf/master.cf). Tlsmgr a besoin d'avoir acc&eacute;s 
-+   &agrave; la source d'entropie et ne peut (encore) &ecirc;tre &eacute;x&eacute;cut&eacute; 
-+   <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&eacute;menentaires</p>
-+ <p> Il peut &ecirc;tre pratique d'avoir postfix Ã©coutant sur des ports suppl&eacute;mentaires, 
-+   nomm&eacute;s &quot;submission&quot;=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&eacute; 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&eacute; 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 &eacute;xecut&eacute; dans une cage)!!! <br>
-+   (utilisez les num&eacute;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>&nbsp;</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&eacute;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&eacute;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 &agrave; 
-+   partir de la version 0.9.5 des bibliothèque OpenSSL. 0.9.5a a prouvé une stabilité 
-+   au del&agrave; 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 &quot;pfixtls.diff&quot; dans le r&eacute;pertoire 
-+   principal du kit de mise Ã  jour.<br>
-+   Pour appliquer la mise Ã  jour, allez dans le r&eacute;pertoire parent de l'arborescence 
-+   des sources originales de Postfix (vous devez voir &quot;postfix-xxxxxx&quot; 
-+   ou &quot;snapshot-xxxxxx&quot; quand vous faites un &quot;ls -al&quot; 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&eacute;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&eacute;e, elle peut &ecirc;tre &eacute;galement 
-+   appliqu&eacute; &agrave; un code source mod&eacute;r&eacute;ment modifi&eacute; 
-+   sans que des conflits apparaissent.</p>
-+ <p>Compiler</p>
-+ <p>Apres &ecirc;tre mis Ã  jour; postfix va se configurer et se compiler comme 
-+   avant. Dans le but d'activer les fonctions TLS, vous devez sp&eacute;cifier 
-+   le chemin des headers OpenSSL ainsi que les biblioth&eacute;ques appropri&eacute;es, 
-+   et vous devez d&eacute;finir USE_SSL. Votre commande pour la configuration doit 
-+   &ecirc;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 &eacute;numér&eacute; dans les instructions INSTALL de postfix 
-+   . Vous pouvez alors continuer de la mani&egrave;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 &agrave;  propos du d&eacute;marrage du projet</p>
-+ <p>Quand j'ai commenc&eacute; a &eacute;crire ce programme, j'avais en t&ecirc;te un un moyen sophistiqu&eacute; 
-+   pour autoriser le relayage de mes utilisateurs itin&eacute;rants. En 
-+   attendant ce projet vit de lui-m&ecirc;me.</p>
-+ <p>RFC2246 : le protocol TLS (anciennement SSL)</p>
-+ <p>Par d&eacute;faut toutes les communications sur internet sont faites sans cryptage 
-+   et sans authentification forte. Cela signifie que toute personne avec un acc&egrave;s 
-+   physique au chemin de communication qu'emprunte un paquet peut &eacute;couter vos communications. 
-+   Pire, il est m&ecirc;me possible de rediriger ou de modifier vos communications donc 
-+   l'information que vous voulez envoyer &agrave; quelqu'un peut &ecirc;tre perdue ou modifi&eacute;e 
-+   &agrave; votre insu.</p>
-+ <p>Dans le but de r&eacute;soudre ces probl&egrave;mes de s&eacute;curit&eacute;, le protocole SSL (Secure 
-+   Socket Layers), pr&eacute;sent&eacute; par Netscape inc., 
-+   a maintenant &eacute;volu&eacute; en protocole TLS (Transportation Layer Security) 
-+   standardis&eacute; par la <a href="http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/doc/rfc2246.txt">RFC2246</a>.
-+  Cela permet &agrave; la fois le cryptage de la communication (arr&ecirc;t des 
-+   &eacute;coutes) et l'authentification forte (&ecirc;tre s&ucirc;r que les deux parties de 
-+   la communication sont correctement identifi&eacute;es et que la communication 
-+   ne peut pas &ecirc;tre alt&eacute;r&eacute;e)</p>
-+ <p>Postfix/TLS ne r&eacute;alise pas le protocole TLS lui-m&ecirc;me, il utilise 
-+   plut&ocirc;t le package OpenSSL pour cette t&acirc;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&eacute;cessaire de les inclure 
-+   ici. (Et, bien s&ucirc;r il n'y a aucune utilit&eacute; de ré&eacute;crire ce 
-+   que d'autres ont déjà ecrits, cela pr&eacute;sente juste l'int&eacute;r&ecirc;t 
-+   de rajouter des erreurs)</p>
-+ <p>&nbsp;</p>
-+ <p>RFC2487: Pr&eacute;sentation de TLS a SMTP</p>
-+ <p>L'int&eacute;gration du protocole TLS au protocole SMTP (Simple Mail Transport Protocol) 
-+   est d&eacute;crit dans la RFC2487</p>
-+ <p>À la différence des premi&egrave;res incarnations du SSL comme 'emballage' 
-+   d'une communication normale [STUNNEL] [JONAMA], le protocole TLS est maintenant 
-+   compl&eacute;tement int&eacute;gr&eacute; dans SMTP : pendant la n&eacute;gociation 
-+   de d&eacute;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&eacute;.</p>
-+ <p>Postfix/TLS : Ce qu'il peut faire pour vous </p>
-+ <p>La liste de fonctions pr&eacute;sent&eacute;e ici doit &ecirc;tre comprise 
-+   comme une liste d'id&eacute;es. Toutes ne sont pas encore r&eacute;alis&eacute;es, 
-+   regardez bien les notes pour chaque fonction.</p>
-+ <p>Encryption de message d'une machine &agrave; une autre:<br>
-+   Etat: Fait<br>
-+   Commentaire: une fois que la negociation STARTTLS est r&eacute;alis&eacute;e, 
-+   la communication entre les deux machines est crypt&eacute;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&ocirc;te r&eacute;cepteur afin d'&eacute;viter une interception<br>
-+   Etat: Fait<br>
-+   Commentaire: Ceci est une fonction importante qui n'est pas difficile a implementer. 
-+   Le probl&egrave;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&egrave;senter la commande STARTTLS, dans ce cas, aucune authentification 
-+   n'est faite. On doit Ã©galement faire attention &agrave; utiliser le nom correct du 
-+   serveur (voir le CNAME), mais ce probl&egrave;me est le même pour des serveurs HTTP.</p>
-+ <p>Authentification de l'hote &eacute;metteur afin d'&eacute;viter la contrefa&ccedil;on<br>
-+   Etat: Fait<br>
-+   Commentaire: Ceci est l'id&eacute;e &agrave; l'origine de ce projet, ce fut 
-+   donc la premi&egrave;re r&eacute;alisation. Bas&eacute; sur le certificat du 
-+   client MTA (ou MUA) pr&eacute;sent&eacute; au serveur, le relayage peut &ecirc;tre 
-+   ainsi autoris&eacute;.</p>
-+ <p>D'autres id&eacute;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&eacute; 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&eacute;s en TLS<br>
-+   - Tous les serveurs eux-m&ecirc;mes soient dignes de confiance, car l'email est seulement 
-+   chiffr&eacute; pendant le transport, pas en spool ni en queue.<br>
-+   - La destination soit digne de confiance, car le courrier est spool&eacute; en 
-+   clair et toute personne pouvant acc&eacute;der &agrave; votre boite aux lettres (root par exemple) 
-+   peut lire votre courrier! <br>
-+   Par cons&eacute;quent, si vous voulez une intimit&eacute; plus cons&eacute;quente, vous devez 
-+   envoyer votre email chiffr&eacute;, par exemple en utilisant S/MIME ou le module traditionnel 
-+   de PGP</p>
-+ <p>Authentifier l'&eacute;metteur du message<br>
-+   Etat: ne peut &ecirc;tre fait<br>
-+   Commentaire: Beaucoup de MUA envoient les messages juste en se connectant sur 
-+   le port SMTP de l'h&ocirc;te local ou du mailhub le plus proche. il n'y a aucun moyen 
-+   de s'assurer que l'&eacute;metteur list&eacute; dans le message est bien l'&eacute;metteur 
-+   r&eacute;el. Et m&ecirc;me si il &eacute;tait possible d'identifier l'&eacute;metteur, 
-+   le contenu du message pourrait avoir &eacute;t&eacute; modifi&eacute; entre 
-+   temps.<br>
-+   Pour assurer l'identit&eacute; de l'exp&eacute;diteur et l'int&eacute;grit&eacute; 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&egrave;gre le support de la RFC2487.<br>
-+   Frederik Vermeulen a r&eacute;alis&eacute; une extension de la RFC2487 pour 
-+   le MTA Qmail.<br>
-+   Matti Aarnio a int&eacute;gr&eacute; la RFC2487 dans ZMailer.<br>
-+   Michal Trojnara est actuellement en train d'int&eacute;grer un syst&egrave;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&eacute;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>&nbsp;</p>
-+ <p>&nbsp;</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&eacute;rations de S&eacute;curit&eacute;</p>
-+ <p>Les sections suivantes couvrent quelques consid&eacute;rations de s&eacute;curit&eacute;s 
-+   (possibles) en ce qui concerne Postfix/TLS.</p>
-+ <p>Clef priv&eacute;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&eacute;fini (smptd/smtp) doit pouvoir acc&eacute;der Ã  la clef priv&eacute;e, 
-+   qui doit cependant Ãªtre maintenue secrète.<br>
-+   Car ces processus sont lanc&eacute;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&eacute;e ne puisse pas Ãªtre chiffr&eacute;e. 
-+ </p>
-+ <p>La seule protection peut donc venu des droits d'accès de syst&eacute;me de 
-+   fichiers, qui devraient Ãªtre plac&eacute;s <br>
-+   Ã  'root' et ' lisible pour le propri&eacute;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&egrave;me est prot&eacute;g&eacute; 
-+   contre les failles de s&eacute;curit&eacute;s concernant root<br>
-+   <br>
-+   Vous devez aussi vous rendre compte que des personnes ayant un acc&eacute;s physique 
-+   &agrave; la machine peuvent voler<br>
-+   la clef priv&eacute;e si ils peuvent d&eacute;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&egrave;me o&ugrave; 
-+   ils sont super-utilisateur. (Oui je sais qu'il existe <br>
-+   des syst&eacute;mes de fichiers encrypt&eacute;s mais ils n'ont pas encore une 
-+   large diffusion)</p>
-+ <p>Ant&eacute;memoire de session sur le disque</p>
-+ <p>Si vous utilisez l'ant&eacute;memoire de session sur le disque (par d&eacute;faut) 
-+   des personnes capables mettre la main sur les fichiers <br>
-+   devraient pouvoir &eacute;viter les param&egrave;tres de transmission s&eacute;curis&eacute;e. 
-+   Cette situation n'est cependant pas plus grave que le cas<br>
-+   de la clef priv&eacute;e d&eacute;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&egrave;me de clefs n'est qu'une affaire de temps 
-+   (m&ecirc;me si ce temps peut &ecirc;tre tr&egrave;s long), les sessions<br>
-+   ne devraient pas &ecirc;tre utilis&eacute;es indéfiniment. La valeur par d&eacute;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 &agrave; utiliser les enregistrements MX.<br>
-+   Comme nous avons &agrave; authentifier le server d&eacute;couvert par le MX, 
-+   quelqu'un est capable d'usurper un faux enregistrement MX<br>
-+   pour &ecirc;tre capable de recevoir le mail, si son serveur peut présenter un 
-+   certificat délivré par un CA acceptable. La derni&egrave;re <br>
-+   partie n'est pas difficile si les certificat 'standarts' sont inclus (Verisign, 
-+   Thawte,...)<br>
-+   Le seul moyen de se prot&eacute;ger contre ce probl&egrave;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 &ecirc;tre les clefs) peuvent &ecirc;tre 
-+   obtenus auprès de tierces parties, qui peuvent &ecirc;tre une autorit&eacute; 
-+   de certification commerciale ou votre FAI. Tout le long vous aurez besoin de 
-+   certificats accept&eacute;s par d'autres entit&eacute;s sur internet, vous avez 
-+   donc &agrave; &ecirc;tre d'accord sur les entit&eacute;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&eacute;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&eacute;part. 
-+   Cependant,au d&eacute;but de la négociation, le client ne peut pas savoir que 
-+   la clef publique appartient r&eacute;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&eacute;e de serveur<br>
-+   - 1 clef publique de serveur sign&eacute;e par une autorit&eacute; 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&eacute;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 &agrave; vous d&eacute;cider sur la politique. 
-+   Le client qui va se connecter sur votre h&ocirc;te va comparer le nom dans le 
-+   certificat de votre serveur Ã   son FQDN (Fully Qualified Domain Name). Si ils 
-+   correspondent, l'identit&eacute; de votre serveur est prouv&eacute;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 
-+   &agrave; la fois.<br>
-+   Il y a des fournisseurs commerciaux (Thawte, Verisign, pour n'en citer que quelques 
-+   uns), leurs certificats CA sont bien distribu&eacute;s. Je ne sais pas pour 
-+   les autres pays mais en Allemagne le organisation de la recherche reseaux (DFN) a commenc&eacute; 
-+   un programme pour les universit&eacute;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 &ecirc;tes pr&ecirc;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 &ecirc;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 
-+   &ecirc;tre au format &quot;PEM&quot;. Puis vous avez &agrave; indiquer &agrave; 
-+   postfix o&ugrave; les trouver:<br>
-+   - La clef priv&eacute;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&eacute;cup&eacute;rer), une personne disposant d'une copie de votre clef 
-+   priv&eacute;e peut usurper votre identit&eacute;e. Ce n'est pas si facile que 
-+   &ccedil;a, du fait qu'il doit &ecirc;tre capable d'intercepter ou de rediriger 
-+   les paquets envoy&eacute;s vers votre serveur, mais j'ai d&eacute;ja vu bien 
-+   de choses arriver. Donc prot&eacute;gez cette clef avec :<br>
-+   <br>
-+   chown root /etc/postfix/key.pem ; chmod 400 /etc/postfix/key.pem <br>
-+   <br>
-+   Une autre possibilit&eacute; de protection est la 'phrase clef'. Ceci est toutefois 
-+   un probl&egrave;me, du fait que vous ayez &agrave; le taper Ã  chaque fois que 
-+   le server est d&eacute;marr&eacute;. Ceci a des inconvenients : premi&egrave;rement 
-+   vous devez le taper dans postfix &agrave; chaque fois que vous le red&eacute;marrez. 
-+   Deuxi&egrave;mement les process smtpd sont lanc&eacute;s ind&eacute;pendamment 
-+   &agrave; partir de master, dans ce cas master doit passer la 'phrase clef' aux 
-+   clients d'une fa&ccedil;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&eacute;e par le programme.<br>
-+   <br>
-+   - Le certificat serveur : ce certificat n'est pas secret, du fait qu'il est 
-+   pr&eacute;sent&eacute; &agrave; chaque client de toutes fa&ccedil;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&eacute;ner la clef priv&eacute;e et le certificat 
-+   dans le m&ecirc;me fichier.<br>
-+   <br>
-+   - Le certificat CA: pour avoir &eacute;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 &ecirc;tre en mesure de faire tourner Postfix/TLS.</p>
-+ <p>Postfix/TLS en mode client<br>
-+   <br>
-+   Quand il se connecte &agrave; un serveur offrant TLS postfix peut pr&eacute;senter 
-+   un certificat client de lui m&ecirc;me. Du fait de la r&eacute;alisation actuelle, 
-+   seulement un certificat ne peut Ãªtre contrôlé, ainsi il devrait Ãªtre Ã©mis depuis 
-+   votre propre nom d'hôte. Par d&eacute;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&eacute; sur les certificats clients. Le client pr&eacute;sente 
-+   un certificat d'un CA, qui est unique et ne peut &ecirc;tre usurp&eacute;.<br>
-+   Des clients peuvent avoir plusieus certificats &eacute;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 &agrave; 
-+   passer. Avec Netscape cela signifie qu'une fen&ecirc;tre est ouverte et seulement 
-+   le certificat client est list&eacute;.<br>
-+   Donc si vos clients ont d&eacute;j&agrave; des certificats &eacute;manant de 
-+   sources de confiances ce n'est pas n&eacute;cessaire de se cr&eacute;er des 
-+   probl&eacute;mes. Vous avez juste &agrave; r&eacute;cup&eacute;rer les certificats 
-+   CA et les rendre disponibles &agrave; Postfix/TLS. Si ce n'est pas suffisant, 
-+   vous pouvez toujours devenir votre propre CA pour cr&eacute;er facilement vos 
-+   certificats clients pour vos usagers (qui sont naturellement inutiles en dehors 
-+   de votre port&eacute;e)</p>
-+ <p>Lister les certificats CA<br>
-+   <br>
-+   Vous avez deux possibilit&eacute; de faire ceci:<br>
-+   1- Concat&eacute;nez les certificats CA au fichier smtp[d]_tls_CAfile que vous 
-+   avez cr&eacute;&eacute;. Ce fichier n'est certainement pas tr&egrave;s lisible 
-+   mais a l'avantage d'&ecirc;tre lu par smtpd avant le changement dans la cage 
-+   chroot et par conséquent fonctionne en mode chroot&eacute;.<br>
-+   2- Vous pouvez ajouter les certificats CA dans plusieurs fichiers avec des noms 
-+   ad&eacute;quats dans un r&eacute;pertoire de certificats sp&eacute;cifi&eacute; 
-+   par:<br>
-+   smtpd_tls_CApath = /etc/postfix/certs<br>
-+   N'oubliez pas de faire un $OPENSSL_HOME/bin/c_rehash /etc/postfix/certs apr&egrave;s 
-+   tout changement, car les tables de hachages sont utilis&eacute;es pour trouver 
-+   le bon certificat CA. Cette methode ne doit pas fonctionner en mode chroot&eacute;.</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 (&agrave; 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 &ecirc;tre suffisament s&eacute;curis&eacute;. 
-+   Je trouverai plus facilement une machine avec une mauvaise s&eacute;curit&eacute; 
-+   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&eacute;rieur, 
-+   m&ecirc;me depuis l'interieur vous pouvez prot&eacute;ger la base &quot;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&eacute;n&eacute;r&eacute;s par postfix sont envoyés 
-+   au syst&egrave;me de journalisation, la mise au point doit &ecirc;tre faite<br>
-+   en utilisant vos fichier de journalisation. Postfix/TLS supporte les niveaux 
-+   de journalisation de 0 (tr&egrave;s calme) &agrave; 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&eacute; de votre c&ocirc;t&eacute; 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 &agrave; des erreurs de connexions sans messages clairs. cela peut nous 
-+   aider d'utiliser Netscape 4.5x en tant que client et d'&eacute;tudier<br>
-+   soigneusement les informations ainsi que les boites de dialogue.<br>
-+   Je n'ai pas encore trouv&eacute; comment identifier le probl&egrave;me de postfix 
-+   &agrave; afficher un message appropri&eacute; dans le fichier de journalisation.<br>
-+   Si tout va bien ce sera possible sans modifier les biblioth&egrave;ques d'OpenSSL.</p>
-+ <p>Plateformes:</p>
-+ <p>Plateformes de d&eacute;veloppement:<br>
-+   OS: HP-UX 10.20 <br>
-+   OS: Linux 2.x (SuSE Linux) <br>
-+   <br>
-+   Succ&eacute;s enregistr&eacute;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&eacute;rop&eacute;rabilit&eacute;:<br>
-+   Sans compter le support par les solutions génériques d'emballage, il existe 
-+   des extensions particuli&egrave;rement travaill&eacute;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&eacute;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 &agrave; lui-m&ecirc;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&egrave;mes connus:<br>
-+   Ce logiciel en est qu'&agrave; ses d&eacute;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 &ecirc;tre r&eacute;solu avec OpenSSL 0.9.5<br>
-+   Cot&eacute; serveur: Outlook Express tout comme Internet explorer 5 fonctionneront 
-+   avec Postfix/TLS mais aucun certificat<br>
-+   client ne seront pr&eacute;sent&eacute;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&eacute; 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&eacute; serveur: Outlook Express (Mac) semble ne pas supporter la RFC2487. 
-+   Utilisez smtpd_tls_wrappermode=yes<br>
-+   sur un autre port.<br>
-+   Cot&eacute; client: MS Exchange m&ecirc;me en version r&eacute;cente offre STARTTLS 
-+   m&ecirc;me si ce dernier n'est pas configur&eacute; (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&eacute; 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.
This page took 1.198014 seconds and 4 git commands to generate.