]> granicus.if.org Git - apache/commitdiff
Support for OpenSSL 1.1.0:
authorRainer Jung <rjung@apache.org>
Tue, 9 Feb 2016 09:55:18 +0000 (09:55 +0000)
committerRainer Jung <rjung@apache.org>
Tue, 9 Feb 2016 09:55:18 +0000 (09:55 +0000)
- partial support for renegotiations.
  - Not a good design, need to poll until
    renegotitation has finished.
  - Loop criterion not right, if no client certs
    will be send.
  - Also doesn't work for EC or DH ciphers.
    Unclear how to fix with current 1.1.0
    API.
  - Details see
    http://marc.info/?t=145493359200002&r=1&w=2

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1729341 13f79535-47bb-0310-9956-ffa450edef68

modules/ssl/ssl_engine_kernel.c

index 3f6b81e0eea76fe58ec7ed2cbc09d786b329129f..855bed2d46d717b3b0e088c4fb8f199afa11d152 100644 (file)
@@ -32,6 +32,9 @@
 #include "mod_ssl.h"
 #include "util_md5.h"
 #include "scoreboard.h"
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#include "apr_time.h"
+#endif
 
 static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
 #ifdef HAVE_TLSEXT
@@ -42,6 +45,11 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
 #define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
 #define CONNECTION_HEADER "Connection: Upgrade"
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define SSL_HANDSHAKE_POLL_MS 10
+#define SSL_HANDSHAKE_MAX_POLLS 500
+#endif
+
 /* Perform an upgrade-to-TLS for the given request, per RFC 2817. */
 static apr_status_t upgrade_connection(request_rec *r)
 {
@@ -1010,16 +1018,49 @@ int ssl_hook_Access(request_rec *r)
              * However, this causes failures in perl-framework currently,
              * perhaps pre-test if we have already negotiated?
              */
-            /* XXX: OpenSSL 1.1.0: SSL_set_state() no longer available.
-             * Would SSL_renegotiate(ssl) work? */
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
+
 #ifdef OPENSSL_NO_SSL_INTERN
             SSL_set_state(ssl, SSL_ST_ACCEPT);
 #else
             ssl->state = SSL_ST_ACCEPT;
-#endif
-#endif
             SSL_do_handshake(ssl);
+#endif
+
+#else /* if OPENSSL_VERSION_NUMBER < 0x10100000L */
+
+            /* XXX: OpenSSL 1.1.0: SSL_set_state() no longer available.
+             * Need to trigger renegotiation handshake by reading,
+             * until handshake has finished.
+             * The code works for some ciphers with 1.1.0pre2 plus the patch
+             * https://github.com/openssl/openssl/commit/311f27852a18fb9c10f0c1283b639f12eea06de2
+             * It does not work for EC and DH. For details see:
+             * See: http://marc.info/?t=145493359200002&r=1&w=2
+             */
+            /* XXX: Polling is bad, alternatives? */
+            /* XXX: What about renegotiations which do not need to
+             *      send client certs, e.g. if only the cipher needs
+             *      to switch? We need a better success criterion here
+             *      or the loop will poll until SSL_HANDSHAKE_MAX_POLLS
+             *      is reached.
+             */
+            for (i = 0; i < SSL_HANDSHAKE_MAX_POLLS; i++) {
+                has_buffered_data(r);
+                cert = SSL_get_peer_certificate(ssl);
+                if (cert != NULL) {
+                    break;
+                }
+                apr_sleep(SSL_HANDSHAKE_POLL_MS);
+            }
+            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, APLOGNO()
+                          "Renegotiation loop %d iterations, "
+                          "in_init=%d, init_finished=%d, "
+                          "state=%s, peer_certs=%s",
+                          i, SSL_in_init(ssl), SSL_is_init_finished(ssl),
+                          SSL_state_string_long(ssl),
+                          cert != NULL ? "yes" : "no");
+
+#endif /* if OPENSSL_VERSION_NUMBER < 0x10100000L */
 
             sslconn->reneg_state = RENEG_REJECT;