]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2.0-RC2 v2.2.0-RC2
authorWietse Venema <wietse@porcupine.org>
Fri, 4 Mar 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 10 Feb 2018 21:10:55 +0000 (16:10 -0500)
19 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/main.cf
postfix/src/discard/discard.c
postfix/src/global/mail_version.h
postfix/src/master/master_vars.c
postfix/src/postdrop/postdrop.c
postfix/src/postqueue/postqueue.c
postfix/src/sendmail/sendmail.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_sasl_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/smtpd_sasl_glue.c
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_server.c
postfix/src/tls/tls_session.c

index 02f7b445ba0b4c673518e7340dfc6d96a2de879a..bd7e14502b8a59c9a33b3deb63e06f0abe5113a2 100644 (file)
@@ -10405,154 +10405,43 @@ Apologies for any names omitted.
        FROM: or CC: by From: or Cc:. Files: cleanup/cleanup_message.c,
        smtp/smtp_proto.c.
 
-Open problems:
+20050228
+
+       Cleanup/portability: missing #includes and bad prototypes.
+       Matthias Andree, Carsten Hoeger, and others.
+
+20050302
+
+       Workaround: make TLS session caching work with perverse
+       sites that have multiple servers per hostname or even
+       multiple servers per IP address, but no shared TLS session
+       cache. The SMTP client TLS session cache is now indexed by
+       (server hostname, server address, server port, server helo
+       hostname). After an idea by Victor Duchovni. Files:
+       smtp/smtp_proto.c, tls/tls_client.c.
+
+20050303
+
+       Bugfix (bug inherited from Postfix/TLS patch): a rare 9kbyte
+       memory leak when in-memory TLS session information expires;
+       found by setting the expiry time shorter than the time to
+       deliver one or two messages with a very slow machine.  This
+       was due to a missing SSL_SESSION_free() call in the "new
+       session" call-back routines. Found by Victor Duchovni.
+       Files: tls/tls_client.c, tls/tls_server.c.
+
+       Workaround: OpenSSL is overly agressive when purging a
+       not-yet expired entry from a full in-memory cache: it also
+       purges the entry from the on-disk server session cache.
+       Workaround is to let only the tlsmgr purge entries from the
+       on-disk server session cache.  Found by Victor Duchovni.
+       File: tls/tls_server.c.
+
+20050304
+
+       Postfix releases are now signed with Wietse's new PGP key.
+       The old key was getting a bit short for today's standards.
+       The new public key can be found on the Postfix download
+       webpage. As proof of authenticity the new PGP key is signed
+       with Wietse's old PGP key.
 
-       Med: disable header address rewriting after XCLIENT?
-       Introduce a better concept of original submission?
-
-       Low: 9kbyte memory leak when expired in-memory session
-       information is removed by SSL_CTX_flush_sessions(); found
-       by setting the expiry time shorter than the time to deliver
-       one or two messages. Postfix processes are short-lived,
-       and the occurrance of this leak is rare enough that it is
-       a low priority.
-
-       Low: configurable order of local(8) delivery methods.
-
-       Med: local and remote source port and IP address for smtpd
-       policy hook.
-
-       Med: smtp_connect_timeout_budget (default: 3x smtp_connect_timeout)
-       to limit the total time spent trying to connect.
-
-       Med: transform IPv4-in-IPv6 address literals to IPv4 form
-       when comparing against local IP addresses?
-
-       Med: transform IPv4-in-IPv6 address literals to IPv4 form
-       when eliminating MX mailer loops?
-
-       Med: Postfix requires [] around IPv6 address information
-       in match lists such as mynetworks, debug_peer_list etc.,
-       but the [] must not be specified in access(5) maps. Other
-       places don't care.  For now, this gotcha is documented in
-       IPV6_README and in postconf(5) with each feature that may
-       use IPv6 address information. The general recommendation
-       is not to use [] unless absolutely necessary.
-
-       Med: the partial address matching of IPv6 addresses in
-       access(5) maps is a bit lame: it repeatedly truncates the
-       last ":octetpair" from the printable address representation
-       until a match is found or until truncation is no longer
-       possible.  Since one or more ":" are usually omitted from
-       the printable IPv6 address representation, this does not
-       really try all the possibilities that one might expect to
-       be tried. For now, this gotcha is documented in access(5).
-
-       Med: the TLS certificate verification depth parameters
-       never worked.
-
-       Med: eliminate the tls_info data structure.
-
-       Low: reject HELO with any domain name or IP address that
-       this MTA is the final destination for.
-
-       Low: should the Delivered-To: test in local(8) be configurable?
-
-       Low: make mail_addr_find() lookup configurable.
-
-       Low: update events.c so that 1-second timer requests do
-       not suffer from rounding errors. This is needed for 1-second
-       SMTP session caching time limits. A 1-second interval would
-       become arbitrarily short when an event is scheduled just
-       before the current second rolls over.
-
-       Low: per-sender resolver personalities?
-
-       Low: configurable internal/system locking method.
-
-       Low: make sure CCARGS -I options come at the end.
-
-       Low: add INSTALL section for pre-existing Postfix systems.
-
-       Low: add INSTALL section for pre-existing RPM Postfixes.
-
-       Low: disallow smtpd_recipient_limit < 100 (the RFC minimum).
-
-       Low: noise filter: allow smtp(8) to retry immediately if
-       all MXes return a quick ECONNRESET or 4xx reply during the
-       initial handshake.
-
-       Low: make post-install a "postfix-only script" so it can
-       take data from the environment instead of main.cf.
-
-       Low: randomize deferred mail backoff.
-
-       Med: separate ulimit for delivery to command?
-
-       Med: option to open queue file early, after MAIL FROM.
-
-       Low: log xdelay (esp. for SMTP and delivery to command).
-
-       Med: silly queue file bit so that the queue manager doesn't
-       skip files when fast flush is requested while a queue scan
-       is in progress. The bit is set by the flush server and is
-       reset when the mail is deferred, so that it survives queue
-       manager restart.
-
-       Med: postsuper -r should do something with recipients in
-       bounce logfiles.
-
-       Low: postsuper re-run after renaming files, but only a
-       limited number of times.
-
-       Low: smtp-source may block when sending large test messages.
-
-       Med: make qmgr recipient bounce/defer activity asynchronous
-       or add a multi-recipient operation that reduces overhead.
-       One possibility is to pass delivery requests to a retry(8)
-       delivery agent which is error(8) in disguise, and which
-       calls defer_append() instead of bounce_append().
-
-       Low: postmap/postalias should not try to open a bogus file
-       when given an unsupported dictionary type.
-
-       Med: find a way to log the sender address when MAIL FROM
-       is rejected due to lack of disk space.
-
-       Low: revise other local delivery agent duplicate filters.
-
-       Low: all table lookups should consistently use internalized
-       (unquoted) or externalized (quoted) forms as lookup keys.
-       smtpd, qmgr, local, etc. use unquoted address forms as
-       keys.  cleanup uses quoted forms.
-
-       Low: have a configurable list of errno values for mailbox
-       or maildir delivery that result in deferral rather than
-       bouncing mail.
-
-       Low: after reorganizing configuration parameters, add flags
-       to all parameters whose value can be read from file.
-
-       Medium: need in-process caching for map lookups. LDAP
-       servers seem to need this in particular. Need a way to
-       expire cached results that are too old.
-
-       Low: generic showq protocol, to allow for more intelligent
-       processing than just mailq. Maybe marry this with postsuper.
-
-       Low: default domain for appending to unqualified recipients,
-       so that unqualified names can be delivered locally.
-
-       Low: The $process_id_directory setting is not used anywhere
-       in Postfix. Problem reported by Michael Smith, texas.net.
-       This should be documented, or better, the code should warn
-       about attempts to set read-only parameters.
-
-       Low: postconf -e edits parameters that postconf won't list.
-
-       Low: while converting 8bit text to quoted-printable, perhaps
-       use =46rom to avoid having to produce >From when delivering
-       to mailbox.
-
-       virtual_mailbox_path expression like forward_path, so that
-       people can specify prefix and suffix.
index 54ba7b6ce42197b4fc2cbad6e4b52ee0156de57b..a973f43e098ac24134b47f81a4542705aa9af748 100644 (file)
@@ -21,8 +21,8 @@ the following sections of this document.
 from third-party patches.
 
 - SMTP client-side connection reuse. This can dramatically speed
-up deliveries to high-volume destinations that have good and
-non-responding mail servers.
+up deliveries to high-volume destinations that have some servers
+that respond, and some non-responding mail servers.
 
 - By default, message header address rewriting is now disabled for
 SMTP mail from other systems.  Thus, spam from poorly written
@@ -75,8 +75,8 @@ the Postfix/TLS patch.
 [Feature 20040919] The upgrade procedure adds the discard service
 to the master.cf file.
 
-[Feature 20040720] The upgrade procedure adds the scache (connection
-cache) service to the master.cf file.
+[Feature 20040720] The upgrade procedure adds the scache (shared
+connection cache) service to the master.cf file.
 
 Major changes - IPv6 support
 ----------------------------
@@ -116,15 +116,6 @@ Postfix/TLS patch by Lutz Jaenicke.  TLS support is not compiled
 in by default.  For more information about Postfix 2.2 TLS support,
 see the TLS_README document.
 
-[Feature 20050209] The Postfix SMTP server policy delegation protocol
-now supplies TLS client certificate information after successful
-verification.  The new policy delegation protocol attribute names
-are ccert_subject, ccert_issuer and ccert_fingerprint.
-
-[Feature 20050208] New "check_ccert_maps maptype:mapname" feature
-to enforce access control based on hexadecimal client certificate
-fingerprints.
-
 [Incompat 20041210] Postfix version 2.2 TLS support differs from
 the Postfix/TLS patch by Lutz Jaenicke in a few minor ways.
 
@@ -150,6 +141,15 @@ the Postfix/TLS patch by Lutz Jaenicke in a few minor ways.
   (PRNG) pool, and in order to access the TLS session cache databases.
   Such a protocol cannot be run across fifos.
 
+[Feature 20050209] The Postfix SMTP server policy delegation protocol
+now supplies TLS client certificate information after successful
+verification.  The new policy delegation protocol attribute names
+are ccert_subject, ccert_issuer and ccert_fingerprint.
+
+[Feature 20050208] New "check_ccert_maps maptype:mapname" feature
+to enforce access control based on hexadecimal client certificate
+fingerprints.
+
 Major changes - SMTP client connection cache
 --------------------------------------------
 
index 272d9866122082413e14626dc1759ae6194422b7..517277974043c7f2f54c40a7adedd2c589feb705 100644 (file)
@@ -582,11 +582,24 @@ debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         xxgdb $daemon_directory/$process_name $process_id & sleep 5
 
-# If you don't have X installed on the Postfix machine, try:
+# If you can't use X, use this to capture the call stack when a
+# daemon crashes. The result is in a file in the configuration
+# directory, and is named after the process name and the process ID.
+#
 # debugger_command =
 #      PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont;
 #      echo where) | gdb $daemon_directory/$process_name $process_id 2>&1
 #      >$config_directory/$process_name.$process_id.log & sleep 5
+#
+# Another possibility is to run gdb under a detached screen session.
+# To attach to the screen sesssion, su root and run "screen -r
+# <id_string>" where <id_string> uniquely matches one of the detached
+# sessions (from "screen -list").
+#
+# debugger_command =
+#      PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; screen
+#      -dmS $process_name gdb $daemon_directory/$process_name
+#      $process_id & sleep 1
 
 # INSTALL-TIME CONFIGURATION INFORMATION
 #
index 09b562745daa132bee82a101ba1f4bd50c3331f5..235367f06e72882f1ab5f2e366382c4a33e467c9 100644 (file)
 #include <bounce.h>
 #include <deliver_completed.h>
 #include <flush_clnt.h>
+#include <sent.h>
 
 /* Single server skeleton. */
 
index 111660d3cde75e6189869662570f8467fc1e4bec..5ba0f79258d1e782f1eb89c470592e860c2e3baa 100644 (file)
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20050227"
+#define MAIL_RELEASE_DATE      "20050304"
 #define MAIL_VERSION_NUMBER    "2.2"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #ifdef SNAPSHOT
 #define DEF_MAIL_VERSION       MAIL_VERSION_NUMBER "-" MAIL_RELEASE_DATE
 #else
-#define DEF_MAIL_VERSION       MAIL_VERSION_NUMBER "-RC1"
+#define DEF_MAIL_VERSION       MAIL_VERSION_NUMBER "-RC2"
 #endif
 extern char *var_mail_version;
 
index 53b37220b98cb6b45042b06a54806f8bf727a93c..33869b8c8df690a1a8a77285ded15f18ce5e0c02 100644 (file)
@@ -25,6 +25,7 @@
 /* System library. */
 
 #include <sys_defs.h>
+#include <string.h>
 #include <unistd.h>
 
 /* Utility library. */
index 13e3b8057fff5491d8aeee04243e4406ef9f0483..d5cf5fa0a040470ba117b82c7c997c8ee6449591 100644 (file)
  /*
   * Local mail submission access list.
   */
-static char *var_submit_acl;
+char   *var_submit_acl;
 
 static CONFIG_STR_TABLE str_table[] = {
     VAR_SUBMIT_ACL, DEF_SUBMIT_ACL, &var_submit_acl, 0, 0,
index 200079ea251ddeee862ad3a95bebe62ede9902fa..6f6ae1d90cdf687b3b70c3dba784e82c0182d89e 100644 (file)
  /*
   * Queue manipulation access lists.
   */
-static char *var_flush_acl;
-static char *var_showq_acl;
+char   *var_flush_acl;
+char   *var_showq_acl;
 
 static CONFIG_STR_TABLE str_table[] = {
     VAR_FLUSH_ACL, DEF_FLUSH_ACL, &var_flush_acl, 0, 0,
index b36aa904c7314fd8f78653ecc95629a35e3b920f..d4d8645fc7a92f3210135cde399bf6c9f09c6bbb 100644 (file)
@@ -447,7 +447,7 @@ typedef struct SM_STATE {
  /*
   * Mail submission ACL
   */
-static char *var_submit_acl;
+char   *var_submit_acl;
 
 static CONFIG_STR_TABLE str_table[] = {
     VAR_SUBMIT_ACL, DEF_SUBMIT_ACL, &var_submit_acl, 0, 0,
index 53d918656066fc12ddc9fbe843741b8dabeb3c77..2aa7a363c06939ab0421cfdda0f2a25fe5a415c9 100644 (file)
@@ -173,6 +173,7 @@ typedef struct SMTP_SESSION {
     char   *host;                      /* mail exchanger */
     char   *addr;                      /* mail exchanger */
     char   *namaddr;                   /* mail exchanger */
+    char   *helo;                      /* helo response */
     unsigned port;                     /* network byte order */
 
     VSTRING *buffer;                   /* I/O buffer */
index 964fd5773164dd137aa9bfdfa1aeea2957f9da95..ebbe53f1aa8d7ce970c26a98315fa2d91d47dd40 100644 (file)
@@ -219,6 +219,8 @@ char   *xfer_request[SMTP_STATE_LAST] = {
     "QUIT command",
 };
 
+static int smtp_start_tls(SMTP_STATE *, int);
+
 /* smtp_helo - perform initial handshake with SMTP server */
 
 int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
@@ -245,7 +247,6 @@ int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
     int     discard_mask;
 
 #ifdef USE_TLS
-    static int smtp_start_tls(SMTP_STATE *, int);
     int     saved_features = session->features;
 
 #endif
@@ -361,9 +362,22 @@ int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
      * MicroSoft implemented AUTH based on an old draft.
      */
     lines = resp->str;
-    while ((words = mystrtok(&lines, "\n")) != 0) {
+    for (n = 0; (words = mystrtok(&lines, "\n")) != 0; /* see below */ ) {
        if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) {
-           if (strcasecmp(word, "8BITMIME") == 0) {
+           if (n == 0) {
+               if (session->helo != 0)
+                   myfree(session->helo);
+               session->helo = lowercase(mystrdup(word));
+               if (strcasecmp(word, var_myhostname) == 0
+                   && (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) != 0) {
+                   msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
+                            session->namaddr, var_myhostname);
+                   return (smtp_site_fail(state,
+                    (session->features & SMTP_FEATURE_BEST_MX) ? 550 : 450,
+                                        "mail for %s loops back to myself",
+                                          request->nexthop));
+               }
+           } else if (strcasecmp(word, "8BITMIME") == 0) {
                if ((discard_mask & EHLO_MASK_8BITMIME) == 0)
                    session->features |= SMTP_FEATURE_8BITMIME;
            } else if (strcasecmp(word, "PIPELINING") == 0) {
@@ -396,16 +410,8 @@ int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
                if ((discard_mask & EHLO_MASK_AUTH) == 0)
                    smtp_sasl_helo_auth(session, words);
 #endif
-           } else if (strcasecmp(word, var_myhostname) == 0) {
-               if (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) {
-                   msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
-                            session->namaddr, var_myhostname);
-                   return (smtp_site_fail(state,
-                    (session->features & SMTP_FEATURE_BEST_MX) ? 550 : 450,
-                                        "mail for %s loops back to myself",
-                                          request->nexthop));
-               }
            }
+           n++;
        }
     }
     if (msg_verbose)
@@ -554,6 +560,7 @@ int     smtp_helo(SMTP_STATE *state, NOCLOBBER int misc_flags)
 static int smtp_start_tls(SMTP_STATE *state, int misc_flags)
 {
     SMTP_SESSION *session = state->session;
+    VSTRING *serverid;
 
     /*
      * Turn off SMTP connection caching. When the TLS handshake succeeds, we
@@ -580,13 +587,26 @@ static int smtp_start_tls(SMTP_STATE *state, int misc_flags)
      * follow below AFTER the tls_client_start() call. These tests should be
      * done inside tls_client_start() or its call-backs, to keep the SMTP
      * client code clean (as it is in the SMTP server).
+     * 
+     * The following assumes sites that use TLS in a perverse configuration:
+     * multiple hosts per hostname, or even multiple hosts per IP address.
+     * All this without a shared TLS session cache, and they still want to
+     * use TLS session caching???
      */
+    serverid = vstring_alloc(10);
+    vstring_sprintf(serverid, "%s:%s:%u",
+                   session->host, session->addr,
+                   ntohs(session->port));
+    if (session->helo && strcasecmp(session->host, session->helo) != 0)
+       vstring_sprintf_append(serverid, ":%s", session->helo);
     session->tls_context =
        tls_client_start(smtp_tls_ctx, session->stream,
                         var_smtp_starttls_tmout,
                         session->tls_enforce_peername,
                         session->host,
+                        lowercase(vstring_str(serverid)),
                         &(session->tls_info));
+    vstring_free(serverid);
     if (session->tls_context == 0)
        return (smtp_site_fail(state, 450,
                               "Cannot start TLS: handshake failure"));
@@ -741,10 +761,10 @@ static void smtp_header_rewrite(void *context, int header_class,
     char   *end_line;
 
     /*
-     * Rewrite primary header addresses that match the smtp_generic_maps.
-     * The cleanup server already enforces that all headers have proper
-     * lengths and that all addresses are in proper form, so we don't have to
-     * repeat that.
+     * Rewrite primary header addresses that match the smtp_generic_maps. The
+     * cleanup server already enforces that all headers have proper lengths
+     * and that all addresses are in proper form, so we don't have to repeat
+     * that.
      */
     if (header_info && header_class == MIME_HDR_PRIMARY
        && (header_info->flags & (HDR_OPT_SENDER | HDR_OPT_RECIP)) != 0) {
index e2a35e0e659e678d9fec3ecf02dd6c6806891880..4dcd20b05c630202787aaa1ad8c1abfa6bc944f8 100644 (file)
@@ -98,8 +98,8 @@ static const char *smtp_sasl_compat_mechs(const char *words)
 
     save_mech = mech_list = mystrdup(words);
 
-    while (mech = mystrtok(&mech_list, " \t")) {
-       if (string_list_match(smtp_sasl_mechs, mech)) {
+    while ((mech = mystrtok(&mech_list, " \t")) != 0) {
+       if (string_list_match(smtp_sasl_mechs, mech)) {
            if (VSTRING_LEN(buf) > 0)
                VSTRING_ADDCH(buf, ' ');
            vstring_strcat(buf, mech);
index 75e7b6dcf7f4cfa0a1bb376c6f8e432540942bf6..64cb7f2735eb8ddcc07fcc68cdafba0f986a829f 100644 (file)
@@ -96,6 +96,7 @@
 #include <sys_defs.h>
 #include <stdlib.h>
 #include <string.h>
+#include <netinet/in.h>
 
 #ifdef STRCASECMP_IN_STRINGS_H
 #include <strings.h>
 /* Application-specific. */
 
 #include "smtp.h"
+#include "smtp_sasl.h"
 
 #define STR(x) vstring_str(x)
 
@@ -211,6 +213,7 @@ SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, const char *dest,
     session->host = mystrdup(host);
     session->addr = mystrdup(addr);
     session->namaddr = concatenate(host, "[", addr, "]", (char *) 0);
+    session->helo = 0;
     session->port = port;
     session->features = 0;
 
@@ -298,6 +301,8 @@ void    smtp_session_free(SMTP_SESSION *session)
     myfree(session->host);
     myfree(session->addr);
     myfree(session->namaddr);
+    if (session->helo)
+       myfree(session->helo);
 
     vstring_free(session->buffer);
     vstring_free(session->scratch);
index b3c3587ccb12f2294582b036d8a72e73ad96a83f..63f3d81831ad02a0631096f1cf5ce6bbfc2c218b 100644 (file)
@@ -93,6 +93,7 @@
 #include <mymalloc.h>
 #include <namadr_list.h>
 #include <name_mask.h>
+#include <stringops.h>
 
 /* Global library. */
 
index a2ce2713994cb7a86535b3ea2d8027f7218d676c..a6514d776526edfec30c359fc4ca7029d9e6e115 100644 (file)
@@ -52,6 +52,7 @@ typedef struct {
     SSL    *con;
     BIO    *internal_bio;              /* postfix/TLS side of pair */
     BIO    *network_bio;               /* network side of pair */
+    char   *serverid;                  /* unique server identifier */
     char    peer_subject[CCERT_BUFSIZ];
     char    peer_issuer[CCERT_BUFSIZ];
     char    peer_CN[CCERT_BUFSIZ];
@@ -67,6 +68,18 @@ typedef struct {
 
 #define TLS_BIO_BUFSIZE        8192
 
+#define NEW_TLS_CONTEXT(p) do { \
+       p = (TLScontext_t *) mymalloc(sizeof(*p)); \
+       memset((char *) p, 0, sizeof(*p)); \
+       p->serverid = 0; \
+    } while (0)
+    
+#define FREE_TLS_CONTEXT(p) do { \
+       if ((p)->serverid) \
+           myfree((p)->serverid); \
+       myfree((char *) (p)); \
+    } while (0)
+
 typedef struct {
     int     peer_verified;
     int     hostname_matched;
@@ -88,7 +101,8 @@ extern const tls_info_t tls_info_zero;
   */
 extern SSL_CTX *tls_client_init(int);
 extern TLScontext_t *tls_client_start(SSL_CTX *, VSTREAM *, int, int,
-                                             const char *, tls_info_t *);
+                                             const char *, const char *,
+                                             tls_info_t *);
 
 #define tls_client_stop(ctx , stream, timeout, failure, tls_info) \
        tls_session_stop((ctx), (stream), (timeout), (failure), (tls_info))
@@ -183,7 +197,6 @@ extern int tls_set_my_certificate_key_info(SSL_CTX *, const char *,
   * tls_misc.c
   */
 extern int TLScontext_index;
-extern int TLSpeername_index;
 
 extern void tls_print_errors(void);
 extern void tls_info_callback(const SSL *, int, int);
index 95002bda2797f7dbe56d30791d12741d5465ed09..a47e322dacc79784a5956ce55ac33b584a6b6f93 100644 (file)
@@ -9,13 +9,15 @@
 /*     SSL_CTX *tls_client_init(verifydepth)
 /*     int     verifydepth; /* unused */
 /*
-/*     TLScontext_t *tls_client_start(client_ctx, stream, timeout, peername,
-/*                                     peeraddr, tls_info)
+/*     TLScontext_t *tls_client_start(client_ctx, stream, timeout, 
+/*                                     enforce_peername, peername, 
+/*                                     serverid, tls_info)
 /*     SSL_CTX *client_ctx;
 /*     VSTREAM *stream;
 /*     int     timeout;
+/*     int     enforce_peername;
 /*     const char *peername;
-/*     const char *peeraddr;
+/*     const char *serverid;
 /*     tls_info_t *tls_info;
 /*
 /*     void    tls_client_stop(client_ctx, stream, failure, tls_info)
@@ -36,6 +38,9 @@
 /*     passed as argument. We expect that network buffers are flushed and the
 /*     TLS handshake can begin immediately. Information about the peer
 /*     is stored into the tls_info structure passed as argument.
+/*     The serverid argument specifies a string that hopefully
+/*     uniquely identifies a server. It is used as the client
+/*     session cache lookup key.
 /*
 /*     tls_client_stop() sends the "close notify" alert via
 /*     SSL_shutdown() to the peer and resets all connection specific
@@ -144,12 +149,10 @@ static int client_verify_callback(int ok, X509_STORE_CTX *ctx)
 
 /* load_clnt_session - load session from client cache (non-callback) */
 
-static SSL_SESSION *load_clnt_session(const char *hostname,
+static SSL_SESSION *load_clnt_session(const char *cache_id,
                                              int enforce_peername)
 {
     SSL_SESSION *session = 0;
-    char   *cache_id;
-    VSTRING *cache_id_buffer;
     VSTRING *session_data = vstring_alloc(2048);
     int     flags = 0;
 
@@ -158,7 +161,6 @@ static SSL_SESSION *load_clnt_session(const char *hostname,
     /*
      * Prepare the query.
      */
-    cache_id = lowercase(mystrdup(hostname));
     if (var_smtp_tls_loglevel >= 3)
        msg_info("looking for session %s in client cache", cache_id);
     if (enforce_peername)
@@ -174,97 +176,34 @@ static SSL_SESSION *load_clnt_session(const char *hostname,
        if (session) {
            if (var_smtp_tls_loglevel >= 3)
                msg_info("reloaded session %s from client cache", cache_id);
-           cache_id_buffer =
-               (VSTRING *) SSL_SESSION_get_ex_data(session, TLSpeername_index);
-           vstring_strcpy(cache_id_buffer, cache_id);
        }
     }
 
     /*
      * Clean up.
      */
-    myfree(cache_id);
     vstring_free(session_data);
 
     return (session);
 }
 
- /*
-  * The client session cache is indexed by peer name, not by session id. The
-  * following routines maintain string storage for the peer name in an
-  * SSL_SESSION object. We use VSTRING buffers so that we don't have to worry
-  * about hostname length problems.
-  */
-
-/* new_cache_id_func - create space for peer name in SSL_SESSION object */
-
-static int new_cache_id_func(void *unused_parent, void *unused_ptr,
-                                    CRYPTO_EX_DATA *ad, int idx,
-                                    long unused_argl, void *unused_argp)
-{
-    VSTRING *cache_id_buffer;
-
-    cache_id_buffer = vstring_alloc(32);
-    return (CRYPTO_set_ex_data(ad, idx, (void *) cache_id_buffer));
-}
-
-/* free_cache_id_func - destroy space for peer name in SSL_SESSION object */
-
-static void free_cache_id_func(void *unused_parent, void *unused_ptr,
-                                      CRYPTO_EX_DATA *ad, int idx,
-                                      long unused_argl, void *unused_argp)
-{
-    VSTRING *cache_id_buffer;
-
-    cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(ad, idx);
-    vstring_free(cache_id_buffer);
-}
-
-/* dup_cache_id_func - duplicate peer name when SSL_SESSION is duplicated */
-
-static int dup_cache_id_func(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from,
-          void *unused_from_d, int idx, long unused_argl, void *unused_argp)
-{
-    const char *myname = "dup_cache_id_func";
-    VSTRING *old_cache_id_buffer;
-    VSTRING *new_cache_id_buffer;
-
-    old_cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(from, idx);
-    if (old_cache_id_buffer == 0) {
-       msg_warn("%s: cannot get old SSL_SESSION peer name buffer", myname);
-       return (0);
-    }
-    new_cache_id_buffer = (VSTRING *) CRYPTO_get_ex_data(to, idx);
-    if (new_cache_id_buffer == 0) {
-       msg_warn("%s: cannot get new SSL_SESSION peer name buffer", myname);
-       return (0);
-    }
-    vstring_strcpy(new_cache_id_buffer, STR(old_cache_id_buffer));
-    return (1);
-}
-
 /* new_client_session_cb - name new session and save it to client cache */
 
 static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
 {
     TLScontext_t *TLScontext;
     VSTRING *session_data;
-    VSTRING *cache_id_buffer;
+    const char *cache_id;
     int     flags = 0;
 
     /*
-     * Attach the cache ID string to the session object. Don't worry about
-     * the length; that is the concern of the code that updates the session
-     * cache.
+     * Look up the cache ID string for this session object.
      */
-    cache_id_buffer =
-       (VSTRING *) SSL_SESSION_get_ex_data(session, TLSpeername_index);
     TLScontext = SSL_get_ex_data(ssl, TLScontext_index);
-    vstring_strcpy(cache_id_buffer, TLScontext->peername_save);
-    lowercase(STR(cache_id_buffer));           /* just in case */
+    cache_id = TLScontext->serverid;
 
     if (var_smtp_tls_loglevel >= 3)
-       msg_info("save session %s to client cache", STR(cache_id_buffer));
+       msg_info("save session %s to client cache", cache_id);
 
     /*
      * Remember whether peername matching was enforced when the session was
@@ -295,7 +234,7 @@ static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
      */
     session_data = tls_session_passivate(session);
     if (session_data)
-       tls_mgr_update(tls_client_cache, STR(cache_id_buffer),
+       tls_mgr_update(tls_client_cache, cache_id,
                       OPENSSL_VERSION_NUMBER, flags,
                       STR(session_data), LEN(session_data));
 
@@ -304,6 +243,7 @@ static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
      */
     if (session_data)
        vstring_free(session_data);
+    SSL_SESSION_free(session);                 /* 200502 */
 
     return (1);
 }
@@ -479,19 +419,6 @@ SSL_CTX *tls_client_init(int unused_verifydepth)
     if (TLScontext_index < 0)
        TLScontext_index = SSL_get_ex_new_index(0, "TLScontext ex_data index",
                                                NULL, NULL, NULL);
-
-    /*
-     * Create a global index so that we can attach peer name information to
-     * SSL_SESSION objects; the client session cache manager uses this to
-     * generate cache ID strings.
-     */
-    if (TLSpeername_index < 0)
-       TLSpeername_index = SSL_SESSION_get_ex_new_index(0,
-                                               "TLSpeername ex_data index",
-                                                        new_cache_id_func,
-                                                        dup_cache_id_func,
-                                                        free_cache_id_func);
-
     return (client_ctx);
 }
 
@@ -500,14 +427,15 @@ SSL_CTX *tls_client_init(int unused_verifydepth)
   * buffers are flushed and the "220 Ready to start TLS" was received by us,
   * so that we can immediately start the TLS handshake process.
   */
-TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout,
+TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream,
+                                      int timeout,
                                       int enforce_peername,
                                       const char *peername,
+                                      const char *serverid,
                                       tls_info_t *tls_info)
 {
     int     sts;
-    SSL_SESSION *session,
-           *old_session;
+    SSL_SESSION *session, *old_session;
     SSL_CIPHER *cipher;
     X509   *peer;
     int     verify_flags;
@@ -526,24 +454,24 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout
      */
 #define PEERNAME_SIZE sizeof(TLScontext->peername_save)
 
-    TLScontext = (TLScontext_t *) mymalloc(sizeof(TLScontext_t));
-    memset((char *) TLScontext, 0, sizeof(*TLScontext));
+    NEW_TLS_CONTEXT(TLScontext);
     TLScontext->log_level = var_smtp_tls_loglevel;
     strncpy(TLScontext->peername_save, peername, PEERNAME_SIZE - 1);
     TLScontext->peername_save[PEERNAME_SIZE - 1] = 0;
     (void) lowercase(TLScontext->peername_save);
+    TLScontext->serverid = mystrdup(serverid);
 
     if ((TLScontext->con = (SSL *) SSL_new(client_ctx)) == NULL) {
        msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
        tls_print_errors();
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
     if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
        msg_info("Could not set application data for 'TLScontext->con'");
        tls_print_errors();
        SSL_free(TLScontext->con);
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
 
@@ -574,7 +502,7 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout
        msg_info("Could not obtain BIO_pair");
        tls_print_errors();
        SSL_free(TLScontext->con);
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
     old_session = NULL;
@@ -587,7 +515,7 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout
      * will be reused.
      */
     if (tls_client_cache) {
-       old_session = load_clnt_session(peername, enforce_peername);
+       old_session = load_clnt_session(serverid, enforce_peername);
        if (old_session) {
            SSL_set_session(TLScontext->con, old_session);
            SSL_SESSION_free(old_session);      /* 200411 */
@@ -661,7 +589,7 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream, int timeout
        }
        SSL_free(TLScontext->con);
        BIO_free(TLScontext->network_bio);      /* 200411 */
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
     if (var_smtp_tls_loglevel >= 3 && SSL_session_reused(TLScontext->con))
index 2828f30081e27bd3f4139a3aa3b7ea2642144244..03976abc7132e9eca33553f4d6545581b763d804 100644 (file)
@@ -82,7 +82,6 @@
   * so that it can be accessed by call-back routines.
   */
 int     TLScontext_index = -1;
-int     TLSpeername_index = -1;
 
 /* tls_print_errors - print and clear the error stack */
 
index 5b8efba5dfb270f33dc86c411acfc8ab807f9985..d71955eabd11be536fb9975b3b560bb245ab3d5f 100644 (file)
@@ -191,28 +191,6 @@ static SSL_SESSION *get_server_session_cb(SSL *unused_ssl,
     return (session);
 }
 
-/* remove_server_session_cb - callback to remove session from server cache */
-
-static void remove_server_session_cb(SSL_CTX *unused_ctx, SSL_SESSION *session)
-{
-    VSTRING *cache_id;
-
-    /*
-     * Encode the session ID.
-     */
-    cache_id =
-       MAKE_SERVER_CACHE_ID(session->session_id, session->session_id_length);
-    if (var_smtpd_tls_loglevel >= 3)
-       msg_info("remove session %s from server cache", STR(cache_id));
-
-    /*
-     * Delete the session from cache.
-     */
-    tls_mgr_delete(tls_server_cache, STR(cache_id));
-
-    vstring_free(cache_id);
-}
-
 /* new_server_session_cb - callback to save session to server cache */
 
 static int new_server_session_cb(SSL *unused_ssl, SSL_SESSION *session)
@@ -243,6 +221,7 @@ static int new_server_session_cb(SSL *unused_ssl, SSL_SESSION *session)
     if (session_data)
        vstring_free(session_data);
     vstring_free(cache_id);
+    SSL_SESSION_free(session);                 /* 200502 */
 
     return (1);
 }
@@ -425,6 +404,13 @@ SSL_CTX *tls_server_init(int unused_verifydepth, int askcert)
 
     /*
      * The session cache is implemented by the tlsmgr(8) server.
+     * 
+     * XXX 200502 Surprise: when OpenSSL purges an entry from the in-memory
+     * cache, it also attempts to purge the entry from the on-disk cache.
+     * This is undesirable, especially when we set the in-memory cache size
+     * to 1. For this reason we don't allow OpenSSL to purge on-disk cache
+     * entries, and leave it up to the tlsmgr process instead. Found by
+     * Victor Duchovni.
      */
     if (tls_mgr_policy(&cache_types) == TLS_MGR_STAT_OK
        && (tls_server_cache = (cache_types & TLS_MGR_SCACHE_SERVER)) != 0) {
@@ -432,7 +418,6 @@ SSL_CTX *tls_server_init(int unused_verifydepth, int askcert)
                      SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
        SSL_CTX_sess_set_get_cb(server_ctx, get_server_session_cb);
        SSL_CTX_sess_set_new_cb(server_ctx, new_server_session_cb);
-       SSL_CTX_sess_set_remove_cb(server_ctx, remove_server_session_cb);
     }
 
     /*
@@ -474,14 +459,13 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * Allocate a new TLScontext for the new connection and get an SSL
      * structure. Add the location of TLScontext to the SSL to later retrieve
      * the information inside the tls_verify_certificate_callback().
-     *
+     * 
      * XXX Need a dedicated procedure for consistent initialization of all the
      * fields in this structure.
      */
 #define PEERNAME_SIZE sizeof(TLScontext->peername_save)
 
-    TLScontext = (TLScontext_t *) mymalloc(sizeof(TLScontext_t));
-    memset((char *) TLScontext, 0, sizeof(*TLScontext));
+    NEW_TLS_CONTEXT(TLScontext);
     TLScontext->log_level = var_smtpd_tls_loglevel;
     strncpy(TLScontext->peername_save, peername, PEERNAME_SIZE - 1);
     TLScontext->peername_save[PEERNAME_SIZE - 1] = 0;
@@ -490,14 +474,14 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     if ((TLScontext->con = (SSL *) SSL_new(server_ctx)) == NULL) {
        msg_info("Could not allocate 'TLScontext->con' with SSL_new()");
        tls_print_errors();
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
     if (!SSL_set_ex_data(TLScontext->con, TLScontext_index, TLScontext)) {
        msg_info("Could not set application data for 'TLScontext->con'");
        tls_print_errors();
        SSL_free(TLScontext->con);
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
 
@@ -528,7 +512,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
        msg_info("Could not obtain BIO_pair");
        tls_print_errors();
        SSL_free(TLScontext->con);
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
 
@@ -577,7 +561,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
        tls_print_errors();
        SSL_free(TLScontext->con);
        BIO_free(TLScontext->network_bio);      /* 200411 */
-       myfree((char *) TLScontext);
+       FREE_TLS_CONTEXT(TLScontext);
        return (0);
     }
     /* Only loglevel==4 dumps everything */
@@ -622,7 +606,6 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
                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,
@@ -672,7 +655,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
            SSL_CTX_remove_session(server_ctx, session);
            SSL_free(TLScontext->con);
            BIO_free(TLScontext->network_bio);  /* 200411 */
-           myfree((char *) TLScontext);
+           FREE_TLS_CONTEXT(TLScontext);
            return (0);
        }
     }
index 1c319dd219e2c1541f36dd5084474eed2b188c1c..8ffe56923e5d661ee1068023a561ad60f6cf5a3f 100644 (file)
@@ -113,7 +113,7 @@ void    tls_session_stop(SSL_CTX *ctx, VSTREAM *stream, int timeout,
     SSL_free(TLScontext->con);
 
     BIO_free(TLScontext->network_bio);
-    myfree((char *) TLScontext);
+    FREE_TLS_CONTEXT(TLScontext);
     tls_stream_stop(stream);
     SSL_CTX_flush_sessions(ctx, time(NULL));