mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Support for OpenSSL 1.1.0:
- use SSL_peek instead of looping with has_buffered_data(). This fixes t/security/CVE-2009-3555.t where has_buffered_data() doesn't help, because it finds the buffered data and doesn't call SSL_read(), so the reneg handshake isn't triggered. SSL_peek() for 0 bytes seems to reliably trigger the reneg in every case. No more polling/sleeping. The code for the OpenSSL 1.1.0 case is now again very close to the pre 1.1.0 case. Still need to run the full test suite with a clean build. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1730316 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -32,9 +32,6 @@
|
|||||||
#include "mod_ssl.h"
|
#include "mod_ssl.h"
|
||||||
#include "util_md5.h"
|
#include "util_md5.h"
|
||||||
#include "scoreboard.h"
|
#include "scoreboard.h"
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
||||||
#include "apr_time.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
|
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
|
||||||
#ifdef HAVE_TLSEXT
|
#ifdef HAVE_TLSEXT
|
||||||
@@ -45,11 +42,6 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
|
|||||||
#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
|
#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
|
||||||
#define CONNECTION_HEADER "Connection: Upgrade"
|
#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. */
|
/* Perform an upgrade-to-TLS for the given request, per RFC 2817. */
|
||||||
static apr_status_t upgrade_connection(request_rec *r)
|
static apr_status_t upgrade_connection(request_rec *r)
|
||||||
{
|
{
|
||||||
@@ -955,6 +947,10 @@ int ssl_hook_Access(request_rec *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
|
int rc;
|
||||||
|
char peekbuf[1];
|
||||||
|
#endif
|
||||||
const char *reneg_support;
|
const char *reneg_support;
|
||||||
request_rec *id = r->main ? r->main : r;
|
request_rec *id = r->main ? r->main : r;
|
||||||
|
|
||||||
@@ -1029,30 +1025,21 @@ int ssl_hook_Access(request_rec *r)
|
|||||||
|
|
||||||
#else /* if OPENSSL_VERSION_NUMBER < 0x10100000L */
|
#else /* if OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||||
|
|
||||||
/* XXX: OpenSSL 1.1.0: SSL_set_state() no longer available.
|
/* Need to trigger renegotiation handshake by reading.
|
||||||
* Need to trigger renegotiation handshake by reading,
|
* Peeking 0 bytes actually works.
|
||||||
* until handshake has finished.
|
* The code needs the following patches on top of OpenSSL 1.1.0pre2:
|
||||||
* The code works for some ciphers with 1.1.0pre2 plus the patch
|
|
||||||
* https://github.com/openssl/openssl/commit/311f27852a18fb9c10f0c1283b639f12eea06de2
|
* https://github.com/openssl/openssl/commit/311f27852a18fb9c10f0c1283b639f12eea06de2
|
||||||
* It does not work for EC and DH. For details see:
|
* https://github.com/openssl/openssl/commit/5b326dc529e19194feaef9a65fa37efbe11eaa7e
|
||||||
|
* It is expected to work without changes with the forthcoming 1.1.0pre3.
|
||||||
* See: http://marc.info/?t=145493359200002&r=1&w=2
|
* See: http://marc.info/?t=145493359200002&r=1&w=2
|
||||||
*/
|
*/
|
||||||
/* XXX: Polling is bad, alternatives? */
|
rc = SSL_peek(ssl, peekbuf, 0);
|
||||||
for (i = 0; i < SSL_HANDSHAKE_MAX_POLLS; i++) {
|
|
||||||
has_buffered_data(r);
|
|
||||||
if (sslconn->ssl == NULL ||
|
|
||||||
sslconn->reneg_state == RENEG_DONE ||
|
|
||||||
sslconn->reneg_state == RENEG_ALERT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
apr_sleep(SSL_HANDSHAKE_POLL_MS);
|
|
||||||
}
|
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, APLOGNO()
|
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, APLOGNO()
|
||||||
"Renegotiation loop %d iterations, "
|
"Renegotiation peek result=%d, "
|
||||||
"reneg_state=%d, "
|
"reneg_state=%d, "
|
||||||
"in_init=%d, init_finished=%d, "
|
"in_init=%d, init_finished=%d, "
|
||||||
"state=%s, sslconn->ssl=%s, peer_certs=%s",
|
"state=%s, sslconn->ssl=%s, peer_certs=%s",
|
||||||
i, sslconn->reneg_state,
|
rc, sslconn->reneg_state,
|
||||||
SSL_in_init(ssl), SSL_is_init_finished(ssl),
|
SSL_in_init(ssl), SSL_is_init_finished(ssl),
|
||||||
SSL_state_string_long(ssl),
|
SSL_state_string_long(ssl),
|
||||||
sslconn->ssl != NULL ? "yes" : "no",
|
sslconn->ssl != NULL ? "yes" : "no",
|
||||||
@@ -2150,23 +2137,6 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
||||||
else if (!scr->is_proxy &&
|
|
||||||
(where & SSL_CB_HANDSHAKE_START) &&
|
|
||||||
scr->reneg_state == RENEG_ALLOW) {
|
|
||||||
scr->reneg_state = RENEG_STARTED;
|
|
||||||
}
|
|
||||||
else if (!scr->is_proxy &&
|
|
||||||
(where & SSL_CB_HANDSHAKE_DONE) &&
|
|
||||||
scr->reneg_state == RENEG_STARTED) {
|
|
||||||
scr->reneg_state = RENEG_DONE;
|
|
||||||
}
|
|
||||||
else if (!scr->is_proxy &&
|
|
||||||
(where & SSL_CB_ALERT) &&
|
|
||||||
(scr->reneg_state == RENEG_ALLOW || scr->reneg_state == RENEG_STARTED)) {
|
|
||||||
scr->reneg_state = RENEG_ALERT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* If the first handshake is complete, change state to reject any
|
/* If the first handshake is complete, change state to reject any
|
||||||
* subsequent client-initiated renegotiation. */
|
* subsequent client-initiated renegotiation. */
|
||||||
else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
|
else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) {
|
||||||
|
@@ -448,11 +448,6 @@ typedef struct {
|
|||||||
* renegotiation should be rejected */
|
* renegotiation should be rejected */
|
||||||
RENEG_ALLOW, /* A server-initiated renegotiation is taking
|
RENEG_ALLOW, /* A server-initiated renegotiation is taking
|
||||||
* place (as dictated by configuration) */
|
* place (as dictated by configuration) */
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
||||||
RENEG_STARTED, /* A renegotiation has started after RENEG_ALLOW */
|
|
||||||
RENEG_DONE, /* A renegotiation has finished after RENEG_STARTED */
|
|
||||||
RENEG_ALERT, /* A renegotiation has finished with an SSL Alert */
|
|
||||||
#endif
|
|
||||||
RENEG_ABORT /* Renegotiation initiated by client, abort the
|
RENEG_ABORT /* Renegotiation initiated by client, abort the
|
||||||
* connection */
|
* connection */
|
||||||
} reneg_state;
|
} reneg_state;
|
||||||
|
Reference in New Issue
Block a user