diff --git a/src/or/hs_circuit.c b/src/or/hs_circuit.c index 6d1cdd4eb0..7704fd0bad 100644 --- a/src/or/hs_circuit.c +++ b/src/or/hs_circuit.c @@ -341,125 +341,6 @@ send_establish_intro(const hs_service_t *service, memwipe(payload, 0, sizeof(payload)); } -/* From a list of link specifier, an onion key and if we are requesting a - * direct connection (ex: single onion service), return a newly allocated - * extend_info_t object. This function checks the firewall policies and if we - * are allowed to extend to the chosen address. - * - * if either IPv4 or legacy ID is missing, error. - * if not direct_conn, IPv4 is prefered. - * if direct_conn, IPv6 is prefered if we have one available. - * if firewall does not allow the chosen address, error. - * - * Return NULL if we can't fulfill the conditions. */ -static extend_info_t * -get_rp_extend_info(const smartlist_t *link_specifiers, - const curve25519_public_key_t *onion_key, int direct_conn) -{ - int have_v4 = 0, have_v6 = 0, have_legacy_id = 0, have_ed25519_id = 0; - char legacy_id[DIGEST_LEN] = {0}; - uint16_t port_v4 = 0, port_v6 = 0, port = 0; - tor_addr_t addr_v4, addr_v6, *addr = NULL; - ed25519_public_key_t ed25519_pk; - extend_info_t *info = NULL; - - tor_assert(link_specifiers); - tor_assert(onion_key); - - SMARTLIST_FOREACH_BEGIN(link_specifiers, const link_specifier_t *, ls) { - switch (link_specifier_get_ls_type(ls)) { - case LS_IPV4: - /* Skip if we already seen a v4. */ - if (have_v4) continue; - tor_addr_from_ipv4h(&addr_v4, - link_specifier_get_un_ipv4_addr(ls)); - port_v4 = link_specifier_get_un_ipv4_port(ls); - have_v4 = 1; - break; - case LS_IPV6: - /* Skip if we already seen a v6. */ - if (have_v6) continue; - tor_addr_from_ipv6_bytes(&addr_v6, - (const char *) link_specifier_getconstarray_un_ipv6_addr(ls)); - port_v6 = link_specifier_get_un_ipv6_port(ls); - have_v6 = 1; - break; - case LS_LEGACY_ID: - /* Make sure we do have enough bytes for the legacy ID. */ - if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) { - break; - } - memcpy(legacy_id, link_specifier_getconstarray_un_legacy_id(ls), - sizeof(legacy_id)); - have_legacy_id = 1; - break; - case LS_ED25519_ID: - memcpy(ed25519_pk.pubkey, - link_specifier_getconstarray_un_ed25519_id(ls), - ED25519_PUBKEY_LEN); - have_ed25519_id = 1; - break; - default: - /* Ignore unknown. */ - break; - } - } SMARTLIST_FOREACH_END(ls); - - /* IPv4, legacy ID are mandatory for rend points. - * ed25519 keys and ipv6 are optional for rend points */ - if (!have_v4 || !have_legacy_id) { - goto done; - } - /* By default, we pick IPv4 but this might change to v6 if certain - * conditions are met. */ - addr = &addr_v4; port = port_v4; - - /* If we are NOT in a direct connection, we'll use our Guard and a 3-hop - * circuit so we can't extend in IPv6. And at this point, we do have an IPv4 - * address available so go to validation. */ - if (!direct_conn) { - goto validate; - } - - /* From this point on, we have a request for a direct connection to the - * rendezvous point so make sure we can actually connect through our - * firewall. We'll prefer IPv6. */ - - /* IPv6 test. */ - if (have_v6 && - fascist_firewall_allows_address_addr(&addr_v6, port_v6, - FIREWALL_OR_CONNECTION, 1, 1)) { - /* Direct connection and we can reach it in IPv6 so go for it. */ - addr = &addr_v6; port = port_v6; - goto validate; - } - /* IPv4 test and we are sure we have a v4 because of the check above. */ - if (fascist_firewall_allows_address_addr(&addr_v4, port_v4, - FIREWALL_OR_CONNECTION, 0, 0)) { - /* Direct connection and we can reach it in IPv4 so go for it. */ - addr = &addr_v4; port = port_v4; - goto validate; - } - - validate: - /* We'll validate now that the address we've picked isn't a private one. If - * it is, are we allowing to extend to private address? */ - if (!extend_info_addr_is_allowed(addr)) { - log_warn(LD_REND, "Rendezvous point address is private and it is not " - "allowed to extend to it: %s:%u", - fmt_addr(&addr_v4), port_v4); - goto done; - } - - /* We do have everything for which we think we can connect successfully. */ - info = extend_info_new(NULL, legacy_id, - have_ed25519_id ? &ed25519_pk : NULL, - NULL, onion_key, - addr, port); - done: - return info; -} - /* For a given service, the ntor onion key and a rendezvous cookie, launch a * circuit to the rendezvous point specified by the link specifiers. On * success, a circuit identifier is attached to the circuit with the needed @@ -483,8 +364,9 @@ launch_rendezvous_point_circuit(const hs_service_t *service, /* Get the extend info data structure for the chosen rendezvous point * specified by the given link specifiers. */ - info = get_rp_extend_info(data->link_specifiers, &data->onion_pk, - service->config.is_single_onion); + info = hs_get_extend_info_from_lspecs(data->link_specifiers, + &data->onion_pk, + service->config.is_single_onion); if (info == NULL) { /* We are done here, we can't extend to the rendezvous point. */ goto end; diff --git a/src/or/hs_common.c b/src/or/hs_common.c index e0c7dca4bc..03dd07f6ca 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -14,12 +14,14 @@ #include "or.h" #include "config.h" +#include "circuitbuild.h" #include "networkstatus.h" #include "nodelist.h" #include "hs_cache.h" #include "hs_common.h" #include "hs_ident.h" #include "hs_service.h" +#include "policies.h" #include "rendcommon.h" #include "rendservice.h" #include "routerset.h" @@ -28,6 +30,9 @@ #include "shared_random.h" #include "shared_random_state.h" +/* Trunnel */ +#include "ed25519_cert.h" + /* Ed25519 Basepoint value. Taken from section 5 of * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */ static const char *str_ed25519_basepoint = @@ -1559,6 +1564,123 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) return hs_dir; } +/* From a list of link specifier, an onion key and if we are requesting a + * direct connection (ex: single onion service), return a newly allocated + * extend_info_t object. This function checks the firewall policies and if we + * are allowed to extend to the chosen address. + * + * if either IPv4 or legacy ID is missing, error. + * if not direct_conn, IPv4 is prefered. + * if direct_conn, IPv6 is prefered if we have one available. + * if firewall does not allow the chosen address, error. + * + * Return NULL if we can fulfill the conditions. */ +extend_info_t * +hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, + const curve25519_public_key_t *onion_key, + int direct_conn) +{ + int have_v4 = 0, have_v6 = 0, have_legacy_id = 0, have_ed25519_id = 0; + char legacy_id[DIGEST_LEN] = {0}; + uint16_t port_v4 = 0, port_v6 = 0, port = 0; + tor_addr_t addr_v4, addr_v6, *addr = NULL; + ed25519_public_key_t ed25519_pk; + extend_info_t *info = NULL; + + tor_assert(lspecs); + + SMARTLIST_FOREACH_BEGIN(lspecs, const link_specifier_t *, ls) { + switch (link_specifier_get_ls_type(ls)) { + case LS_IPV4: + /* Skip if we already seen a v4. */ + if (have_v4) continue; + tor_addr_from_ipv4h(&addr_v4, + link_specifier_get_un_ipv4_addr(ls)); + port_v4 = link_specifier_get_un_ipv4_port(ls); + have_v4 = 1; + break; + case LS_IPV6: + /* Skip if we already seen a v6. */ + if (have_v6) continue; + tor_addr_from_ipv6_bytes(&addr_v6, + (const char *) link_specifier_getconstarray_un_ipv6_addr(ls)); + port_v6 = link_specifier_get_un_ipv6_port(ls); + have_v6 = 1; + break; + case LS_LEGACY_ID: + /* Make sure we do have enough bytes for the legacy ID. */ + if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) { + break; + } + memcpy(legacy_id, link_specifier_getconstarray_un_legacy_id(ls), + sizeof(legacy_id)); + have_legacy_id = 1; + break; + case LS_ED25519_ID: + memcpy(ed25519_pk.pubkey, + link_specifier_getconstarray_un_ed25519_id(ls), + ED25519_PUBKEY_LEN); + have_ed25519_id = 1; + break; + default: + /* Ignore unknown. */ + break; + } + } SMARTLIST_FOREACH_END(ls); + + /* IPv4 and legacy ID are mandatory. */ + if (!have_v4 || !have_legacy_id) { + goto done; + } + /* By default, we pick IPv4 but this might change to v6 if certain + * conditions are met. */ + addr = &addr_v4; port = port_v4; + + /* If we are NOT in a direct connection, we'll use our Guard and a 3-hop + * circuit so we can't extend in IPv6. And at this point, we do have an IPv4 + * address available so go to validation. */ + if (!direct_conn) { + goto validate; + } + + /* From this point on, we have a request for a direct connection to the + * rendezvous point so make sure we can actually connect through our + * firewall. We'll prefer IPv6. */ + + /* IPv6 test. */ + if (have_v6 && + fascist_firewall_allows_address_addr(&addr_v6, port_v6, + FIREWALL_OR_CONNECTION, 1, 1)) { + /* Direct connection and we can reach it in IPv6 so go for it. */ + addr = &addr_v6; port = port_v6; + goto validate; + } + /* IPv4 test and we are sure we have a v4 because of the check above. */ + if (fascist_firewall_allows_address_addr(&addr_v4, port_v4, + FIREWALL_OR_CONNECTION, 0, 0)) { + /* Direct connection and we can reach it in IPv4 so go for it. */ + addr = &addr_v4; port = port_v4; + goto validate; + } + + validate: + /* We'll validate now that the address we've picked isn't a private one. If + * it is, are we allowing to extend to private address? */ + if (!extend_info_addr_is_allowed(addr)) { + log_warn(LD_REND, "Requested address is private and it is not " + "allowed to extend to it: %s:%u", + fmt_addr(&addr_v4), port_v4); + goto done; + } + + /* We do have everything for which we think we can connect successfully. */ + info = extend_info_new(NULL, legacy_id, + (have_ed25519_id) ? &ed25519_pk : NULL, NULL, + onion_key, addr, port); + done: + return info; +} + /***********************************************************************/ /* Initialize the entire HS subsytem. This is called in tor_init() before any diff --git a/src/or/hs_common.h b/src/or/hs_common.h index 6ad68d0a8a..79d92d915f 100644 --- a/src/or/hs_common.h +++ b/src/or/hs_common.h @@ -237,6 +237,10 @@ int hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn); void hs_inc_rdv_stream_counter(origin_circuit_t *circ); void hs_dec_rdv_stream_counter(origin_circuit_t *circ); +extend_info_t *hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, + const curve25519_public_key_t *onion_key, + int direct_conn); + #ifdef HS_COMMON_PRIVATE STATIC void get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out);