mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
prop224: Make lspecs to extend info public
The hs circuit file had this function that takes a list of link specifiers and return a newly allocated extend info object. Make it public so the client side can also use it to be able to extend to introduction point. Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
8e2854372d
commit
8a552bf49b
@ -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,7 +364,8 @@ 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,
|
||||
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. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user