summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-10-07 10:04:12 -0400
committerNick Mathewson <nickm@torproject.org>2015-10-07 10:04:12 -0400
commitbd1a1378933815456cf8dc614be0281c5f085ef6 (patch)
treeafde7d135fdb2d0b87cd0e5511136a7df618873d
parent4e34ef87a48421e9b90bea30c5b1110ab0df81c2 (diff)
downloadtor-bd1a1378933815456cf8dc614be0281c5f085ef6.tar.gz
tor-bd1a1378933815456cf8dc614be0281c5f085ef6.zip
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.
-rw-r--r--changes/111506
-rw-r--r--src/common/tortls.c139
-rw-r--r--src/common/tortls.h3
-rw-r--r--src/or/connection_or.c50
-rw-r--r--src/test/test_tortls.c139
5 files changed, 15 insertions, 322 deletions
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 <b>tls</b>, 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 <b>tls</b>. 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 <b>name</b> 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 <b>tls</b>
- * 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
* <b>tls</b>. */
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
@@ -1195,143 +1195,6 @@ test_tortls_used_v1_handshake(void *ignored)
}
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)
{
(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),