commit ecd239e3b577705e0669d47293a2e755cf93cec0 Author: George Kadianakis desnacked@gmail.com Date: Wed Oct 26 03:12:18 2011 +0200
Detect and deny excess renegotiations attempts.
Switch 'server_handshake_count' from a uint8_t to 2 unsigned int bits. Since we won't ever be doing more than 3 handshakes, we don't need the extra space.
Toggle tor_tls_t.got_renegotiate based on the server_handshake_count. Also assert that when we've done two handshakes as a server (the initial SSL handshake, and the renegotiation handshake) we've just renegotiated.
Finally, in tor_tls_read() return an error if we see more than 2 handshakes. --- src/common/tortls.c | 20 +++++++++++++++----- 1 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/common/tortls.c b/src/common/tortls.c index 79b6d2c..7269785 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -146,7 +146,7 @@ struct tor_tls_t { /** True iff we should call negotiated_callback when we're done reading. */ unsigned int got_renegotiate:1; /** Incremented every time we start the server side of a handshake. */ - uint8_t server_handshake_count; + unsigned int server_handshake_count:2; size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last * time. */ /** Last values retrieved from BIO_number_read()/write(); see @@ -1286,12 +1286,14 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) static void tor_tls_got_server_hello(tor_tls_t *tls) { - /* Check whether we're watching for renegotiates. If so, this is one! */ - if (tls->negotiated_callback) - tls->got_renegotiate = 1; - if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/ + if (tls->server_handshake_count < 3) ++tls->server_handshake_count;
+ if (tls->server_handshake_count == 2) { + tor_assert(tls->negotiated_callback); + tls->got_renegotiate = 1; + } + /* Now check the cipher list. */ if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) { /*XXXX_TLS keep this from happening more than once! */ @@ -1625,6 +1627,14 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) tls->got_renegotiate = 0;
return r; + } else if (tls->server_handshake_count > 2) { + /* If we get more than 2 handshakes, it means that our peer is + trying to re-renegotiate. Return an error. */ + tor_assert(tls->server_handshake_count == 3); + + log_info(LD_NET, "Detected excess renegotiation from %s!", ADDR(tls)); + + return TOR_TLS_ERROR_MISC; } #endif