hs: Move get_lspecs_from_node to nodelist.c

Also:
* rename to node_get_link_specifier_smartlist
* rewrite to return a smartlist
* add link_specifier_smartlist_free

Part of 23576.
This commit is contained in:
teor 2019-01-30 15:15:41 +01:00
parent d9010c5b67
commit cdda3dc484
3 changed files with 105 additions and 82 deletions

View file

@ -565,81 +565,6 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
return;
}
/* Add all possible link specifiers in node to lspecs:
* - legacy ID is mandatory thus MUST be present in node;
* - include ed25519 link specifier if present in the node, and the node
* supports ed25519 link authentication, even if its link versions are not
* compatible with us;
* - include IPv4 link specifier, if the primary address is not IPv4, log a
* BUG() warning, and return an empty smartlist;
* - include IPv6 link specifier if present in the node. */
static void
get_lspecs_from_node(const node_t *node, smartlist_t *lspecs)
{
link_specifier_t *ls;
tor_addr_port_t ap;
tor_assert(node);
tor_assert(lspecs);
/* Get the relay's IPv4 address. */
node_get_prim_orport(node, &ap);
/* We expect the node's primary address to be a valid IPv4 address.
* This conforms to the protocol, which requires either an IPv4 or IPv6
* address (or both). */
if (BUG(!tor_addr_is_v4(&ap.addr)) ||
BUG(!tor_addr_port_is_valid_ap(&ap, 0))) {
return;
}
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_IPV4);
link_specifier_set_un_ipv4_addr(ls, tor_addr_to_ipv4h(&ap.addr));
link_specifier_set_un_ipv4_port(ls, ap.port);
/* Four bytes IPv4 and two bytes port. */
link_specifier_set_ls_len(ls, sizeof(ap.addr.addr.in_addr) +
sizeof(ap.port));
smartlist_add(lspecs, ls);
/* Legacy ID is mandatory and will always be present in node. */
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_LEGACY_ID);
memcpy(link_specifier_getarray_un_legacy_id(ls), node->identity,
link_specifier_getlen_un_legacy_id(ls));
link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
smartlist_add(lspecs, ls);
/* ed25519 ID is only included if the node has it, and the node declares a
protocol version that supports ed25519 link authentication, even if that
link version is not compatible with us. (We are sending the ed25519 key
to another tor, which may support different link versions.) */
if (!ed25519_public_key_is_zero(&node->ed25519_id) &&
node_supports_ed25519_link_authentication(node, 0)) {
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_ED25519_ID);
memcpy(link_specifier_getarray_un_ed25519_id(ls), &node->ed25519_id,
link_specifier_getlen_un_ed25519_id(ls));
link_specifier_set_ls_len(ls, link_specifier_getlen_un_ed25519_id(ls));
smartlist_add(lspecs, ls);
}
/* Check for IPv6. If so, include it as well. */
if (node_has_ipv6_orport(node)) {
ls = link_specifier_new();
node_get_pref_ipv6_orport(node, &ap);
link_specifier_set_ls_type(ls, LS_IPV6);
size_t addr_len = link_specifier_getlen_un_ipv6_addr(ls);
const uint8_t *in6_addr = tor_addr_to_in6_addr8(&ap.addr);
uint8_t *ipv6_array = link_specifier_getarray_un_ipv6_addr(ls);
memcpy(ipv6_array, in6_addr, addr_len);
link_specifier_set_un_ipv6_port(ls, ap.port);
/* Sixteen bytes IPv6 and two bytes port. */
link_specifier_set_ls_len(ls, addr_len + sizeof(ap.port));
smartlist_add(lspecs, ls);
}
}
/* Using the given descriptor intro point ip, the node of the
* rendezvous point rp_node and the service's subcredential, populate the
* already allocated intro1_data object with the needed key material and link
@ -662,10 +587,9 @@ setup_introduce1_data(const hs_desc_intro_point_t *ip,
tor_assert(subcredential);
tor_assert(intro1_data);
/* Build the link specifiers from the extend information of the rendezvous
* circuit that we've picked previously. */
rp_lspecs = smartlist_new();
get_lspecs_from_node(rp_node, rp_lspecs);
/* Build the link specifiers from the node at the end of the rendezvous
* circuit that we opened for this introduction. */
rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
if (smartlist_len(rp_lspecs) == 0) {
/* We can't rendezvous without link specifiers. */
smartlist_free(rp_lspecs);
@ -1044,9 +968,7 @@ hs_circ_handle_introduce2(const hs_service_t *service,
ret = 0;
done:
SMARTLIST_FOREACH(data.link_specifiers, link_specifier_t *, lspec,
link_specifier_free(lspec));
smartlist_free(data.link_specifiers);
link_specifier_smartlist_free(data.link_specifiers);
memwipe(&data, 0, sizeof(data));
return ret;
}

View file

@ -1189,6 +1189,102 @@ node_get_rsa_id_digest(const node_t *node)
return (const uint8_t*)node->identity;
}
/* Returns a new smartlist with all possible link specifiers from node:
* - legacy ID is mandatory thus MUST be present in node;
* - include ed25519 link specifier if present in the node, and the node
* supports ed25519 link authentication, and:
* - if direct_conn is true, its link versions are compatible with us,
* - if direct_conn is false, regardless of its link versions;
* - include IPv4 link specifier, if the primary address is not IPv4, log a
* BUG() warning, and return an empty smartlist;
* - include IPv6 link specifier if present in the node.
*
* If node is NULL, returns an empty smartlist.
*
* The smartlist must be freed using link_specifier_smartlist_free(). */
smartlist_t *
node_get_link_specifier_smartlist(const node_t *node, bool direct_conn)
{
link_specifier_t *ls;
tor_addr_port_t ap;
smartlist_t *lspecs = smartlist_new();
if (!node)
return lspecs;
/* Get the relay's IPv4 address. */
node_get_prim_orport(node, &ap);
/* We expect the node's primary address to be a valid IPv4 address.
* This conforms to the protocol, which requires either an IPv4 or IPv6
* address (or both). */
if (BUG(!tor_addr_is_v4(&ap.addr)) ||
BUG(!tor_addr_port_is_valid_ap(&ap, 0))) {
return lspecs;
}
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_IPV4);
link_specifier_set_un_ipv4_addr(ls, tor_addr_to_ipv4h(&ap.addr));
link_specifier_set_un_ipv4_port(ls, ap.port);
/* Four bytes IPv4 and two bytes port. */
link_specifier_set_ls_len(ls, sizeof(ap.addr.addr.in_addr) +
sizeof(ap.port));
smartlist_add(lspecs, ls);
/* Legacy ID is mandatory and will always be present in node. */
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_LEGACY_ID);
memcpy(link_specifier_getarray_un_legacy_id(ls), node->identity,
link_specifier_getlen_un_legacy_id(ls));
link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
smartlist_add(lspecs, ls);
/* ed25519 ID is only included if the node has it, and the node declares a
protocol version that supports ed25519 link authentication.
If direct_conn is true, we also require that the node's link version is
compatible with us. (Otherwise, we will be sending the ed25519 key
to another tor, which may support different link versions.) */
if (!ed25519_public_key_is_zero(&node->ed25519_id) &&
node_supports_ed25519_link_authentication(node, direct_conn)) {
ls = link_specifier_new();
link_specifier_set_ls_type(ls, LS_ED25519_ID);
memcpy(link_specifier_getarray_un_ed25519_id(ls), &node->ed25519_id,
link_specifier_getlen_un_ed25519_id(ls));
link_specifier_set_ls_len(ls, link_specifier_getlen_un_ed25519_id(ls));
smartlist_add(lspecs, ls);
}
/* Check for IPv6. If so, include it as well. */
if (node_has_ipv6_orport(node)) {
ls = link_specifier_new();
node_get_pref_ipv6_orport(node, &ap);
link_specifier_set_ls_type(ls, LS_IPV6);
size_t addr_len = link_specifier_getlen_un_ipv6_addr(ls);
const uint8_t *in6_addr = tor_addr_to_in6_addr8(&ap.addr);
uint8_t *ipv6_array = link_specifier_getarray_un_ipv6_addr(ls);
memcpy(ipv6_array, in6_addr, addr_len);
link_specifier_set_un_ipv6_port(ls, ap.port);
/* Sixteen bytes IPv6 and two bytes port. */
link_specifier_set_ls_len(ls, addr_len + sizeof(ap.port));
smartlist_add(lspecs, ls);
}
return lspecs;
}
/* Free a link specifier list. */
void
link_specifier_smartlist_free_(smartlist_t *ls_list)
{
if (!ls_list)
return;
SMARTLIST_FOREACH(ls_list, link_specifier_t *, lspec,
link_specifier_free(lspec));
smartlist_free(ls_list);
}
/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
const char *
node_get_nickname(const node_t *node)

View file

@ -77,6 +77,11 @@ int node_supports_v3_hsdir(const node_t *node);
int node_supports_ed25519_hs_intro(const node_t *node);
int node_supports_v3_rendezvous_point(const node_t *node);
const uint8_t *node_get_rsa_id_digest(const node_t *node);
smartlist_t *node_get_link_specifier_smartlist(const node_t *node,
bool direct_conn);
void link_specifier_smartlist_free_(smartlist_t *ls_list);
#define link_specifier_smartlist_free(ls_list) \
FREE_AND_NULL(smartlist_t, link_specifier_smartlist_free_, (ls_list))
int node_has_ipv6_addr(const node_t *node);
int node_has_ipv6_orport(const node_t *node);