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