diff --git a/src/common/tortls.c b/src/common/tortls.c index 9a3c02b5b3..6757cfa780 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1280,55 +1280,29 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) return 1; } +/** We sent the ServerHello part of an SSL handshake. This might mean + * that we completed a renegotiation and appropriate actions must be + * taken. */ static void -tor_tls_debug_state_callback(const SSL *ssl, int type, int val) +tor_tls_got_server_hello(tor_tls_t *tls) { - log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].", - ssl, ssl_state_to_string(ssl->state), type, val); -} - -/** Invoked when we're accepting a connection on ssl, and the connection - * changes state. We use this: - * - */ -static void -tor_tls_server_info_callback(const SSL *ssl, int type, int val) -{ - tor_tls_t *tls; - (void) val; - - tor_tls_debug_state_callback(ssl, type, val); - - if (type != SSL_CB_ACCEPT_LOOP) - return; - if (ssl->state != SSL3_ST_SW_SRVR_HELLO_A) - return; - - tls = tor_tls_get_by_ssl(ssl); - if (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*/ - ++tls->server_handshake_count; - } else { - log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); - return; - } + /* 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*/ + ++tls->server_handshake_count; /* Now check the cipher list. */ - if (tor_tls_client_is_using_v2_ciphers(ssl, ADDR(tls))) { + if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) { /*XXXX_TLS keep this from happening more than once! */ /* Yes, we're casting away the const from ssl. This is very naughty of us. * Let's hope openssl doesn't notice! */ /* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */ - SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN); + SSL_set_mode((SSL*) tls->ssl, SSL_MODE_NO_AUTO_CHAIN); /* Don't send a hello request. */ - SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL); + SSL_set_verify((SSL*) tls->ssl, SSL_VERIFY_NONE, NULL); if (tls) { tls->wasV2Handshake = 1; @@ -1343,6 +1317,35 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) } #endif +/** This is a callback function for SSL_set_info_callback() and it + * will be called in every SSL state change. + * It logs the SSL state change, and executes any actions that must be + * taken. */ +static void +tor_tls_state_changed_callback(const SSL *ssl, int type, int val) +{ + log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].", + ssl, ssl_state_to_string(ssl->state), type, val); + +#ifdef V2_HANDSHAKE_SERVER + if (type == SSL_CB_ACCEPT_LOOP && + ssl->state == SSL3_ST_SW_SRVR_HELLO_A) { + + /* Call tor_tls_got_server_hello() for every SSL ServerHello we + send. */ + + tor_tls_t *tls = tor_tls_get_by_ssl(ssl); + if (!tls) { + log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); + return; + } + + tor_tls_got_server_hello(tls); + } +#endif + +} + /** Replace *ciphers with a new list of SSL ciphersuites: specifically, * a list designed to mimic a common web browser. Some of the ciphers in the * list won't actually be implemented by OpenSSL: that's okay so long as the @@ -1484,14 +1487,8 @@ tor_tls_new(int sock, int isServer) log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu", result->last_read_count, result->last_write_count); } -#ifdef V2_HANDSHAKE_SERVER - if (isServer) { - SSL_set_info_callback(result->ssl, tor_tls_server_info_callback); - } else -#endif - { - SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); - } + + SSL_set_info_callback(result->ssl, tor_tls_state_changed_callback); /* Not expected to get called. */ tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object"); @@ -1521,13 +1518,7 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls, tls->negotiated_callback = cb; tls->callback_arg = arg; tls->got_renegotiate = 0; -#ifdef V2_HANDSHAKE_SERVER - if (cb) { - SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback); - } else { - SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback); - } -#endif + SSL_set_info_callback(tls->ssl, tor_tls_state_changed_callback); } /** If this version of openssl requires it, turn on renegotiation on