Loading changes/ticket40081 0 → 100644 +6 −0 Original line number Diff line number Diff line o Minor features (security): - Channels using obsolete versions of the Tor link protocol are no longer allowed to circumvent address-canonicity checks. (This is only a minor issue, since such channels have no way to set ed25519 keys, and therefore should always be rejected.) Closes ticket 40081. src/core/or/channel.c +7 −39 Original line number Diff line number Diff line Loading @@ -780,10 +780,9 @@ channel_check_for_duplicates(void) if (is_dirauth) total_dirauth_connections++; if (chan->is_canonical(chan, 0)) total_canonical++; if (chan->is_canonical(chan)) total_canonical++; if (!chan->is_canonical_to_peer && chan->is_canonical(chan, 0) && chan->is_canonical(chan, 1)) { if (!chan->is_canonical_to_peer && chan->is_canonical(chan)) { total_half_canonical++; } } Loading Loading @@ -2450,21 +2449,9 @@ channel_get_for_extend,(const char *rsa_id_digest, continue; } /* If the connection is using a recent link protocol, only return canonical * connections, when the address is one of the addresses we wanted. * * The channel_is_canonical_is_reliable() function asks the lower layer * if we should trust channel_is_canonical(). It only applies when * the lower-layer transport is channel_tls_t. * * For old link protocols, we can't rely on is_canonical getting * set properly if we're talking to the right address, since we might * have an out-of-date descriptor, and we will get no NETINFO cell to * tell us about the right address. */ if (!channel_is_canonical(chan) && channel_is_canonical_is_reliable(chan) && !matches_target) { /* Only return canonical connections or connections where the address * is the address we wanted. */ if (!channel_is_canonical(chan) && !matches_target) { ++n_noncanonical; continue; } Loading Loading @@ -2605,16 +2592,12 @@ channel_dump_statistics, (channel_t *chan, int severity)) /* Handle marks */ tor_log(severity, LD_GENERAL, " * Channel %"PRIu64 " has these marks: %s %s %s " "%s %s %s", " * Channel %"PRIu64 " has these marks: %s %s %s %s %s", (chan->global_identifier), channel_is_bad_for_new_circs(chan) ? "bad_for_new_circs" : "!bad_for_new_circs", channel_is_canonical(chan) ? "canonical" : "!canonical", channel_is_canonical_is_reliable(chan) ? "is_canonical_is_reliable" : "!is_canonical_is_reliable", channel_is_client(chan) ? "client" : "!client", channel_is_local(chan) ? Loading Loading @@ -2939,22 +2922,7 @@ channel_is_canonical(channel_t *chan) tor_assert(chan); tor_assert(chan->is_canonical); return chan->is_canonical(chan, 0); } /** * Test if the canonical flag is reliable. * * This function asks if the lower layer thinks it's safe to trust the * result of channel_is_canonical(). */ int channel_is_canonical_is_reliable(channel_t *chan) { tor_assert(chan); tor_assert(chan->is_canonical); return chan->is_canonical(chan, 1); return chan->is_canonical(chan); } /** Loading src/core/or/channel.h +3 −6 Original line number Diff line number Diff line Loading @@ -344,12 +344,10 @@ struct channel_t { /** Check if the lower layer has queued writes */ int (*has_queued_writes)(channel_t *); /** * If the second param is zero, ask the lower layer if this is * 'canonical', for a transport-specific definition of canonical; if * it is 1, ask if the answer to the preceding query is safe to rely * on. * Ask the lower layer if this is 'canonical', for a transport-specific * definition of canonical. */ int (*is_canonical)(channel_t *, int); int (*is_canonical)(channel_t *); /** Check if this channel matches a specified extend_info_t */ int (*matches_extend_info)(channel_t *, extend_info_t *); /** Check if this channel matches a target address when extending */ Loading Loading @@ -725,7 +723,6 @@ int channel_has_queued_writes(channel_t *chan); int channel_is_bad_for_new_circs(channel_t *chan); void channel_mark_bad_for_new_circs(channel_t *chan); int channel_is_canonical(channel_t *chan); int channel_is_canonical_is_reliable(channel_t *chan); int channel_is_client(const channel_t *chan); int channel_is_local(channel_t *chan); int channel_is_incoming(channel_t *chan); Loading src/core/or/channeltls.c +10 −22 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ static int channel_tls_get_transport_name_method(channel_t *chan, char **transport_out); static const char *channel_tls_describe_peer_method(const channel_t *chan); static int channel_tls_has_queued_writes_method(channel_t *chan); static int channel_tls_is_canonical_method(channel_t *chan, int req); static int channel_tls_is_canonical_method(channel_t *chan); static int channel_tls_matches_extend_info_method(channel_t *chan, extend_info_t *extend_info); Loading Loading @@ -627,12 +627,11 @@ channel_tls_has_queued_writes_method(channel_t *chan) /** * Tell the upper layer if we're canonical. * * This implements the is_canonical method for channel_tls_t; if req is zero, * it returns whether this is a canonical channel, and if it is one it returns * whether that can be relied upon. * This implements the is_canonical method for channel_tls_t: * it returns whether this is a canonical channel. */ static int channel_tls_is_canonical_method(channel_t *chan, int req) channel_tls_is_canonical_method(channel_t *chan) { int answer = 0; channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); Loading @@ -640,24 +639,13 @@ channel_tls_is_canonical_method(channel_t *chan, int req) tor_assert(tlschan); if (tlschan->conn) { switch (req) { case 0: /* If this bit is set to 0, and link_proto is sufficiently old, then we * can't actually _rely_ on this being a non-canonical channel. * Nonetheless, we're going to believe that this is a non-canonical * channel in this case, since nobody should be using these link protocols * any more. */ answer = tlschan->conn->is_canonical; break; case 1: /* * Is the is_canonical bit reliable? In protocols version 2 and up * we get the canonical address from a NETINFO cell, but in older * versions it might be based on an obsolete descriptor. */ answer = (tlschan->conn->link_proto >= 2); break; default: /* This shouldn't happen; channel.c is broken if it does */ tor_assert_nonfatal_unreached_once(); } } /* else return 0 for tlschan->conn == NULL */ return answer; } Loading src/core/or/circuitbuild.c +2 −0 Original line number Diff line number Diff line Loading @@ -731,6 +731,8 @@ circuit_deliver_create_cell,(circuit_t *circ, goto error; } tor_assert_nonfatal_once(circ->n_chan->is_canonical); memset(&cell, 0, sizeof(cell_t)); r = relayed ? create_cell_format_relayed(&cell, create_cell) : create_cell_format(&cell, create_cell); Loading Loading
changes/ticket40081 0 → 100644 +6 −0 Original line number Diff line number Diff line o Minor features (security): - Channels using obsolete versions of the Tor link protocol are no longer allowed to circumvent address-canonicity checks. (This is only a minor issue, since such channels have no way to set ed25519 keys, and therefore should always be rejected.) Closes ticket 40081.
src/core/or/channel.c +7 −39 Original line number Diff line number Diff line Loading @@ -780,10 +780,9 @@ channel_check_for_duplicates(void) if (is_dirauth) total_dirauth_connections++; if (chan->is_canonical(chan, 0)) total_canonical++; if (chan->is_canonical(chan)) total_canonical++; if (!chan->is_canonical_to_peer && chan->is_canonical(chan, 0) && chan->is_canonical(chan, 1)) { if (!chan->is_canonical_to_peer && chan->is_canonical(chan)) { total_half_canonical++; } } Loading Loading @@ -2450,21 +2449,9 @@ channel_get_for_extend,(const char *rsa_id_digest, continue; } /* If the connection is using a recent link protocol, only return canonical * connections, when the address is one of the addresses we wanted. * * The channel_is_canonical_is_reliable() function asks the lower layer * if we should trust channel_is_canonical(). It only applies when * the lower-layer transport is channel_tls_t. * * For old link protocols, we can't rely on is_canonical getting * set properly if we're talking to the right address, since we might * have an out-of-date descriptor, and we will get no NETINFO cell to * tell us about the right address. */ if (!channel_is_canonical(chan) && channel_is_canonical_is_reliable(chan) && !matches_target) { /* Only return canonical connections or connections where the address * is the address we wanted. */ if (!channel_is_canonical(chan) && !matches_target) { ++n_noncanonical; continue; } Loading Loading @@ -2605,16 +2592,12 @@ channel_dump_statistics, (channel_t *chan, int severity)) /* Handle marks */ tor_log(severity, LD_GENERAL, " * Channel %"PRIu64 " has these marks: %s %s %s " "%s %s %s", " * Channel %"PRIu64 " has these marks: %s %s %s %s %s", (chan->global_identifier), channel_is_bad_for_new_circs(chan) ? "bad_for_new_circs" : "!bad_for_new_circs", channel_is_canonical(chan) ? "canonical" : "!canonical", channel_is_canonical_is_reliable(chan) ? "is_canonical_is_reliable" : "!is_canonical_is_reliable", channel_is_client(chan) ? "client" : "!client", channel_is_local(chan) ? Loading Loading @@ -2939,22 +2922,7 @@ channel_is_canonical(channel_t *chan) tor_assert(chan); tor_assert(chan->is_canonical); return chan->is_canonical(chan, 0); } /** * Test if the canonical flag is reliable. * * This function asks if the lower layer thinks it's safe to trust the * result of channel_is_canonical(). */ int channel_is_canonical_is_reliable(channel_t *chan) { tor_assert(chan); tor_assert(chan->is_canonical); return chan->is_canonical(chan, 1); return chan->is_canonical(chan); } /** Loading
src/core/or/channel.h +3 −6 Original line number Diff line number Diff line Loading @@ -344,12 +344,10 @@ struct channel_t { /** Check if the lower layer has queued writes */ int (*has_queued_writes)(channel_t *); /** * If the second param is zero, ask the lower layer if this is * 'canonical', for a transport-specific definition of canonical; if * it is 1, ask if the answer to the preceding query is safe to rely * on. * Ask the lower layer if this is 'canonical', for a transport-specific * definition of canonical. */ int (*is_canonical)(channel_t *, int); int (*is_canonical)(channel_t *); /** Check if this channel matches a specified extend_info_t */ int (*matches_extend_info)(channel_t *, extend_info_t *); /** Check if this channel matches a target address when extending */ Loading Loading @@ -725,7 +723,6 @@ int channel_has_queued_writes(channel_t *chan); int channel_is_bad_for_new_circs(channel_t *chan); void channel_mark_bad_for_new_circs(channel_t *chan); int channel_is_canonical(channel_t *chan); int channel_is_canonical_is_reliable(channel_t *chan); int channel_is_client(const channel_t *chan); int channel_is_local(channel_t *chan); int channel_is_incoming(channel_t *chan); Loading
src/core/or/channeltls.c +10 −22 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ static int channel_tls_get_transport_name_method(channel_t *chan, char **transport_out); static const char *channel_tls_describe_peer_method(const channel_t *chan); static int channel_tls_has_queued_writes_method(channel_t *chan); static int channel_tls_is_canonical_method(channel_t *chan, int req); static int channel_tls_is_canonical_method(channel_t *chan); static int channel_tls_matches_extend_info_method(channel_t *chan, extend_info_t *extend_info); Loading Loading @@ -627,12 +627,11 @@ channel_tls_has_queued_writes_method(channel_t *chan) /** * Tell the upper layer if we're canonical. * * This implements the is_canonical method for channel_tls_t; if req is zero, * it returns whether this is a canonical channel, and if it is one it returns * whether that can be relied upon. * This implements the is_canonical method for channel_tls_t: * it returns whether this is a canonical channel. */ static int channel_tls_is_canonical_method(channel_t *chan, int req) channel_tls_is_canonical_method(channel_t *chan) { int answer = 0; channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); Loading @@ -640,24 +639,13 @@ channel_tls_is_canonical_method(channel_t *chan, int req) tor_assert(tlschan); if (tlschan->conn) { switch (req) { case 0: /* If this bit is set to 0, and link_proto is sufficiently old, then we * can't actually _rely_ on this being a non-canonical channel. * Nonetheless, we're going to believe that this is a non-canonical * channel in this case, since nobody should be using these link protocols * any more. */ answer = tlschan->conn->is_canonical; break; case 1: /* * Is the is_canonical bit reliable? In protocols version 2 and up * we get the canonical address from a NETINFO cell, but in older * versions it might be based on an obsolete descriptor. */ answer = (tlschan->conn->link_proto >= 2); break; default: /* This shouldn't happen; channel.c is broken if it does */ tor_assert_nonfatal_unreached_once(); } } /* else return 0 for tlschan->conn == NULL */ return answer; } Loading
src/core/or/circuitbuild.c +2 −0 Original line number Diff line number Diff line Loading @@ -731,6 +731,8 @@ circuit_deliver_create_cell,(circuit_t *circ, goto error; } tor_assert_nonfatal_once(circ->n_chan->is_canonical); memset(&cell, 0, sizeof(cell_t)); r = relayed ? create_cell_format_relayed(&cell, create_cell) : create_cell_format(&cell, create_cell); Loading