From 1744e447a15216b74f239b30da735416dd1fde92 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 29 Jan 2010 17:02:17 -0500 Subject: [PATCH] Decide whether to use SSL flags based on runtime OpenSSL version. We need to do this because Apple doesn't update its dev-tools headers when it updates its libraries in a security patch. On the bright side, this might get us out of shipping a statically linked OpenSSL on OSX. May fix bug 1225. [backported] --- ChangeLog | 6 ++++++ src/common/tortls.c | 61 ++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71ab2d7220..592c39f8a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,12 @@ Changes in version 0.2.1.23 - 2010-0?-?? automatically discard guards picked using the old algorithm. Fixes bug 1217; bugfix on 0.2.1.3-alpha. Found by Mike Perry. + o Minor bugfixes: + - When deciding whether to use strange flags to turn TLS renegotiation + on, detect the OpenSSL version at run-time, not compile time. We + need to do this because Apple doesn't update its dev-tools headers + when it updates its libraries in a security patch. + o Minor features: - Avoid a mad rush at the beginning of each month when each client rotates half of its guards. Instead we spread the rotation out diff --git a/src/common/tortls.c b/src/common/tortls.c index beab5356c5..1b9e681970 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -53,6 +53,24 @@ #define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer") +/* We redefine these so that we can run correctly even if the vendor gives us + * a version of OpenSSL that does not match its header files. (Apple: I am + * looking at you.) + */ +#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION +#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L +#endif +#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION +#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010 +#endif + +/** Does the run-time openssl version look like we need + * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ +static int use_unsafe_renegotiation_op = 0; +/** Does the run-time openssl version look like we need + * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ +static int use_unsafe_renegotiation_flag = 0; + /** Structure holding the TLS state for a single connection. */ typedef struct tor_tls_context_t { int refcnt; @@ -309,9 +327,29 @@ static void tor_tls_init(void) { if (!tls_library_is_initialized) { + long version; SSL_library_init(); SSL_load_error_strings(); crypto_global_init(-1); + + version = SSLeay(); + if (version >= 0x009070c0L && version < 0x00908000L) { + log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.7l or later; " + "I will try SSL3_FLAGS and SSL3_OP to enable renegotation", + SSLeay_version(SSLEAY_VERSION)); + use_unsafe_renegotiation_flag = 1; + use_unsafe_renegotiation_op = 1; + } else if (version >= 0x009080c0L) { + log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8l or later; " + "I will try SSL3_FLAGS and SSL_OP to enable renegotiation", + SSLeay_version(SSLEAY_VERSION)); + use_unsafe_renegotiation_flag = 1; + use_unsafe_renegotiation_op = 1; + } else { + log_info(LD_GENERAL, "OpenSSL %s has version %lx", + SSLeay_version(SSLEAY_VERSION), version); + } + tls_library_is_initialized = 1; } } @@ -568,7 +606,6 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) SSL_CTX_set_options(result->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif -#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. * @@ -577,9 +614,10 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) * seems) broke anything that used SSL3_FLAGS_* for the purpose. So we need * to do both.) */ - SSL_CTX_set_options(result->ctx, - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); -#endif + if (use_unsafe_renegotiation_op) { + SSL_CTX_set_options(result->ctx, + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); + } /* Don't actually allow compression; it uses ram and time, but the data * we transmit is all encrypted anyway. */ if (result->ctx->comp_methods) @@ -920,19 +958,16 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls, } /** If this version of openssl requires it, turn on renegotiation on - * tls. (Our protocol never requires this for security, but it's nice - * to use belt-and-suspenders here.) + * tls. */ static void tor_tls_unblock_renegotiation(tor_tls_t *tls) { -#ifdef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ - tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; -#else - (void)tls; -#endif + if (use_unsafe_renegotiation_flag) { + tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + } } /** If this version of openssl supports it, turn off renegotiation on @@ -942,11 +977,7 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls) void tor_tls_block_renegotiation(tor_tls_t *tls) { -#ifdef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; -#else - (void)tls; -#endif } /** Return whether this tls initiated the connect (client) or -- 2.11.4.GIT