diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-11-05 18:13:08 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2009-11-05 18:13:08 -0500 |
commit | ce0a89e2624471272ffc4950c5069d9b81a7f0b9 (patch) | |
tree | 3f430604ba70db318b670429c65e0f21ebca4e5e /src/common/tortls.c | |
parent | 54973a45a693cf3e0dada2572016fa6695a51e75 (diff) | |
download | tor-ce0a89e2624471272ffc4950c5069d9b81a7f0b9.tar.gz tor-ce0a89e2624471272ffc4950c5069d9b81a7f0b9.zip |
Make Tor work with OpenSSL 0.9.8l
To fix a major security problem related to incorrect use of
SSL/TLS renegotiation, OpenSSL has turned off renegotiation by
default. We are not affected by this security problem, however,
since we do renegotiation right. (Specifically, we never treat a
renegotiated credential as authenticating previous communication.)
Nevertheless, OpenSSL's new behavior requires us to explicitly
turn renegotiation back on in order to get our protocol working
again.
Amusingly, this is not so simple as "set the flag when you create
the SSL object" , since calling connect or accept seems to clear
the flags.
For belt-and-suspenders purposes, we clear the flag once the Tor
handshake is done. There's no way to exploit a second handshake
either, but we might as well not allow it.
Diffstat (limited to 'src/common/tortls.c')
-rw-r--r-- | src/common/tortls.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index c6b11e9a6e..bcc6780a65 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -154,6 +154,7 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname, const char *cname_sign, unsigned int lifetime); +static void tor_tls_unblock_renegotiation(tor_tls_t *tls); /** Global tls context. We keep it here because nobody else needs to * touch it. */ @@ -904,6 +905,36 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls, #endif } +/** 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 + * to use belt-and-suspenders here.) + */ +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 this version of openssl supports it, turn off renegotiation on + * <b>tls</b>. (Our protocol never requires this for security, but it's nice + * to use belt-and-suspenders here.) + */ +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 * received it (server). */ int @@ -1026,6 +1057,9 @@ tor_tls_handshake(tor_tls_t *tls) } else { r = SSL_connect(tls->ssl); } + /* We need to call this here and not earlier, since OpenSSL has a penchant + * for clearing its flags when you say accept or connect. */ + tor_tls_unblock_renegotiation(tls); r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO); if (ERR_peek_error() != 0) { tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, |