From bd1a1378933815456cf8dc614be0281c5f085ef6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:04:12 -0400 Subject: [PATCH 1/6] Remove the client-side code for the v1 and v2 tls handshakes. (This is safe since super-old Tor servers are no longer allowed on the network.) Closes the client-side part of 11150. --- changes/11150 | 6 ++ src/common/tortls.c | 139 ----------------------------------------- src/common/tortls.h | 3 - src/or/connection_or.c | 50 +++------------ src/test/test_tortls.c | 139 ----------------------------------------- 5 files changed, 15 insertions(+), 322 deletions(-) create mode 100644 changes/11150 diff --git a/changes/11150 b/changes/11150 new file mode 100644 index 0000000000..7160b94e85 --- /dev/null +++ b/changes/11150 @@ -0,0 +1,6 @@ + o Removed features: + - Remove client-side support for connecting to Tor servers running + versions of Tor before 0.2.3.6-alpha. These servers didn't support + the v3 TLS handshake protocol, and + are no longer allowed on the Tor network. + Implements the client side of ticket 11150. diff --git a/src/common/tortls.c b/src/common/tortls.c index 156750853e..eda65a9538 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1985,52 +1985,6 @@ tor_tls_finish_handshake(tor_tls_t *tls) return r; } -#ifdef USE_BUFFEREVENTS -/** Put tls, which must be a client connection, into renegotiation - * mode. */ -int -tor_tls_start_renegotiating(tor_tls_t *tls) -{ - int r = SSL_renegotiate(tls->ssl); - if (r <= 0) { - return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN, - LD_HANDSHAKE); - } - return 0; -} -#endif - -/** Client only: Renegotiate a TLS session. When finished, returns - * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or - * TOR_TLS_WANTWRITE. - */ -int -tor_tls_renegotiate(tor_tls_t *tls) -{ - int r; - tor_assert(tls); - /* We could do server-initiated renegotiation too, but that would be tricky. - * Instead of "SSL_renegotiate, then SSL_do_handshake until done" */ - tor_assert(!tls->isServer); - - check_no_tls_errors(); - if (tls->state != TOR_TLS_ST_RENEGOTIATE) { - int r = SSL_renegotiate(tls->ssl); - if (r <= 0) { - return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN, - LD_HANDSHAKE); - } - tls->state = TOR_TLS_ST_RENEGOTIATE; - } - r = SSL_do_handshake(tls->ssl); - if (r == 1) { - tls->state = TOR_TLS_ST_OPEN; - return TOR_TLS_DONE; - } else - return tor_tls_get_error(tls, r, 0, "renegotiating handshake", LOG_INFO, - LD_HANDSHAKE); -} - /** Shut down an open tls connection tls. When finished, returns * TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, * or TOR_TLS_WANTWRITE. @@ -2424,99 +2378,6 @@ tor_tls_used_v1_handshake(tor_tls_t *tls) #endif } -/** Return true iff name is a DN of a kind that could only - * occur in a v3-handshake-indicating certificate */ -STATIC int -dn_indicates_v3_cert(X509_NAME *name) -{ -#ifdef DISABLE_V3_LINKPROTO_CLIENTSIDE - (void)name; - return 0; -#else - X509_NAME_ENTRY *entry; - int n_entries; - ASN1_OBJECT *obj; - ASN1_STRING *str; - unsigned char *s; - int len, r; - - n_entries = X509_NAME_entry_count(name); - if (n_entries != 1) { - return 1; /* More than one entry in the DN. */ - } - entry = X509_NAME_get_entry(name, 0); - - obj = X509_NAME_ENTRY_get_object(entry); - if (OBJ_obj2nid(obj) != OBJ_txt2nid("commonName")) { - return 1; /* The entry isn't a commonName. */ - } - - str = X509_NAME_ENTRY_get_data(entry); - len = ASN1_STRING_to_UTF8(&s, str); - if (len < 0) { - return 0; - } - r = fast_memneq(s + len - 4, ".net", 4); - OPENSSL_free(s); - return r; -#endif -} - -/** Return true iff the peer certificate we're received on tls - * indicates that this connection should use the v3 (in-protocol) - * authentication handshake. - * - * Only the connection initiator should use this, and only once the initial - * handshake is done; the responder detects a v1 handshake by cipher types, - * and a v3/v2 handshake by Versions cell vs renegotiation. - */ -int -tor_tls_received_v3_certificate(tor_tls_t *tls) -{ - check_no_tls_errors(); - - X509 *cert = SSL_get_peer_certificate(tls->ssl); - EVP_PKEY *key = NULL; - X509_NAME *issuer_name, *subject_name; - int is_v3 = 0; - - if (!cert) { - log_warn(LD_BUG, "Called on a connection with no peer certificate"); - goto done; - } - - subject_name = X509_get_subject_name(cert); - issuer_name = X509_get_issuer_name(cert); - - if (X509_name_cmp(subject_name, issuer_name) == 0) { - is_v3 = 1; /* purportedly self signed */ - goto done; - } - - if (dn_indicates_v3_cert(subject_name) || - dn_indicates_v3_cert(issuer_name)) { - is_v3 = 1; /* DN is fancy */ - goto done; - } - - key = X509_get_pubkey(cert); - if (EVP_PKEY_bits(key) != 1024 || - EVP_PKEY_type(key->type) != EVP_PKEY_RSA) { - is_v3 = 1; /* Key is fancy */ - goto done; - } - - done: - tls_log_errors(tls, LOG_WARN, LD_NET, "checking for a v3 cert"); - - if (key) - EVP_PKEY_free(key); - if (cert) - X509_free(cert); - - return is_v3; -} - /** Return the number of server handshakes that we've noticed doing on * tls. */ int diff --git a/src/common/tortls.h b/src/common/tortls.h index 1cfe029adb..55e4749612 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -135,7 +135,6 @@ STATIC int tor_tls_classify_client_ciphers(const SSL *ssl, STATIC int tor_tls_client_is_using_v2_ciphers(const SSL *ssl); MOCK_DECL(STATIC void, try_to_extract_certs_from_tls, (int severity, tor_tls_t *tls, X509 **cert_out, X509 **id_cert_out)); -STATIC int dn_indicates_v3_cert(X509_NAME *name); #ifndef HAVE_SSL_SESSION_GET_MASTER_KEY STATIC size_t SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out, size_t len); @@ -195,7 +194,6 @@ MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len)); int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n); int tor_tls_handshake(tor_tls_t *tls); int tor_tls_finish_handshake(tor_tls_t *tls); -int tor_tls_renegotiate(tor_tls_t *tls); void tor_tls_unblock_renegotiation(tor_tls_t *tls); void tor_tls_block_renegotiation(tor_tls_t *tls); void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls); @@ -213,7 +211,6 @@ int tor_tls_get_buffer_sizes(tor_tls_t *tls, MOCK_DECL(double, tls_get_write_overhead_ratio, (void)); int tor_tls_used_v1_handshake(tor_tls_t *tls); -int tor_tls_received_v3_certificate(tor_tls_t *tls); int tor_tls_get_num_server_handshakes(tor_tls_t *tls); int tor_tls_server_got_renegotiate(tor_tls_t *tls); MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index a967c93aca..8e12aa0cea 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1450,17 +1450,12 @@ connection_tls_continue_handshake(or_connection_t *conn) { int result; check_no_tls_errors(); - again: - if (conn->base_.state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) { - // log_notice(LD_OR, "Renegotiate with %p", conn->tls); - result = tor_tls_renegotiate(conn->tls); - // log_notice(LD_OR, "Result: %d", result); - } else { - tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING); - // log_notice(LD_OR, "Continue handshake with %p", conn->tls); - result = tor_tls_handshake(conn->tls); - // log_notice(LD_OR, "Result: %d", result); - } + + tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING); + // log_notice(LD_OR, "Continue handshake with %p", conn->tls); + result = tor_tls_handshake(conn->tls); + // log_notice(LD_OR, "Result: %d", result); + switch (result) { CASE_TOR_TLS_ERROR_ANY: log_info(LD_OR,"tls error [%s]. breaking connection.", @@ -1470,20 +1465,8 @@ connection_tls_continue_handshake(or_connection_t *conn) if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { - if (tor_tls_received_v3_certificate(conn->tls)) { - log_info(LD_OR, "Client got a v3 cert! Moving on to v3 " - "handshake with ciphersuite %s", - tor_tls_get_ciphersuite_name(conn->tls)); - return connection_or_launch_v3_or_handshake(conn); - } else { - log_debug(LD_OR, "Done with initial SSL handshake (client-side)." - " Requesting renegotiation."); - connection_or_change_state(conn, - OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING); - goto again; - } + return connection_or_launch_v3_or_handshake(conn); } - // log_notice(LD_OR,"Done. state was %d.", conn->base_.state); } else { /* v2/v3 handshake, but not a client. */ log_debug(LD_OR, "Done with initial SSL handshake (server-side). " @@ -1533,22 +1516,8 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event, if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { - if (tor_tls_received_v3_certificate(conn->tls)) { - log_info(LD_OR, "Client got a v3 cert!"); - if (connection_or_launch_v3_or_handshake(conn) < 0) - connection_or_close_for_error(conn, 0); - return; - } else { - connection_or_change_state(conn, - OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING); - tor_tls_unblock_renegotiation(conn->tls); - if (bufferevent_ssl_renegotiate(conn->base_.bufev)<0) { - log_warn(LD_OR, "Start_renegotiating went badly."); - connection_or_close_for_error(conn, 0); - } - tor_tls_unblock_renegotiation(conn->tls); - return; /* ???? */ - } + if (connection_or_launch_v3_or_handshake(conn) < 0) + connection_or_close_for_error(conn, 0); } } else { const int handshakes = tor_tls_get_num_server_handshakes(conn->tls); @@ -1844,7 +1813,6 @@ static int connection_or_launch_v3_or_handshake(or_connection_t *conn) { tor_assert(connection_or_nonopen_was_started_here(conn)); - tor_assert(tor_tls_received_v3_certificate(conn->tls)); circuit_build_times_network_is_live(get_circuit_build_times_mutable()); diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c index 2e53293373..5f202698ef 100644 --- a/src/test/test_tortls.c +++ b/src/test/test_tortls.c @@ -1194,143 +1194,6 @@ test_tortls_used_v1_handshake(void *ignored) tor_free(tls); } -static void -test_tortls_dn_indicates_v3_cert(void *ignored) -{ - (void)ignored; - int ret; - X509_NAME *name; - - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, - (const unsigned char *)"US", -1, -1, 0); - X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, - (const unsigned char *)"Foobar", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(name); - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, - (const unsigned char *)"US", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(name); - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "commonName", V_ASN1_REAL, - (const unsigned char *)"123", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 0); - - X509_NAME_free(name); - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC, - (const unsigned char *)"hello.com", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(name); - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC, - (const unsigned char *)"hello.net", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 0); - - X509_NAME_free(name); - name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_ASC, - (const unsigned char *)"x.s", -1, -1, 0); - ret = dn_indicates_v3_cert(name); - tt_int_op(ret, OP_EQ, 1); - - done: - X509_NAME_free(name); -} - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_received_v3_certificate(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - X509 *validCert = read_cert_from(validCertString); - X509_NAME *subject=NULL, *issuer=NULL; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 0); - - tls->ssl->session->peer = validCert; - - subject = X509_NAME_new(); - X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC, - (const unsigned char *)"same.com", -1, -1, 0); - X509_set_subject_name(validCert, subject); - - issuer = X509_NAME_new(); - X509_NAME_add_entry_by_txt(issuer, "commonName", MBSTRING_ASC, - (const unsigned char *)"same.com", -1, -1, 0); - X509_set_issuer_name(validCert, issuer); - - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(subject); - subject = X509_NAME_new(); - X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC, - (const unsigned char *)"different.net", -1, -1, 0); - X509_set_subject_name(validCert, subject); - - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(subject); - subject = X509_NAME_new(); - X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC, - (const unsigned char *)"same.com", -1, -1, 0); - X509_set_subject_name(validCert, subject); - - X509_NAME_free(issuer); - issuer = X509_NAME_new(); - X509_NAME_add_entry_by_txt(issuer, "commonName", MBSTRING_ASC, - (const unsigned char *)"different.net", -1, -1, 0); - X509_set_issuer_name(validCert, issuer); - - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 1); - - X509_NAME_free(subject); - subject = X509_NAME_new(); - X509_NAME_add_entry_by_txt(subject, "commonName", MBSTRING_ASC, - (const unsigned char *)"different2.net", -1, -1, 0); - X509_set_subject_name(validCert, subject); - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 0); - - EVP_PKEY *key = X509_get_pubkey(validCert); - key->type = 5; - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 1); - - key->type = 6; - key->ameth = NULL; - ret = tor_tls_received_v3_certificate(tls); - tt_int_op(ret, OP_EQ, 1); - - done: - X509_NAME_free(subject); - X509_NAME_free(issuer); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); -} -#endif - static void test_tortls_get_num_server_handshakes(void *ignored) { @@ -2913,8 +2776,6 @@ struct testcase_t tortls_tests[] = { LOCAL_TEST_CASE(get_forced_write_size, 0), LOCAL_TEST_CASE(get_write_overhead_ratio, TT_FORK), LOCAL_TEST_CASE(used_v1_handshake, TT_FORK), - LOCAL_TEST_CASE(dn_indicates_v3_cert, 0), - INTRUSIVE_TEST_CASE(received_v3_certificate, 0), LOCAL_TEST_CASE(get_num_server_handshakes, 0), LOCAL_TEST_CASE(server_got_renegotiate, 0), INTRUSIVE_TEST_CASE(SSL_SESSION_get_master_key, 0), From 2ad6e1bb0eeec88e8a2580a9b33a5dbadc995ba2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:07:29 -0400 Subject: [PATCH 2/6] Make the mis-named V2_HANDSHAKE_SERVER/CLIENT macros always-on. They selected the V2 handshake *and* the V3 handshake, in a strange mixture. Both handshakes have been mandatory for a long time. --- src/common/tortls.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index eda65a9538..62d8cab50f 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -83,11 +83,6 @@ #define X509_get_notAfter_const(cert) \ ((const ASN1_TIME*) X509_get_notAfter((X509 *)cert)) -/* Enable the "v2" TLS handshake. - */ -#define V2_HANDSHAKE_SERVER -#define V2_HANDSHAKE_CLIENT - /* Copied from or.h */ #define LEGAL_NICKNAME_CHARACTERS \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" @@ -1288,8 +1283,6 @@ tor_tls_get_ciphersuite_name(tor_tls_t *tls) return SSL_get_cipher(tls->ssl); } -#ifdef V2_HANDSHAKE_SERVER - /* Here's the old V2 cipher list we sent from 0.2.1.1-alpha up to * 0.2.3.17-beta. If a client is using this list, we can't believe the ciphers * that it claims to support. We'll prune this list to remove the ciphers @@ -1569,7 +1562,6 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) } } } -#endif /** Callback to get invoked on a server after we've read the list of ciphers * the client supports, but before we pick our own ciphersuite. @@ -1679,12 +1671,9 @@ 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 - { + } else { SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); } @@ -1723,13 +1712,11 @@ 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 } /** If this version of openssl requires it, turn on renegotiation on @@ -1816,7 +1803,6 @@ tor_tls_read,(tor_tls_t *tls, char *cp, size_t len)) tor_assert(lenssl, cp, (int)len); if (r > 0) { -#ifdef V2_HANDSHAKE_SERVER if (tls->got_renegotiate) { /* Renegotiation happened! */ log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls)); @@ -1824,7 +1810,6 @@ tor_tls_read,(tor_tls_t *tls, char *cp, size_t len)) tls->negotiated_callback(tls, tls->callback_arg); tls->got_renegotiate = 0; } -#endif return r; } err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); @@ -1941,7 +1926,6 @@ tor_tls_finish_handshake(tor_tls_t *tls) SSL_set_info_callback(tls->ssl, NULL); SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb); SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN); -#ifdef V2_HANDSHAKE_SERVER if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) { /* This check is redundant, but back when we did it in the callback, * we might have not been able to look up the tor_tls_t if the code @@ -1956,9 +1940,9 @@ tor_tls_finish_handshake(tor_tls_t *tls) } else { tls->wasV2Handshake = 0; } -#endif } else { -#ifdef V2_HANDSHAKE_CLIENT +#if 1111 + /* XXXXXXXX remove v1 detection support, NM! */ /* If we got no ID cert, we're a v2 handshake. */ X509 *cert = SSL_get_peer_certificate(tls->ssl); STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl); @@ -2362,20 +2346,7 @@ check_no_tls_errors_(const char *fname, int line) int tor_tls_used_v1_handshake(tor_tls_t *tls) { -#if defined(V2_HANDSHAKE_SERVER) && defined(V2_HANDSHAKE_CLIENT) return ! tls->wasV2Handshake; -#else - if (tls->isServer) { -# ifdef V2_HANDSHAKE_SERVER - return ! tls->wasV2Handshake; -# endif - } else { -# ifdef V2_HANDSHAKE_CLIENT - return ! tls->wasV2Handshake; -# endif - } - return 1; -#endif } /** Return the number of server handshakes that we've noticed doing on From 6505d529a5cc669ee723d818a614fe7663e5c0ea Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:10:08 -0400 Subject: [PATCH 3/6] Remove client-side support for detecting v1 handshake Fixes more of 11150 --- src/common/tortls.c | 22 +++------------------- src/or/connection_or.c | 7 +++---- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index 62d8cab50f..4321330708 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1941,25 +1941,9 @@ tor_tls_finish_handshake(tor_tls_t *tls) tls->wasV2Handshake = 0; } } else { -#if 1111 - /* XXXXXXXX remove v1 detection support, NM! */ - /* If we got no ID cert, we're a v2 handshake. */ - X509 *cert = SSL_get_peer_certificate(tls->ssl); - STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl); - int n_certs = sk_X509_num(chain); - if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) { - log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it " - "looks like a v1 handshake on %p", tls); - tls->wasV2Handshake = 0; - } else { - log_debug(LD_HANDSHAKE, - "Server sent back a single certificate; looks like " - "a v2 handshake on %p.", tls); - tls->wasV2Handshake = 1; - } - if (cert) - X509_free(cert); -#endif + /* Client-side */ + tls->wasV2Handshake = 1; + /* XXXX this can move, probably? -NM */ if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) { tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers"); r = TOR_TLS_ERROR_MISC; diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 8e12aa0cea..c08dc4bd12 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1783,11 +1783,10 @@ connection_tls_finish_handshake(or_connection_t *conn) circuit_build_times_network_is_live(get_circuit_build_times_mutable()); if (tor_tls_used_v1_handshake(conn->tls)) { + tor_assert(!started_here); conn->link_proto = 1; - if (!started_here) { - connection_or_init_conn_from_address(conn, &conn->base_.addr, - conn->base_.port, digest_rcvd, 0); - } + connection_or_init_conn_from_address(conn, &conn->base_.addr, + conn->base_.port, digest_rcvd, 0); tor_tls_block_renegotiation(conn->tls); rep_hist_note_negotiated_link_proto(1, started_here); return connection_or_set_state_open(conn); From 5bd3290df3254e6ffb3ac80150f8c8217fd0ac66 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:16:37 -0400 Subject: [PATCH 4/6] Remove workaround code for broken client-side renegotiation Since 11150 removed client-side support for renegotiation, we no longer need to make sure we have an openssl/TLSvX combination that supports it (client-side) --- src/common/tortls.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/common/tortls.c b/src/common/tortls.c index 4321330708..86f48a45dd 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1124,23 +1124,6 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, * historically been chosen for fingerprinting resistance. */ SSL_CTX_set_options(result->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); - /* Disable TLS1.1 and TLS1.2 if they exist. We need to do this to - * workaround a bug present in all OpenSSL 1.0.1 versions (as of 1 - * June 2012), wherein renegotiating while using one of these TLS - * protocols will cause the client to send a TLS 1.0 ServerHello - * rather than a ServerHello written with the appropriate protocol - * version. Once some version of OpenSSL does TLS1.1 and TLS1.2 - * renegotiation properly, we can turn them back on when built with - * that version. */ -#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,1,'e') -#ifdef SSL_OP_NO_TLSv1_2 - SSL_CTX_set_options(result->ctx, SSL_OP_NO_TLSv1_2); -#endif -#ifdef SSL_OP_NO_TLSv1_1 - SSL_CTX_set_options(result->ctx, SSL_OP_NO_TLSv1_1); -#endif -#endif - /* Disable TLS tickets if they're supported. We never want to use them; * using them can make our perfect forward secrecy a little worse, *and* * create an opportunity to fingerprint us (since it's unusual to use them From 22471026574b3384e9919529a37c56548ea4c293 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:25:00 -0400 Subject: [PATCH 5/6] credit tvdw --- changes/11150 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/changes/11150 b/changes/11150 index 7160b94e85..b4d40ed07c 100644 --- a/changes/11150 +++ b/changes/11150 @@ -1,6 +1,6 @@ o Removed features: - Remove client-side support for connecting to Tor servers running - versions of Tor before 0.2.3.6-alpha. These servers didn't support - the v3 TLS handshake protocol, and - are no longer allowed on the Tor network. - Implements the client side of ticket 11150. + versions of Tor before 0.2.3.6-alpha. These servers didn't + support the v3 TLS handshake protocol, and are no longer allowed + on the Tor network. Implements the client side of ticket + 11150. Based on patches by Tom van der Woerdt. From 9d019a7db725dca3dfdbf8d4dbc3b51835e0b49e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 7 Oct 2015 10:32:54 -0400 Subject: [PATCH 6/6] tor_tls_finish_handshake is server-side only. --- src/or/connection_or.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/or/connection_or.c b/src/or/connection_or.c index c08dc4bd12..59dea37abd 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1464,11 +1464,10 @@ connection_tls_continue_handshake(or_connection_t *conn) case TOR_TLS_DONE: if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { - if (conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING) { - return connection_or_launch_v3_or_handshake(conn); - } + tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING); + return connection_or_launch_v3_or_handshake(conn); } else { - /* v2/v3 handshake, but not a client. */ + /* v2/v3 handshake, but we are not a client. */ log_debug(LD_OR, "Done with initial SSL handshake (server-side). " "Expecting renegotiation or VERSIONS cell"); tor_tls_set_renegotiate_callback(conn->tls, @@ -1481,6 +1480,7 @@ connection_tls_continue_handshake(or_connection_t *conn) return 0; } } + tor_assert(!tor_tls_is_server(conn->tls)); return connection_tls_finish_handshake(conn); case TOR_TLS_WANTWRITE: connection_start_writing(TO_CONN(conn)); @@ -1769,6 +1769,8 @@ connection_tls_finish_handshake(or_connection_t *conn) char digest_rcvd[DIGEST_LEN]; int started_here = connection_or_nonopen_was_started_here(conn); + tor_assert(!started_here); + log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done, using " "ciphersuite %s. verifying.", started_here?"outgoing":"incoming", @@ -1783,7 +1785,6 @@ connection_tls_finish_handshake(or_connection_t *conn) circuit_build_times_network_is_live(get_circuit_build_times_mutable()); if (tor_tls_used_v1_handshake(conn->tls)) { - tor_assert(!started_here); conn->link_proto = 1; connection_or_init_conn_from_address(conn, &conn->base_.addr, conn->base_.port, digest_rcvd, 0); @@ -1794,10 +1795,8 @@ connection_tls_finish_handshake(or_connection_t *conn) connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V2); if (connection_init_or_handshake_state(conn, started_here) < 0) return -1; - if (!started_here) { - connection_or_init_conn_from_address(conn, &conn->base_.addr, - conn->base_.port, digest_rcvd, 0); - } + connection_or_init_conn_from_address(conn, &conn->base_.addr, + conn->base_.port, digest_rcvd, 0); return connection_or_send_versions(conn, 0); } }