summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2020-04-29 19:16:40 -0400
committerNick Mathewson <nickm@torproject.org>2020-04-29 19:16:40 -0400
commit49800cf5390bc1445a5fab9bbf346ca73c6b3a58 (patch)
tree6b7624d7367e8629320f949d2f3abb3eedb316a1 /src/core
parentcbe9e56590b0ea354313667bf20e187dd5b1d556 (diff)
parented4420b4b8b891bd29587a27cb51e9184ff3e093 (diff)
downloadtor-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.c60
-rw-r--r--src/core/or/channel.h5
-rw-r--r--src/core/or/channeltls.c2
-rw-r--r--src/core/or/circuitbuild.c16
-rw-r--r--src/core/or/connection_edge.c2
-rw-r--r--src/core/or/onion.c43
-rw-r--r--src/core/or/policies.c4
-rw-r--r--src/core/or/relay.c8
-rw-r--r--src/core/proto/proto_socks.c5
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);