]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.4-20061006
authorWietse Venema <wietse@porcupine.org>
Fri, 6 Oct 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:38 +0000 (06:32 +0000)
postfix/.indent.pro
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls.h
postfix/src/tls/tls_server.c

index 86d18924c44ffde4e21bd1272055edb5ca96ed0d..d9653076e07f0e99a1a5e28cb6588eabf701aca3 100644 (file)
 -Ttls_client_start_props
 -Ttls_info_t
 -Ttls_server_props
+-Ttls_server_start_props
index 86b25c8056c2265782b87e26516045a3e98d44e3..aeee142e685ebb45816e6dff35e469bf48a2d41f 100644 (file)
@@ -12781,6 +12781,14 @@ Apologies for any names omitted.
        settings are backwards compatible. File: smtp/smtp.c,
        smtp/smtp_proto.c.
 
+20061006
+
+       Workaround: include the smtpd(8) service name when searching
+       the TLS session cache, to avoid cross-talk between multiple
+       master.cf entries. This does not eliminate cross-talk between
+       multiple (x)inetd.conf entries. Victor Duchovni. Files:
+       smtpd/smtpd.c, tls/tls_server.c.
+
 Wish list:
 
        Update FILTER_README with mailing list suggestions to tag
index e90aeb5e3ac0af80e9cead620fae0d6eaa0df718..8cc6422af3f1ac402366bdcdb388a349bfcfa253 100644 (file)
@@ -17,6 +17,12 @@ Incompatibility with Postfix 2.2 and earlier
 If you upgrade from Postfix 2.2 or earlier, read RELEASE_NOTES-2.3
 before proceeding.
 
+Incompatible changes with Postfix snapshot 20061006
+===================================================
+
+The format of SMTP server TLS session cache lookup keys has changed.
+The lookup key now includes the master.cf service name.
+
 Incompatible changes with Postfix snapshot 20060806
 ===================================================
 
index b845ceda13174abaab4ab6ec5bd90534f1c6445d..a4a7665fb9bc1b0b7114fdf3518e5b054d088489 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20061005"
+#define MAIL_RELEASE_DATE      "20061006"
 #define MAIL_VERSION_NUMBER    "2.4"
 
 #ifdef SNAPSHOT
index 16f71294bfc7eb9ff4099cf6b6a899ce15358b92..4a19510d2d0a21c1c909df89fd9326af0333c430 100644 (file)
@@ -3533,6 +3533,7 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
 static void smtpd_start_tls(SMTPD_STATE *state)
 {
     int     rate;
+    tls_server_start_props props;
 
     /*
      * Wrapper mode uses a dedicated port and always requires TLS.
@@ -3543,12 +3544,24 @@ static void smtpd_start_tls(SMTPD_STATE *state)
      * perform SMTP transactions when the client does not use the STARTTLS
      * command. For this reason, Postfix does not require client certificate
      * verification unless TLS is required.
+     * 
+     * XXX We append the service name to the session cache ID, so that there
+     * won't be collisions between multiple master.cf entries that use
+     * different roots of trust. This does not eliminate collisions between
+     * multiple inetd.conf entries that use different roots of trust. For a
+     * universal solution we would have to append the local IP address + port
+     * number information.
      */
-    state->tls_context =
-       tls_server_start(smtpd_tls_ctx, state->client,
-                        var_smtpd_starttls_tmout, var_smtpd_tls_loglevel,
-                        state->name, state->addr,
-                      (var_smtpd_tls_req_ccert && state->tls_enforce_tls));
+    memset((char *) &props, 0, sizeof(props));
+    props.ctx = smtpd_tls_ctx;
+    props.stream = state->client;
+    props.log_level = var_smtpd_tls_loglevel;
+    props.timeout = var_smtpd_starttls_tmout;
+    props.requirecert = (var_smtpd_tls_req_ccert && state->tls_enforce_tls);
+    props.serverid = state->service;
+    props.peername = state->name;
+    props.peeraddr = state->addr;
+    state->tls_context = tls_server_start(&props);
 
     /*
      * XXX The client event count/rate control must be consistent in its use
index f1370232703ffd56621b6386ab6e538387c7574e..7865180e11d142c17607d7774f01cd426a19505f 100644 (file)
@@ -188,9 +188,19 @@ typedef struct {
     int     ask_ccert;
 } tls_server_props;
 
+typedef struct {
+    SSL_CTX *ctx;                      /* SSL application context */
+    VSTREAM *stream;                   /* Client stream */
+    int     log_level;                 /* TLS log level */
+    int     timeout;                   /* TLS handshake timeout */
+    int     requirecert;               /* Insist on client cert? */
+    char   *serverid;                  /* Server instance (salt cache key) */
+    char   *peername;                  /* Client name */
+    char   *peeraddr;                  /* Client address */
+} tls_server_start_props;
+
 extern SSL_CTX *tls_server_init(const tls_server_props *);
-extern TLScontext_t *tls_server_start(SSL_CTX *, VSTREAM *, int, int,
-                                          const char *, const char *, int);
+extern TLScontext_t *tls_server_start(const tls_server_start_props *props);
 
 #define tls_server_stop(ctx , stream, timeout, failure, TLScontext) \
        tls_session_stop((ctx), (stream), (timeout), (failure), (TLScontext))
index 3c6dac341a458b4766574c342bcb7d45c9be31de..ed1ff72ba5558f5f455e07220a9a2fb0c3375142 100644 (file)
@@ -9,15 +9,8 @@
 /*     SSL_CTX *tls_server_init(props)
 /*     const tls_server_props *props;
 /*
-/*     TLScontext_t *tls_server_start(server_ctx, stream, timeout, log_level,
-/*                                     peername, peeraddr, requirecert)
-/*     SSL_CTX *server_ctx;
-/*     VSTREAM *stream;
-/*     int     timeout;
-/*     int     log_level;
-/*     const char *peername;
-/*     const char *peeraddr;
-/*     int     requirecert;
+/*     TLScontext_t *tls_server_start(props)
+/*     const tls_server_start_props *props;
 /*
 /*     void    tls_server_stop(server_ctx, stream, failure, TLScontext)
 /*     SSL_CTX *server_ctx;
@@ -154,10 +147,15 @@ static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id,
     if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0)
        msg_panic("%s: null TLScontext in session lookup callback", myname);
 
-#define HEX_CACHE_ID(id, len) \
-    hex_encode(vstring_alloc(2 * (len) + 1), (char *) (id), (len))
+#define GEN_CACHE_ID(buf, id, len, service) \
+    do { \
+       buf = vstring_alloc(2 * (len) + 1 + strlen(service) + 3); \
+       hex_encode(buf, (char *) (id), (len)); \
+       vstring_sprintf_append(buf, "&s=%s", (service)); \
+    } while (0)
 
-    cache_id = HEX_CACHE_ID(session_id, session_id_length);
+
+    GEN_CACHE_ID(cache_id, session_id, session_id_length, TLScontext->serverid);
 
     if (TLScontext->log_level >= 2)
        msg_info("looking up session %s in %s cache",
@@ -195,7 +193,9 @@ static void uncache_session(SSL_CTX *ctx, TLScontext_t *TLScontext)
     if (TLScontext->cache_type == 0)
        return;
 
-    cache_id = HEX_CACHE_ID(session->session_id, session->session_id_length);
+    GEN_CACHE_ID(cache_id, session->session_id, session->session_id_length,
+                TLScontext->serverid);
+
     if (TLScontext->log_level >= 2)
        msg_info("remove session %s from %s cache",
                 STR(cache_id), TLScontext->cache_type);
@@ -216,7 +216,8 @@ static int new_server_session_cb(SSL *ssl, SSL_SESSION *session)
     if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0)
        msg_panic("%s: null TLScontext in new session callback", myname);
 
-    cache_id = HEX_CACHE_ID(session->session_id, session->session_id_length);
+    GEN_CACHE_ID(cache_id, session->session_id, session->session_id_length,
+                TLScontext->serverid);
 
     if (TLScontext->log_level >= 2)
        msg_info("save session %s to %s cache",
@@ -512,10 +513,7 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
   * the SMTP buffers are flushed and the "220 Ready to start TLS" was sent to
   * the client, so that we can immediately start the TLS handshake process.
   */
-TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
-                                      int timeout, int log_level,
-                                      const char *peername,
-                                      const char *peeraddr, int requirecert)
+TLScontext_t *tls_server_start(const tls_server_start_props *props)
 {
     int     sts;
     int     j;
@@ -527,18 +525,20 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
     unsigned char md[EVP_MAX_MD_SIZE];
     char    buf[CCERT_BUFSIZ];
 
-    if (log_level >= 1)
-       msg_info("setting up TLS connection from %s[%s]", peername, peeraddr);
+    if (props->log_level >= 1)
+       msg_info("setting up TLS connection from %s[%s]",
+                props->peername, props->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 tls_verify_certificate_callback().
      */
-    TLScontext = tls_alloc_context(log_level, peername);
-    TLScontext->cache_type = SSL_CTX_get_ex_data(server_ctx, TLSscache_index);
+    TLScontext = tls_alloc_context(props->log_level, props->peername);
+    TLScontext->cache_type = SSL_CTX_get_ex_data(props->ctx, TLSscache_index);
+    TLScontext->serverid = mystrdup(props->serverid);
 
-    if ((TLScontext->con = (SSL *) SSL_new(server_ctx)) == NULL) {
+    if ((TLScontext->con = (SSL *) SSL_new(props->ctx)) == NULL) {
        msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
        tls_print_errors();
        tls_free_context(TLScontext);
@@ -555,7 +555,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * Set the verification parameters to be checked in
      * tls_verify_certificate_callback().
      */
-    if (requirecert) {
+    if (props->requirecert) {
        verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
        verify_flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
        TLScontext->enforce_verify_errors = 1;
@@ -611,7 +611,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * Well there is a BIO below the SSL routines that is automatically
      * created for us, so we can use it for debugging purposes.
      */
-    if (log_level >= 3)
+    if (props->log_level >= 3)
        BIO_set_callback(SSL_get_rbio(TLScontext->con), tls_bio_dump_cb);
 
     /*
@@ -621,15 +621,17 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * Error handling: If the SSL handhake fails, we print out an error message
      * and remove all TLS state concerning this session.
      */
-    sts = tls_bio_accept(vstream_fileno(stream), timeout, TLScontext);
+    sts = tls_bio_accept(vstream_fileno(props->stream), props->timeout,
+                        TLScontext);
     if (sts <= 0) {
-       msg_info("SSL_accept error from %s[%s]: %d", peername, peeraddr, sts);
+       msg_info("SSL_accept error from %s[%s]: %d",
+                props->peername, props->peeraddr, sts);
        tls_print_errors();
        tls_free_context(TLScontext);
        return (0);
     }
     /* Only loglevel==4 dumps everything */
-    if (log_level < 4)
+    if (props->log_level < 4)
        BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
 
     /*
@@ -637,7 +639,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * session was negotiated.
      */
     TLScontext->session_reused = SSL_session_reused(TLScontext->con);
-    if (log_level >= 2 && TLScontext->session_reused)
+    if (props->log_level >= 2 && TLScontext->session_reused)
        msg_info("Reusing old session");
 
     /*
@@ -649,7 +651,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
        if (SSL_get_verify_result(TLScontext->con) == X509_V_OK)
            TLScontext->peer_verified = 1;
 
-       if (log_level >= 2) {
+       if (props->log_level >= 2) {
            X509_NAME_oneline(X509_get_subject_name(peer),
                              buf, sizeof(buf));
            msg_info("subject=%s", buf);
@@ -669,7 +671,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
                else
                    TLScontext->peer_fingerprint[(j * 3) + 2] = '\0';
            }
-           if (log_level >= 1)
+           if (props->log_level >= 1)
                msg_info("fingerprint=%s", TLScontext->peer_fingerprint);
        }
        if ((TLScontext->peer_CN = tls_peer_CN(peer)) == 0)
@@ -677,7 +679,7 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
        if ((TLScontext->issuer_CN = tls_issuer_CN(peer)) == 0)
            TLScontext->issuer_CN = mystrdup("");
 
-       if (log_level >= 1) {
+       if (props->log_level >= 1) {
            if (TLScontext->peer_verified)
                msg_info("Verified: subject_CN=%s, issuer=%s",
                         TLScontext->peer_CN, TLScontext->issuer_CN);
@@ -692,12 +694,12 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * If this is a cached session, we have to check by hand if the cached
      * session peer was verified.
      */
-    if (requirecert) {
+    if (props->requirecert) {
        if (!TLScontext->peer_verified || !TLScontext->peer_CN) {
            if (TLScontext->session_reused == 0)
                msg_panic("tls_server_start: peer was not verified");
            msg_info("Re-used session without peer certificate removed");
-           uncache_session(server_ctx, TLScontext);
+           uncache_session(props->ctx, TLScontext);
            tls_free_context(TLScontext);
            return (0);
        }
@@ -716,11 +718,11 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
      * The TLS engine is active. Switch to the tls_timed_read/write()
      * functions and make the TLScontext available to those functions.
      */
-    tls_stream_start(stream, TLScontext);
+    tls_stream_start(props->stream, TLScontext);
 
-    if (log_level >= 1)
+    if (props->log_level >= 1)
        msg_info("TLS connection established from %s[%s]: %s with cipher %s (%d/%d bits)",
-                peername, peeraddr,
+                props->peername, props->peeraddr,
                 TLScontext->protocol, TLScontext->cipher_name,
                 TLScontext->cipher_usebits, TLScontext->cipher_algbits);
     tls_int_seed();