From: Wietse Venema Date: Fri, 6 Oct 2006 05:00:00 +0000 (-0500) Subject: postfix-2.4-20061006 X-Git-Tag: v2.4.0-RC1~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8496eb5cae28287710b605a09c97ee386ec5a00f;p=thirdparty%2Fpostfix.git postfix-2.4-20061006 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 86d18924c..d9653076e 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -264,3 +264,4 @@ -Ttls_client_start_props -Ttls_info_t -Ttls_server_props +-Ttls_server_start_props diff --git a/postfix/HISTORY b/postfix/HISTORY index 86b25c805..aeee142e6 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index e90aeb5e3..8cc6422af 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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 =================================================== diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index b845ceda1..a4a7665fb 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 16f71294b..4a19510d2 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -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 diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index f13702327..7865180e1 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -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)) diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index 3c6dac341..ed1ff72ba 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -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();