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.
This commit is contained in:
Nick Mathewson 2010-01-29 17:02:17 -05:00
parent f75f7322b9
commit 8d68e5c748
2 changed files with 52 additions and 15 deletions

View File

@ -1,4 +1,10 @@
Changes in version 0.2.2.9-alpha - 2010-??-?? Changes in version 0.2.2.9-alpha - 2010-??-??
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 Code simplifications and refactoring: o Code simplifications and refactoring:
- Generate our manpage and HTML documentation using Asciidoc. This - Generate our manpage and HTML documentation using Asciidoc. This
should make it easier to maintain the documentation, and produce should make it easier to maintain the documentation, and produce

View File

@ -53,6 +53,24 @@
#define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer") #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. */ /** Structure holding the TLS state for a single connection. */
typedef struct tor_tls_context_t { typedef struct tor_tls_context_t {
int refcnt; int refcnt;
@ -333,8 +351,28 @@ static void
tor_tls_init(void) tor_tls_init(void)
{ {
if (!tls_library_is_initialized) { if (!tls_library_is_initialized) {
long version;
SSL_library_init(); SSL_library_init();
SSL_load_error_strings(); SSL_load_error_strings();
version = SSLeay();
if (version >= 0x009070c0L && version < 0x00908000L) {
log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.7l or later; "
"I will use SSL3_FLAGS to enable renegotation",
SSLeay_version(SSLEAY_VERSION));
use_unsafe_renegotiation_flag = 1;
use_unsafe_renegotiation_op = 1;
} else if (version >= 0x009080d0L) {
log_notice(LD_GENERAL, "OpenSSL %s looks like version 0.9.8m or later; "
"I will use 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; tls_library_is_initialized = 1;
} }
} }
@ -591,7 +629,6 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
SSL_CTX_set_options(result->ctx, SSL_CTX_set_options(result->ctx,
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif #endif
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
/* Yes, we know what we are doing here. No, we do not treat a renegotiation /* Yes, we know what we are doing here. No, we do not treat a renegotiation
* as authenticating any earlier-received data. * as authenticating any earlier-received data.
* *
@ -600,9 +637,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 * seems) broke anything that used SSL3_FLAGS_* for the purpose. So we need
* to do both.) * to do both.)
*/ */
if (use_unsafe_renegotiation_op) {
SSL_CTX_set_options(result->ctx, SSL_CTX_set_options(result->ctx,
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
#endif }
/* Don't actually allow compression; it uses ram and time, but the data /* Don't actually allow compression; it uses ram and time, but the data
* we transmit is all encrypted anyway. */ * we transmit is all encrypted anyway. */
if (result->ctx->comp_methods) if (result->ctx->comp_methods)
@ -943,19 +981,16 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
} }
/** If this version of openssl requires it, turn on renegotiation on /** If this version of openssl requires it, turn on renegotiation on
* <b>tls</b>. (Our protocol never requires this for security, but it's nice * <b>tls</b>.
* to use belt-and-suspenders here.)
*/ */
static void static void
tor_tls_unblock_renegotiation(tor_tls_t *tls) 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 /* Yes, we know what we are doing here. No, we do not treat a renegotiation
* as authenticating any earlier-received data. */ * as authenticating any earlier-received data. */
if (use_unsafe_renegotiation_flag) {
tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
#else }
(void)tls;
#endif
} }
/** If this version of openssl supports it, turn off renegotiation on /** If this version of openssl supports it, turn off renegotiation on
@ -965,11 +1000,7 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls)
void void
tor_tls_block_renegotiation(tor_tls_t *tls) 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; tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
#else
(void)tls;
#endif
} }
/** Return whether this tls initiated the connect (client) or /** Return whether this tls initiated the connect (client) or