diff options
author | Nick Mathewson <nickm@torproject.org> | 2020-04-29 19:16:40 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2020-04-29 19:16:40 -0400 |
commit | 49800cf5390bc1445a5fab9bbf346ca73c6b3a58 (patch) | |
tree | 6b7624d7367e8629320f949d2f3abb3eedb316a1 /src/core | |
parent | cbe9e56590b0ea354313667bf20e187dd5b1d556 (diff) | |
parent | ed4420b4b8b891bd29587a27cb51e9184ff3e093 (diff) | |
download | tor-49800cf5390bc1445a5fab9bbf346ca73c6b3a58.tar.gz tor-49800cf5390bc1445a5fab9bbf346ca73c6b3a58.zip |
Merge remote-tracking branch 'tor-github/pr/1864/head'
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/or/channel.c | 60 | ||||
-rw-r--r-- | src/core/or/channel.h | 5 | ||||
-rw-r--r-- | src/core/or/channeltls.c | 2 | ||||
-rw-r--r-- | src/core/or/circuitbuild.c | 16 | ||||
-rw-r--r-- | src/core/or/connection_edge.c | 2 | ||||
-rw-r--r-- | src/core/or/onion.c | 43 | ||||
-rw-r--r-- | src/core/or/policies.c | 4 | ||||
-rw-r--r-- | src/core/or/relay.c | 8 | ||||
-rw-r--r-- | src/core/proto/proto_socks.c | 5 |
9 files changed, 100 insertions, 45 deletions
diff --git a/src/core/or/channel.c b/src/core/or/channel.c index 75054aa0c4..a05554472f 100644 --- a/src/core/or/channel.c +++ b/src/core/or/channel.c @@ -83,6 +83,13 @@ #include "core/or/cell_queue_st.h" +/* Static function prototypes */ + +static bool channel_matches_target_addr_for_extend( + channel_t *chan, + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr); + /* Global lists of channels */ /* All channel_t instances */ @@ -2360,9 +2367,9 @@ channel_is_better(channel_t *a, channel_t *b) * Get a channel to extend a circuit. * * Given the desired relay identity, pick a suitable channel to extend a - * circuit to the target address requsted by the client. Search for an - * existing channel for the requested endpoint. Make sure the channel is - * usable for new circuits, and matches the target address. + * circuit to the target IPv4 or IPv6 address requsted by the client. Search + * for an existing channel for the requested endpoint. Make sure the channel + * is usable for new circuits, and matches one of the target addresses. * * Try to return the best channel. But if there is no good channel, set * *msg_out to a message describing the channel's state and our next action, @@ -2372,7 +2379,8 @@ channel_is_better(channel_t *a, channel_t *b) MOCK_IMPL(channel_t *, channel_get_for_extend,(const char *rsa_id_digest, const ed25519_public_key_t *ed_id, - const tor_addr_t *target_addr, + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr, const char **msg_out, int *launch_out)) { @@ -2404,11 +2412,15 @@ channel_get_for_extend,(const char *rsa_id_digest, continue; } + const bool matches_target = + channel_matches_target_addr_for_extend(chan, + target_ipv4_addr, + target_ipv6_addr); /* Never return a non-open connection. */ if (!CHANNEL_IS_OPEN(chan)) { /* If the address matches, don't launch a new connection for this * circuit. */ - if (channel_matches_target_addr_for_extend(chan, target_addr)) + if (matches_target) ++n_inprogress_goodaddr; continue; } @@ -2419,22 +2431,21 @@ channel_get_for_extend,(const char *rsa_id_digest, continue; } - /* Never return a non-canonical connection using a recent link protocol - * if the address is not what we wanted. + /* 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(). The below is from the - * comments of the old circuit_or_get_for_extend() and applies when + * 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 + * 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.) + * tell us about the right address. */ if (!channel_is_canonical(chan) && channel_is_canonical_is_reliable(chan) && - !channel_matches_target_addr_for_extend(chan, target_addr)) { + !matches_target) { ++n_noncanonical; continue; } @@ -3297,20 +3308,33 @@ channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info) } /** - * Check if a channel matches a given target address; return true iff we do. + * Check if a channel matches the given target IPv4 or IPv6 addresses. + * If either address matches, return true. If neither address matches, + * return false. + * + * Both addresses can't be NULL. * * This function calls into the lower layer and asks if this channel thinks - * it matches a given target address for circuit extension purposes. + * it matches the target addresses for circuit extension purposes. */ -int +static bool channel_matches_target_addr_for_extend(channel_t *chan, - const tor_addr_t *target) + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr) { tor_assert(chan); tor_assert(chan->matches_target); - tor_assert(target); - return chan->matches_target(chan, target); + IF_BUG_ONCE(!target_ipv4_addr && !target_ipv6_addr) + return false; + + if (target_ipv4_addr && chan->matches_target(chan, target_ipv4_addr)) + return true; + + if (target_ipv6_addr && chan->matches_target(chan, target_ipv6_addr)) + return true; + + return false; } /** diff --git a/src/core/or/channel.h b/src/core/or/channel.h index 49331d5d58..4968c8714a 100644 --- a/src/core/or/channel.h +++ b/src/core/or/channel.h @@ -661,7 +661,8 @@ channel_t * channel_connect(const tor_addr_t *addr, uint16_t port, MOCK_DECL(channel_t *, channel_get_for_extend,( const char *rsa_id_digest, const struct ed25519_public_key_t *ed_id, - const tor_addr_t *target_addr, + const tor_addr_t *target_ipv4_addr, + const tor_addr_t *target_ipv6_addr, const char **msg_out, int *launch_out)); @@ -737,8 +738,6 @@ int channel_is_outgoing(channel_t *chan); void channel_mark_client(channel_t *chan); void channel_clear_client(channel_t *chan); int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info); -int channel_matches_target_addr_for_extend(channel_t *chan, - const tor_addr_t *target); unsigned int channel_num_circuits(channel_t *chan); MOCK_DECL(void,channel_set_circid_type,(channel_t *chan, crypto_pk_t *identity_rcvd, diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c index b424d02a59..be941c1762 100644 --- a/src/core/or/channeltls.c +++ b/src/core/or/channeltls.c @@ -1669,7 +1669,7 @@ tor_addr_from_netinfo_addr(tor_addr_t *tor_addr, } else if (type == NETINFO_ADDR_TYPE_IPV6 && len == 16) { const uint8_t *ipv6_bytes = netinfo_addr_getconstarray_addr_ipv6( netinfo_addr); - tor_addr_from_ipv6_bytes(tor_addr, (const char *)ipv6_bytes); + tor_addr_from_ipv6_bytes(tor_addr, ipv6_bytes); } else { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Cannot read address from NETINFO " "- wrong type/length."); diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index ce0f9618fe..0381a4dc35 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -559,11 +559,17 @@ circuit_handle_first_hop(origin_circuit_t *circ) fmt_addrport(&firsthop->extend_info->addr, firsthop->extend_info->port)); - n_chan = channel_get_for_extend(firsthop->extend_info->identity_digest, - &firsthop->extend_info->ed_identity, - &firsthop->extend_info->addr, - &msg, - &should_launch); + /* We'll cleanup this code in #33220, when we add an IPv6 address to + * extend_info_t. */ + const bool addr_is_ipv4 = + (tor_addr_family(&firsthop->extend_info->addr) == AF_INET); + n_chan = channel_get_for_extend( + firsthop->extend_info->identity_digest, + &firsthop->extend_info->ed_identity, + addr_is_ipv4 ? &firsthop->extend_info->addr : NULL, + addr_is_ipv4 ? NULL : &firsthop->extend_info->addr, + &msg, + &should_launch); if (!n_chan) { /* not currently connected in a useful way. */ diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index 23c6e230cb..803bd82fc8 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -3531,7 +3531,7 @@ connection_ap_handshake_socks_resolved,(entry_connection_t *conn, } } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) { tor_addr_t a; - tor_addr_from_ipv6_bytes(&a, (char*)answer); + tor_addr_from_ipv6_bytes(&a, answer); if (! tor_addr_is_null(&a)) { client_dns_set_addressmap(conn, conn->socks_request->address, &a, diff --git a/src/core/or/onion.c b/src/core/or/onion.c index 45144b5e6c..7b8f3c61fc 100644 --- a/src/core/or/onion.c +++ b/src/core/or/onion.c @@ -240,11 +240,21 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in) static int check_extend_cell(const extend_cell_t *cell) { + const bool is_extend2 = (cell->cell_type == RELAY_COMMAND_EXTEND2); + if (tor_digest_is_zero((const char*)cell->node_id)) return -1; - /* We don't currently allow EXTEND2 cells without an IPv4 address */ - if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC) - return -1; + if (!tor_addr_port_is_valid_ap(&cell->orport_ipv4, 0)) { + /* EXTEND cells must have an IPv4 address. */ + if (!is_extend2) { + return -1; + } + /* EXTEND2 cells must have at least one IP address. + * It can be IPv4 or IPv6. */ + if (!tor_addr_port_is_valid_ap(&cell->orport_ipv6, 0)) { + return -1; + } + } if (cell->create_cell.cell_type == CELL_CREATE) { if (cell->cell_type != RELAY_COMMAND_EXTEND) return -1; @@ -343,7 +353,7 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out, continue; found_ipv6 = 1; tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr, - (const char *)ls->un_ipv6_addr); + ls->un_ipv6_addr); cell_out->orport_ipv6.port = ls->un_ipv6_port; break; case LS_LEGACY_ID: @@ -364,7 +374,12 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out, } } - if (!found_rsa_id || !found_ipv4) /* These are mandatory */ + /* EXTEND2 cells must have an RSA ID */ + if (!found_rsa_id) + return -1; + + /* EXTEND2 cells must have at least one IP address */ + if (!found_ipv4 && !found_ipv6) return -1; return create_cell_from_create2_cell_body(&cell_out->create_cell, @@ -620,12 +635,13 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out, break; case RELAY_COMMAND_EXTEND2: { - uint8_t n_specifiers = 2; + uint8_t n_specifiers = 1; *command_out = RELAY_COMMAND_EXTEND2; extend2_cell_body_t *cell = extend2_cell_body_new(); link_specifier_t *ls; - { - /* IPv4 specifier first. */ + if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) { + /* Maybe IPv4 specifier first. */ + ++n_specifiers; ls = link_specifier_new(); extend2_cell_body_add_ls(cell, ls); ls->ls_type = LS_IPV4; @@ -651,6 +667,17 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out, ls->ls_len = 32; memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32); } + if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv6, 0)) { + /* Then maybe IPv6 specifier. */ + ++n_specifiers; + ls = link_specifier_new(); + extend2_cell_body_add_ls(cell, ls); + ls->ls_type = LS_IPV6; + ls->ls_len = 18; + tor_addr_copy_ipv6_bytes(ls->un_ipv6_addr, + &cell_in->orport_ipv6.addr); + ls->un_ipv6_port = cell_in->orport_ipv6.port; + } cell->n_spec = n_specifiers; /* Now, the handshake */ diff --git a/src/core/or/policies.c b/src/core/or/policies.c index dd4feaadfc..ea803f393d 100644 --- a/src/core/or/policies.c +++ b/src/core/or/policies.c @@ -167,7 +167,7 @@ policy_expand_unspec(smartlist_t **policy) } tor_addr_from_ipv4h(&newpolicy_ipv4.addr, 0); tor_addr_from_ipv6_bytes(&newpolicy_ipv6.addr, - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); + (const uint8_t *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv4)); smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy_ipv6)); addr_policy_free(p); @@ -1005,7 +1005,7 @@ fascist_firewall_choose_address_ls(const smartlist_t *lspecs, * direct connection. */ if (have_v6) continue; tor_addr_from_ipv6_bytes(&addr_v6, - (const char *) link_specifier_getconstarray_un_ipv6_addr(ls)); + link_specifier_getconstarray_un_ipv6_addr(ls)); port_v6 = link_specifier_get_un_ipv6_port(ls); have_v6 = 1; break; diff --git a/src/core/or/relay.c b/src/core/or/relay.c index 00bbf77b99..b831af0ac3 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -867,7 +867,7 @@ connection_ap_process_end_not_open( ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5)); } else if (rh->length == 17 || rh->length == 21) { tor_addr_from_ipv6_bytes(&addr, - (char*)(cell->payload+RELAY_HEADER_SIZE+1)); + (cell->payload+RELAY_HEADER_SIZE+1)); if (rh->length == 21) ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17)); } @@ -1092,7 +1092,7 @@ connected_cell_parse(const relay_header_t *rh, const cell_t *cell, return -1; if (get_uint8(payload + 4) != 6) return -1; - tor_addr_from_ipv6_bytes(addr_out, (char*)(payload + 5)); + tor_addr_from_ipv6_bytes(addr_out, (payload + 5)); bytes = ntohl(get_uint32(payload + 21)); if (bytes <= INT32_MAX) *ttl_out = (int) bytes; @@ -1165,7 +1165,7 @@ resolved_cell_parse(const cell_t *cell, const relay_header_t *rh, if (answer_len != 16) goto err; addr = tor_malloc_zero(sizeof(*addr)); - tor_addr_from_ipv6_bytes(&addr->addr, (const char*) cp); + tor_addr_from_ipv6_bytes(&addr->addr, cp); cp += 16; addr->ttl = ntohl(get_uint32(cp)); cp += 4; @@ -3217,7 +3217,7 @@ decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload, case RESOLVED_TYPE_IPV6: if (payload[1] != 16) return NULL; - tor_addr_from_ipv6_bytes(addr_out, (char*)(payload+2)); + tor_addr_from_ipv6_bytes(addr_out, (payload+2)); break; default: tor_addr_make_unspec(addr_out); diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c index 6fd08b2273..c7d2af3d97 100644 --- a/src/core/proto/proto_socks.c +++ b/src/core/proto/proto_socks.c @@ -587,9 +587,8 @@ parse_socks5_client_request(const uint8_t *raw_data, socks_request_t *req, strlcpy(req->address, hostname, sizeof(req->address)); } break; case 4: { - const char *ipv6 = - (const char *)socks5_client_request_getarray_dest_addr_ipv6( - trunnel_req); + const uint8_t *ipv6 = + socks5_client_request_getarray_dest_addr_ipv6(trunnel_req); tor_addr_from_ipv6_bytes(&destaddr, ipv6); tor_addr_to_str(req->address, &destaddr, sizeof(req->address), 1); |