summaryrefslogtreecommitdiff
path: root/httpd-2.4.51-r1877397.patch
diff options
context:
space:
mode:
Diffstat (limited to 'httpd-2.4.51-r1877397.patch')
-rw-r--r--httpd-2.4.51-r1877397.patch249
1 files changed, 249 insertions, 0 deletions
diff --git a/httpd-2.4.51-r1877397.patch b/httpd-2.4.51-r1877397.patch
new file mode 100644
index 0000000..f629317
--- /dev/null
+++ b/httpd-2.4.51-r1877397.patch
@@ -0,0 +1,249 @@
+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
+index 211ebff..c8cb1af 100644
+--- a/modules/ssl/ssl_engine_init.c
++++ b/modules/ssl/ssl_engine_init.c
+@@ -871,6 +871,13 @@ static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+ SSL_CTX_set_keylog_callback(ctx, modssl_callback_keylog);
+ }
+ #endif
++
++#ifdef SSL_OP_NO_RENEGOTIATION
++ /* For server-side SSL_CTX, disable renegotiation by default.. */
++ if (!mctx->pkp) {
++ SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION);
++ }
++#endif
+
+ return APR_SUCCESS;
+ }
+@@ -892,6 +899,14 @@ static void ssl_init_ctx_session_cache(server_rec *s,
+ }
+ }
+
++#ifdef SSL_OP_NO_RENEGOTIATION
++/* OpenSSL-level renegotiation protection. */
++#define MODSSL_BLOCKS_RENEG (0)
++#else
++/* mod_ssl-level renegotiation protection. */
++#define MODSSL_BLOCKS_RENEG (1)
++#endif
++
+ static void ssl_init_ctx_callbacks(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+@@ -905,7 +920,13 @@ static void ssl_init_ctx_callbacks(server_rec *s,
+ SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
+ #endif
+
+- SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
++ /* The info callback is used for debug-level tracing. For OpenSSL
++ * versions where SSL_OP_NO_RENEGOTIATION is not available, the
++ * callback is also used to prevent use of client-initiated
++ * renegotiation. Enable it in either case. */
++ if (APLOGdebug(s) || MODSSL_BLOCKS_RENEG) {
++ SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
++ }
+
+ #ifdef HAVE_TLS_ALPN
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_callback_alpn_select, NULL);
+diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
+index 79b9a70..3a0c22a 100644
+--- a/modules/ssl/ssl_engine_io.c
++++ b/modules/ssl/ssl_engine_io.c
+@@ -209,11 +209,13 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
+
+ BIO_clear_retry_flags(bio);
+
++#ifndef SSL_OP_NO_RENEGOTIATION
+ /* Abort early if the client has initiated a renegotiation. */
+ if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
+ outctx->rc = APR_ECONNABORTED;
+ return -1;
+ }
++#endif
+
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, outctx->c,
+ "bio_filter_out_write: %i bytes", inl);
+@@ -474,11 +476,13 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
+
+ BIO_clear_retry_flags(bio);
+
++#ifndef SSL_OP_NO_RENEGOTIATION
+ /* Abort early if the client has initiated a renegotiation. */
+ if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
+ inctx->rc = APR_ECONNABORTED;
+ return -1;
+ }
++#endif
+
+ if (!inctx->bb) {
+ inctx->rc = APR_EOF;
+diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
+index 591f6ae..8416864 100644
+--- a/modules/ssl/ssl_engine_kernel.c
++++ b/modules/ssl/ssl_engine_kernel.c
+@@ -992,7 +992,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
+
+ /* Toggle the renegotiation state to allow the new
+ * handshake to proceed. */
+- sslconn->reneg_state = RENEG_ALLOW;
++ modssl_set_reneg_state(sslconn, RENEG_ALLOW);
+
+ SSL_renegotiate(ssl);
+ SSL_do_handshake(ssl);
+@@ -1019,7 +1019,7 @@ static int ssl_hook_Access_classic(request_rec *r, SSLSrvConfigRec *sc, SSLDirCo
+ */
+ SSL_peek(ssl, peekbuf, 0);
+
+- sslconn->reneg_state = RENEG_REJECT;
++ modssl_set_reneg_state(sslconn, RENEG_REJECT);
+
+ if (!SSL_is_init_finished(ssl)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02261)
+@@ -1078,7 +1078,7 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
+ int vmode_inplace, vmode_needed;
+ int change_vmode = FALSE;
+- int old_state, n, rc;
++ int n, rc;
+
+ vmode_inplace = SSL_get_verify_mode(ssl);
+ vmode_needed = SSL_VERIFY_NONE;
+@@ -1180,8 +1180,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ return HTTP_FORBIDDEN;
+ }
+
+- old_state = sslconn->reneg_state;
+- sslconn->reneg_state = RENEG_ALLOW;
+ modssl_set_app_data2(ssl, r);
+
+ SSL_do_handshake(ssl);
+@@ -1191,7 +1189,6 @@ static int ssl_hook_Access_modern(request_rec *r, SSLSrvConfigRec *sc, SSLDirCon
+ */
+ SSL_peek(ssl, peekbuf, 0);
+
+- sslconn->reneg_state = old_state;
+ modssl_set_app_data2(ssl, NULL);
+
+ /*
+@@ -2263,8 +2260,8 @@ static void log_tracing_state(const SSL *ssl, conn_rec *c,
+ /*
+ * This callback function is executed while OpenSSL processes the SSL
+ * handshake and does SSL record layer stuff. It's used to trap
+- * client-initiated renegotiations, and for dumping everything to the
+- * log.
++ * client-initiated renegotiations (where SSL_OP_NO_RENEGOTIATION is
++ * not available), and for dumping everything to the log.
+ */
+ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ {
+@@ -2276,14 +2273,12 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ return;
+ }
+
+- /* With TLS 1.3 this callback may be called multiple times on the first
+- * negotiation, so the below logic to detect renegotiations can't work.
+- * Fortunately renegotiations are forbidden starting with TLS 1.3, and
+- * this is enforced by OpenSSL so there's nothing to be done here.
+- */
+-#if SSL_HAVE_PROTOCOL_TLSV1_3
+- if (SSL_version(ssl) < TLS1_3_VERSION)
+-#endif
++#ifndef SSL_OP_NO_RENEGOTIATION
++ /* With OpenSSL < 1.1.1 (implying TLS v1.2 or earlier), this
++ * callback is used to block client-initiated renegotiation. With
++ * TLSv1.3 it is unnecessary since renegotiation is forbidden at
++ * protocol level. Otherwise (TLSv1.2 with OpenSSL >=1.1.1),
++ * SSL_OP_NO_RENEGOTIATION is used to block renegotiation. */
+ {
+ SSLConnRec *sslconn;
+
+@@ -2308,6 +2303,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
+ sslconn->reneg_state = RENEG_REJECT;
+ }
+ }
++#endif
+
+ s = mySrvFromConn(c);
+ if (s && APLOGdebug(s)) {
+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
+index a329d99..7666c31 100644
+--- a/modules/ssl/ssl_private.h
++++ b/modules/ssl/ssl_private.h
+@@ -512,6 +512,16 @@ typedef struct {
+ apr_time_t source_mtime;
+ } ssl_asn1_t;
+
++typedef enum {
++ RENEG_INIT = 0, /* Before initial handshake */
++ RENEG_REJECT, /* After initial handshake; any client-initiated
++ * renegotiation should be rejected */
++ RENEG_ALLOW, /* A server-initiated renegotiation is taking
++ * place (as dictated by configuration) */
++ RENEG_ABORT /* Renegotiation initiated by client, abort the
++ * connection */
++} modssl_reneg_state;
++
+ /**
+ * Define the mod_ssl per-module configuration structure
+ * (i.e. the global configuration for each httpd process)
+@@ -543,18 +553,13 @@ typedef struct {
+ NON_SSL_SET_ERROR_MSG /* Need to set the error message */
+ } non_ssl_request;
+
+- /* Track the handshake/renegotiation state for the connection so
+- * that all client-initiated renegotiations can be rejected, as a
+- * partial fix for CVE-2009-3555. */
+- enum {
+- RENEG_INIT = 0, /* Before initial handshake */
+- RENEG_REJECT, /* After initial handshake; any client-initiated
+- * renegotiation should be rejected */
+- RENEG_ALLOW, /* A server-initiated renegotiation is taking
+- * place (as dictated by configuration) */
+- RENEG_ABORT /* Renegotiation initiated by client, abort the
+- * connection */
+- } reneg_state;
++#ifndef SSL_OP_NO_RENEGOTIATION
++ /* For OpenSSL < 1.1.1, track the handshake/renegotiation state
++ * for the connection to block client-initiated renegotiations.
++ * For OpenSSL >=1.1.1, the SSL_OP_NO_RENEGOTIATION flag is used in
++ * the SSL * options state with equivalent effect. */
++ modssl_reneg_state reneg_state;
++#endif
+
+ server_rec *server;
+ SSLDirConfigRec *dc;
+@@ -1158,6 +1163,9 @@ int ssl_is_challenge(conn_rec *c, const char *servername,
+ * the configured ENGINE. */
+ int modssl_is_engine_id(const char *name);
+
++/* Set the renegotation state for connection. */
++void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state);
++
+ #endif /* SSL_PRIVATE_H */
+ /** @} */
+
+diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
+index 38079a9..dafb833 100644
+--- a/modules/ssl/ssl_util_ssl.c
++++ b/modules/ssl/ssl_util_ssl.c
+@@ -589,3 +589,19 @@ cleanup:
+ }
+ return rv;
+ }
++
++void modssl_set_reneg_state(SSLConnRec *sslconn, modssl_reneg_state state)
++{
++#ifdef SSL_OP_NO_RENEGOTIATION
++ switch (state) {
++ case RENEG_ALLOW:
++ SSL_clear_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
++ break;
++ default:
++ SSL_set_options(sslconn->ssl, SSL_OP_NO_RENEGOTIATION);
++ break;
++ }
++#else
++ sslconn->reneg_state = state;
++#endif
++}