From: Viktor Dukhovni Date: Fri, 13 Jun 2014 02:56:47 +0000 (-0400) Subject: Upcoming OpenSSL security levels disable "weak" crypto. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb7dba6de3d0f9e2b9a33f111c55e23116d88243;p=thirdparty%2Fpostfix.git Upcoming OpenSSL security levels disable "weak" crypto. Bitrot: OpenSSL 1.1.0-dev (aka the "master" branch) has new security levels ranging from 0 to 5. * Level "0" is backwards compatible anything goes. * Level "1", the new default, is roughly 80-bit or greater security across the board (block ciphers, EDH parameters, EC curves, RSA bit lengths, ...). It also disables anonymous ciphersuites, breaking "smtpd_tls_cert_file = none", and in is stronger than we want for opportunistic TLS. * The remaining levels are for now too strong even for mandatory authenticated TLS, they disable RC4, RSA keys shorter than 2048 bits, and SSLv3. Therefore, (subject to the presence of the feature detected via macro recommended by Steve Henson), we revert the default security level back to 0 in the application SSL context. Users can if they wish change this by appending ":@SECURITY=" to the various tls cipherlists. TODO: we'll shold also add a main.cf parameter and policy table overrides for this at some point, provided we can figure out how to explain yet another "mumble_level" to the users. When authentication is mandatory in either the SMTP client or in the SMTP server (smtpd_tls_req_ccert = yes) we set the security level to 1 to ensure adequately strong parameters. When testing this, discovered that verification error reasons are not logged in the SMTP server, cloned and tested corresponding code from the client. Sample logging (when client cert has wrong EKU): smtpd[63016]: certificate verification failed for localhost[127.0.0.1]: not designated for use as a client certificate smtpd[63016]: Untrusted TLS connection established from localhost[127.0.0.1]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits) smtpd[63016]: NOQUEUE: abort: TLS from localhost[127.0.0.1]: Client certificate not trusted --- diff --git a/postfix/src/tls/tls_client.c b/postfix/src/tls/tls_client.c index fb0f87a0c..9553995a9 100644 --- a/postfix/src/tls/tls_client.c +++ b/postfix/src/tls/tls_client.c @@ -355,6 +355,11 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props) return (0); } +#ifdef SSL_SECOP_PEER + /* Backwards compatible security as a base for opportunistic TLS. */ + SSL_CTX_set_security_level(client_ctx, 0); +#endif + /* * See the verify callback in tls_verify.c */ @@ -936,6 +941,12 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props) if (protomask != 0) SSL_set_options(TLScontext->con, TLS_SSL_OP_PROTOMASK(protomask)); +#ifdef SSL_SECOP_PEER + /* When authenticating the peer, use 80-bit plus OpenSSL security level */ + if (TLS_MUST_MATCH(props->tls_level)) + SSL_set_security_level(TLScontext->con, 1); +#endif + /* * XXX To avoid memory leaks we must always call SSL_SESSION_free() after * calling SSL_set_session(), regardless of whether or not the session diff --git a/postfix/src/tls/tls_server.c b/postfix/src/tls/tls_server.c index d8866fe9a..71b5988dc 100644 --- a/postfix/src/tls/tls_server.c +++ b/postfix/src/tls/tls_server.c @@ -444,6 +444,11 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) return (0); } +#ifdef SSL_SECOP_PEER + /* Backwards compatible security as a base for opportunistic TLS. */ + SSL_CTX_set_security_level(server_ctx, 0); +#endif + /* * See the verify callback in tls_verify.c */ @@ -751,6 +756,12 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props) return (0); } +#ifdef SSL_SECOP_PEER + /* When authenticating the peer, use 80-bit plus OpenSSL security level */ + if (props->requirecert) + SSL_set_security_level(TLScontext->con, 1); +#endif + /* * Before really starting anything, try to seed the PRNG a little bit * more. @@ -880,6 +891,22 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext) TLScontext->peer_pkey_fprint); } X509_free(peer); + + /* + * Give them a clue. Problems with trust chain verification are logged + * when the session is first negotiated, before the session is stored + * into the cache. We don't want mystery failures, so log the fact the + * real problem is to be found in the past. + */ + if (!TLS_CERT_IS_TRUSTED(TLScontext) + && (TLScontext->log_mask & TLS_LOG_UNTRUSTED)) { + if (TLScontext->session_reused == 0) + tls_log_verify_error(TLScontext); + else + msg_info("%s: re-using session with untrusted certificate, " + "look for details earlier in the log", + TLScontext->namaddr); + } } else { TLScontext->peer_CN = mystrdup(""); TLScontext->issuer_CN = mystrdup("");