From 23fa28b96e5650b4c0a71ffa93e7d81abb8c63dd Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Sat, 27 Feb 2010 21:00:58 +0000 Subject: [PATCH] Backport: mod_ssl: Add SSLInsecureRenegotiation directive. +1: jorton, trawick, minfrin git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@917044 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ STATUS | 14 ----------- docs/manual/mod/mod_ssl.xml | 42 +++++++++++++++++++++++++++++++++ modules/ssl/mod_ssl.c | 2 ++ modules/ssl/ssl_engine_config.c | 15 ++++++++++++ modules/ssl/ssl_engine_init.c | 14 +++++++---- modules/ssl/ssl_engine_kernel.c | 21 ++++++++++++++--- modules/ssl/ssl_engine_vars.c | 8 +++++++ modules/ssl/ssl_private.h | 2 ++ 9 files changed, 100 insertions(+), 22 deletions(-) diff --git a/CHANGES b/CHANGES index 9245a583ed8..8db3e02ad6b 100644 --- a/CHANGES +++ b/CHANGES @@ -35,6 +35,10 @@ Changes with Apache 2.2.15 desired. Fix the default value of the SSIAccessEnable directive. [Graham Leggett] + *) mod_ssl: Add the 'SSLInsecureRenegotiation' directive, which + allows insecure renegotiation with clients which do not yet + support the secure renegotiation protocol. [Joe Orton] + *) core: Fix potential memory leaks by making sure to not destroy bucket brigades that have been created by earlier filters. [Stefan Fritsch] diff --git a/STATUS b/STATUS index cd73c28be21..15385b410b0 100644 --- a/STATUS +++ b/STATUS @@ -87,20 +87,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_ssl: Add SSLInsecureRenegotiation directive. - Trunk version of patch: - http://svn.apache.org/viewcvs.cgi?rev=906039&view=rev - http://svn.apache.org/viewcvs.cgi?rev=906057&view=rev - http://svn.apache.org/viewcvs.cgi?rev=906485&view=rev - http://svn.apache.org/viewcvs.cgi?rev=906491&view=rev - http://svn.apache.org/viewcvs.cgi?rev=908015&view=rev - http://svn.apache.org/viewcvs.cgi?rev=916733&view=rev - http://svn.apache.org/viewcvs.cgi?rev=916817&view=rev - Backport version for 2.2.x of patch: - http://people.apache.org/~jorton/ms_reneg22_v2.diff - +1: jorton, trawick, minfrin - minfrin: needs docs, on the case - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index a8a2dd24949..a7c1046a861 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -1808,4 +1808,46 @@ SSLCryptoDevice ubsec + +SSLInsecureRenegotiation +Option to enable support for insecure renegotiation +SSLInsecureRenegotiation flag +SSLInsecureRenegotiation off +server config +virtual host +Available in httpd 2.3 and later, if using OpenSSL 1.0.0 Beta 5 or later + + +

As originally specified, all versions of the SSL and TLS protocols +(up to and including TLS/1.2) were vulnerable to a Man-in-the-Middle +attack +(CVE-2009-3555) +during a renegotiation. This vulnerability allowed an attacker to +"prefix" a chosen plaintext to the HTTP request as seen by the web +server. A protocol extension was developed which fixed this +vulnerability if supported by both client and server.

+ +

If mod_ssl is linked against OpenSSL version 1.0.0 +Beta 5 or later, by default renegotiation is only supported with +clients supporting the new protocol extension. If this directive is +enabled, renegotiation will be allowed with old (unpatched) clients, +albeit insecurely.

+ +Security warning +

If this directive is enabled, SSL connections will be vulnerable to +the Man-in-the-Middle prefix attack as described +in CVE-2009-3555.

+
+ +Example +SSLInsecureRenegotiation on + + +

The SSL_SECURE_RENEG environment variable can be used +from an SSI or CGI script to determine whether secure renegotiation is +supported for a given SSL connection.

+ +
+
+ diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index c8600e9dc38..37c13731523 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -143,6 +143,8 @@ static const command_rec ssl_config_cmds[] = { "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") SSL_CMD_SRV(HonorCipherOrder, FLAG, "Use the server's cipher ordering preference") + SSL_CMD_SRV(InsecureRenegotiation, FLAG, + "Enable support for insecure renegotiation") SSL_CMD_ALL(UserName, TAKE1, "Set user name to SSL variable value") SSL_CMD_SRV(StrictSNIVHostCheck, FLAG, diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index bda6fe569d7..e983f1e4e04 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -169,6 +169,7 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) sc->vhost_id_len = 0; /* set during module init */ sc->session_cache_timeout = UNSET; sc->cipher_server_pref = UNSET; + sc->insecure_reneg = UNSET; sc->proxy_ssl_check_peer_expire = SSL_ENABLED_UNSET; sc->proxy_ssl_check_peer_cn = SSL_ENABLED_UNSET; #ifndef OPENSSL_NO_TLSEXT @@ -262,6 +263,7 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) cfgMergeBool(proxy_enabled); cfgMergeInt(session_cache_timeout); cfgMergeBool(cipher_server_pref); + cfgMergeBool(insecure_reneg); cfgMerge(proxy_ssl_check_peer_expire, SSL_ENABLED_UNSET); cfgMerge(proxy_ssl_check_peer_cn, SSL_ENABLED_UNSET); #ifndef OPENSSL_NO_TLSEXT @@ -688,6 +690,19 @@ const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag) #endif } +const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag) +{ +#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + sc->insecure_reneg = flag?TRUE:FALSE; + return NULL; +#else + return "The SSLInsecureRenegotiation directive is not available " + "with this SSL library"; +#endif +} + + static const char *ssl_cmd_check_dir(cmd_parms *parms, const char **dir) { diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 05ccd0ce6db..d4f9171dfe3 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -394,6 +394,7 @@ static void ssl_init_ctx_protocol(server_rec *s, MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL; char *cp; int protocol = mctx->protocol; + SSLSrvConfigRec *sc = mySrvConfig(s); /* * Create the new per-server SSL context @@ -444,11 +445,14 @@ static void ssl_init_ctx_protocol(server_rec *s, } #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - { - SSLSrvConfigRec *sc = mySrvConfig(s); - if (sc->cipher_server_pref == TRUE) { - SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - } + if (sc->cipher_server_pref == TRUE) { + SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } +#endif + +#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + if (sc->insecure_reneg == TRUE) { + SSL_CTX_set_options(ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } #endif diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 05ace714b79..33f97bd9d90 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -760,10 +760,17 @@ int ssl_hook_Access(request_rec *r) r->connection->keepalive = AP_CONN_CLOSE; } - /* do a full renegotiation */ + /* Perform a full renegotiation. */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "Performing full renegotiation: " - "complete handshake protocol"); + "Performing full renegotiation: complete handshake " + "protocol (%s support secure renegotiation)", +#if defined(SSL_get_secure_renegotiation_support) + SSL_get_secure_renegotiation_support(ssl) ? + "client does" : "client does not" +#else + "server does not" +#endif + ); SSL_set_session_id_context(ssl, (unsigned char *)&id, @@ -779,6 +786,7 @@ int ssl_hook_Access(request_rec *r) if (SSL_get_state(ssl) != SSL_ST_OK) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Re-negotiation request failed"); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); r->connection->aborted = 1; return HTTP_FORBIDDEN; @@ -1067,6 +1075,7 @@ static const char *ssl_hook_Fixup_vars[] = { "SSL_VERSION_INTERFACE", "SSL_VERSION_LIBRARY", "SSL_PROTOCOL", + "SSL_SECURE_RENEG", "SSL_COMPRESS_METHOD", "SSL_CIPHER", "SSL_CIPHER_EXPORT", @@ -1171,6 +1180,12 @@ int ssl_hook_Fixup(request_rec *r) } } + +#ifdef SSL_get_secure_renegotiation_support + apr_table_setn(r->notes, "ssl-secure-reneg", + SSL_get_secure_renegotiation_support(ssl) ? "1" : "0"); +#endif + return DECLINED; } diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c index dd235a809fe..83cff2c12da 100644 --- a/modules/ssl/ssl_engine_vars.c +++ b/modules/ssl/ssl_engine_vars.c @@ -326,6 +326,14 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var) TLSEXT_NAMETYPE_host_name)); } #endif + else if (ssl != NULL && strcEQ(var, "SECURE_RENEG")) { + int flag = 0; +#ifdef SSL_get_secure_renegotiation_support + flag = SSL_get_secure_renegotiation_support(ssl); +#endif + result = apr_pstrdup(p, flag ? "true" : "false"); + } + return result; } diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index f6f488099f4..0613f0d213a 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -471,6 +471,7 @@ struct SSLSrvConfigRec { int vhost_id_len; int session_cache_timeout; BOOL cipher_server_pref; + BOOL insecure_reneg; modssl_ctx_t *server; modssl_ctx_t *proxy; ssl_enabled_t proxy_ssl_check_peer_expire; @@ -545,6 +546,7 @@ const char *ssl_cmd_SSLRequire(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLUserName(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag); const char *ssl_cmd_SSLProxyProtocol(cmd_parms *, void *, const char *); -- 2.47.2