From 1b551823de6e6c03cf86bcbb7ca1b687c5f16ea6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 10 Jun 2014 11:11:47 -0400 Subject: [PATCH 1/6] Avoid illegal read off end of an array in prune_v2_cipher_list This function is supposed to construct a list of all the ciphers in the "v2 link protocol cipher list" that are supported by Tor's openssl. It does this by invoking ssl23_get_cipher_by_char on each two-byte ciphersuite ID to see which ones give a match. But when ssl23_get_cipher_by_char cannot find a match for a two-byte SSL3/TLS ciphersuite ID, it checks to see whether it has a match for a three-byte SSL2 ciphersuite ID. This was causing a read off the end of the 'cipherid' array. This was probably harmless in practice, but we shouldn't be having any uninitialized reads. (Using ssl23_get_cipher_by_char in this way is a kludge, but then again the entire existence of the v2 link protocol is kind of a kludge. Once Tor 0.2.2 clients are all gone, we can drop this code entirely.) Found by starlight. Fix on 0.2.4.8-alpha. Fixes bug 12227. --- changes/bug12227 | 5 +++++ src/common/tortls.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 changes/bug12227 diff --git a/changes/bug12227 b/changes/bug12227 new file mode 100644 index 000000000..d8b5d08a5 --- /dev/null +++ b/changes/bug12227 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Avoid an illegal read from stack when initializing the TLS + module using a version of OpenSSL without all of the ciphers + used by the v2 link handshake. Fixes bug 12227; bugfix on + 0.2.4.8-alpha. Found by "starlight". diff --git a/src/common/tortls.c b/src/common/tortls.c index 8f3f6a713..c13b12fd4 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -1489,10 +1489,13 @@ prune_v2_cipher_list(void) inp = outp = v2_cipher_list; while (*inp) { - unsigned char cipherid[2]; + unsigned char cipherid[3]; const SSL_CIPHER *cipher; /* Is there no better way to do this? */ set_uint16(cipherid, htons(*inp)); + cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting + * with a two-byte 'cipherid', it may look for a v2 + * cipher with the appropriate 3 bytes. */ cipher = m->get_cipher_by_char(cipherid); if (cipher) { tor_assert((cipher->id & 0xffff) == *inp); From e001610c99bea661dbefc693ec173a90fcb3ee5e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 31 Oct 2013 16:44:14 -0400 Subject: [PATCH 2/6] Implement proposal 221: Stop sending CREATE_FAST This makes FastFirstHopPK an AUTOBOOL; makes the default "auto"; and makes the behavior of "auto" be "look at the consensus." --- changes/prop221 | 6 ++++++ doc/tor.1.txt | 8 +++++--- src/or/circuitbuild.c | 8 +++++--- src/or/config.c | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 changes/prop221 diff --git a/changes/prop221 b/changes/prop221 new file mode 100644 index 000000000..b2bf44bc3 --- /dev/null +++ b/changes/prop221 @@ -0,0 +1,6 @@ + o Minor features: + - Stop sending the CREATE_FAST cells by default; instead, use a + parameter in the consensus to decide whether to use + CREATE_FAST. This can improve security on connections where + Tor's circuit handshake is stronger than the available TLS + connection security levels. Implements proposal 221. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 779db61c2..4f3612b10 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1119,15 +1119,17 @@ The following options are useful only for clients (that is, if the node "foo". Disabled by default since attacking websites and exit relays can use it to manipulate your path selection. (Default: 0) -[[FastFirstHopPK]] **FastFirstHopPK** **0**|**1**:: +[[FastFirstHopPK]] **FastFirstHopPK** **0**|**1**|**auto**:: When this option is disabled, Tor uses the public key step for the first hop of creating circuits. Skipping it is generally safe since we have already used TLS to authenticate the relay and to establish forward-secure - keys. Turning this option off makes circuit building slower. + + keys. Turning this option off makes circuit building a little + slower. Setting this option to "auto" takes advice from the authorities + in the latest consensus about whether to use this feature. + + Note that Tor will always use the public key step for the first hop if it's operating as a relay, and it will never use the public key step if it - doesn't yet know the onion key of the first hop. (Default: 1) + doesn't yet know the onion key of the first hop. (Default: auto) [[TransPort]] **TransPort** \['address':]__port__|**auto** [_isolation flags_]:: Open this port to listen for transparent proxy connections. Set this to diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 2b4d3c311..4603de071 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -663,16 +663,18 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) if (!circ->cpath->extend_info->onion_key) return 1; /* our hand is forced: only a create_fast will work. */ - if (!options->FastFirstHopPK) - return 0; /* we prefer to avoid create_fast */ if (public_server_mode(options)) { /* We're a server, and we know an onion key. We can choose. * Prefer to blend our circuit into the other circuits we are * creating on behalf of others. */ return 0; } + if (options->FastFirstHopPK == -1) { + /* option is "auto", so look at the consensus. */ + return networkstatus_get_param(NULL, "usecreatefast", 1, 0, 1); + } - return 1; + return options->FastFirstHopPK; } /** Return true if circ is the type of circuit we want to count diff --git a/src/or/config.c b/src/or/config.c index a2811ebc2..1de91878b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -236,7 +236,7 @@ static config_var_t option_vars_[] = { OBSOLETE("FallbackNetworkstatusFile"), V(FascistFirewall, BOOL, "0"), V(FirewallPorts, CSV, ""), - V(FastFirstHopPK, BOOL, "1"), + V(FastFirstHopPK, AUTOBOOL, "auto"), V(FetchDirInfoEarly, BOOL, "0"), V(FetchDirInfoExtraEarly, BOOL, "0"), V(FetchServerDescriptors, BOOL, "1"), From d5558f00729992a9abeeb1cb1512004de35ec007 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 31 Oct 2013 16:53:31 -0400 Subject: [PATCH 3/6] circuit_build_failed: distinguish "first hop chan failed", "CREATE failed" Roger spotted this on tor-dev in his comments on proposal 221. (Actually, detect DESTROY vs everything else, since arma likes network timeout indicating failure but not overload indicating failure.) --- src/or/circuituse.c | 9 +++++---- src/or/command.c | 1 + src/or/or.h | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index c2d2b2e87..06a51a04a 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1382,10 +1382,11 @@ circuit_build_failed(origin_circuit_t *circ) failed_at_last_hop = 1; } if (circ->cpath && - circ->cpath->state != CPATH_STATE_OPEN) { - /* We failed at the first hop. If there's an OR connection - * to blame, blame it. Also, avoid this relay for a while, and - * fail any one-hop directory fetches destined for it. */ + circ->cpath->state != CPATH_STATE_OPEN && + ! circ->base_.received_destroy) { + /* We failed at the first hop for some reason other than a DESTROY cell. + * If there's an OR connection to blame, blame it. Also, avoid this relay + * for a while, and fail any one-hop directory fetches destined for it. */ const char *n_chan_id = circ->cpath->extend_info->identity_digest; int already_marked = 0; if (circ->base_.n_chan) { diff --git a/src/or/command.c b/src/or/command.c index 699b02fb4..51d07b048 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -499,6 +499,7 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan) log_debug(LD_OR,"Received for circID %u.",(unsigned)cell->circ_id); reason = (uint8_t)cell->payload[0]; + circ->received_destroy = 1; if (!CIRCUIT_IS_ORIGIN(circ) && cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) { diff --git a/src/or/or.h b/src/or/or.h index 3eaf3447d..34f055cf0 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2785,6 +2785,9 @@ typedef struct circuit_t { * allowing n_streams to add any more cells. (OR circuit only.) */ unsigned int streams_blocked_on_p_chan : 1; + /** True iff this circuit has received a DESTROY cell in either direction */ + unsigned int received_destroy : 1; + uint8_t state; /**< Current status of this circuit. */ uint8_t purpose; /**< Why are we creating this circuit? */ From 8f70d756fb5af54cc184d4683e445161f91cf1d1 Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Sun, 27 Jul 2014 18:05:01 +0200 Subject: [PATCH 4/6] Confusing log message when circuit can't be extended --- src/or/control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/control.c b/src/or/control.c index a88de12d6..ae9dd69d2 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2506,7 +2506,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, goto done; } if (!node_has_descriptor(node)) { - connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n); + connection_printf_to_buf(conn, "552 No descriptor for \"%s\"\r\n", n); goto done; } smartlist_add(nodes, (void*)node); From 8882dcfc598edde4d78c14ea0b90c8ed7f189274 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sun, 27 Jul 2014 15:41:30 -0400 Subject: [PATCH 5/6] add a changes file for bug 12718 --- changes/bug12718 | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changes/bug12718 diff --git a/changes/bug12718 b/changes/bug12718 new file mode 100644 index 000000000..0c5f70844 --- /dev/null +++ b/changes/bug12718 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Correct a confusing error message when trying to extend a circuit + via the control protocol but we don't know a descriptor or + microdescriptor for one of the specified relays. Fixes bug 12718; + bugfix on 0.2.3.1-alpha. From 68a2e4ca4baa595cc4595a511db11fa7ccbbc8f7 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 28 Jul 2014 02:44:05 -0400 Subject: [PATCH 6/6] Warn and drop the circuit if we receive an inbound 'relay early' cell Those used to be normal to receive on hidden service circuits due to bug 1038, but the buggy Tor versions are long gone from the network so we can afford to resume watching for them. Resolves the rest of bug 1038; bugfix on 0.2.1.19. --- changes/bug1038-3 | 6 ++++++ src/or/command.c | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 changes/bug1038-3 diff --git a/changes/bug1038-3 b/changes/bug1038-3 new file mode 100644 index 000000000..5af4afa46 --- /dev/null +++ b/changes/bug1038-3 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Warn and drop the circuit if we receive an inbound 'relay early' + cell. Those used to be normal to receive on hidden service circuits + due to bug 1038, but the buggy Tor versions are long gone from + the network so we can afford to resume watching for them. Resolves + the rest of bug 1038; bugfix on 0.2.1.19. diff --git a/src/or/command.c b/src/or/command.c index 51d07b048..78fd4fad3 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -443,10 +443,22 @@ command_process_relay_cell(cell_t *cell, channel_t *chan) * gotten no more than MAX_RELAY_EARLY_CELLS_PER_CIRCUIT of them. */ if (cell->command == CELL_RELAY_EARLY) { if (direction == CELL_DIRECTION_IN) { - /* Allow an unlimited number of inbound relay_early cells, - * for hidden service compatibility. There isn't any way to make - * a long circuit through inbound relay_early cells anyway. See - * bug 1038. -RD */ + /* Inbound early cells could once be encountered as a result of + * bug 1038; but relays running versions before 0.2.1.19 are long + * gone from the network, so any such cells now are surprising. */ + log_warn(LD_OR, + "Received an inbound RELAY_EARLY cell on circuit %u." + " Closing circuit. Please report this event," + " along with the following message.", + (unsigned)cell->circ_id); + if (CIRCUIT_IS_ORIGIN(circ)) { + circuit_log_path(LOG_WARN, LD_OR, TO_ORIGIN_CIRCUIT(circ)); + } else if (circ->n_chan) { + log_warn(LD_OR, " upstream=%s", + channel_get_actual_remote_descr(circ->n_chan)); + } + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + return; } else { or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); if (or_circ->remaining_relay_early_cells == 0) {