mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 15:10:48 +01:00
Merge branch 'maint-0.3.2'
This commit is contained in:
commit
a46dcc0709
7 changed files with 153 additions and 93 deletions
5
changes/bug23820
Normal file
5
changes/bug23820
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
o Minor bugfixes (IPv6, v3 single onion services):
|
||||||
|
- Remove buggy code for IPv6-only v3 single onion services, and reject
|
||||||
|
attempts to configure them. This release supports IPv4, dual-stack, and
|
||||||
|
IPv6-only v3 hidden services; and IPv4 and dual-stack v3 single onion
|
||||||
|
services. Fixes bug 23820; bugfix on 0.3.2.1-alpha.
|
|
@ -343,6 +343,17 @@ send_establish_intro(const hs_service_t *service,
|
||||||
memwipe(payload, 0, sizeof(payload));
|
memwipe(payload, 0, sizeof(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a string constant describing the anonymity of service. */
|
||||||
|
static const char *
|
||||||
|
get_service_anonymity_string(const hs_service_t *service)
|
||||||
|
{
|
||||||
|
if (service->config.is_single_onion) {
|
||||||
|
return "single onion";
|
||||||
|
} else {
|
||||||
|
return "hidden";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* For a given service, the ntor onion key and a rendezvous cookie, launch a
|
/* 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
|
* circuit to the rendezvous point specified by the link specifiers. On
|
||||||
* success, a circuit identifier is attached to the circuit with the needed
|
* success, a circuit identifier is attached to the circuit with the needed
|
||||||
|
@ -370,7 +381,15 @@ launch_rendezvous_point_circuit(const hs_service_t *service,
|
||||||
&data->onion_pk,
|
&data->onion_pk,
|
||||||
service->config.is_single_onion);
|
service->config.is_single_onion);
|
||||||
if (info == NULL) {
|
if (info == NULL) {
|
||||||
/* We are done here, we can't extend to the rendezvous point. */
|
/* We are done here, we can't extend to the rendezvous point.
|
||||||
|
* If you're running an IPv6-only v3 single onion service on 0.3.2 or with
|
||||||
|
* 0.3.2 clients, and somehow disable the option check, it will fail here.
|
||||||
|
*/
|
||||||
|
log_fn(LOG_PROTOCOL_WARN, LD_REND,
|
||||||
|
"Not enough info to open a circuit to a rendezvous point for "
|
||||||
|
"%s service %s.",
|
||||||
|
get_service_anonymity_string(service),
|
||||||
|
safe_str_client(service->onion_address));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,17 +411,19 @@ launch_rendezvous_point_circuit(const hs_service_t *service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circ == NULL) {
|
if (circ == NULL) {
|
||||||
log_warn(LD_REND, "Giving up on launching rendezvous circuit to %s "
|
log_warn(LD_REND, "Giving up on launching a rendezvous circuit to %s "
|
||||||
"for service %s",
|
"for %s service %s",
|
||||||
safe_str_client(extend_info_describe(info)),
|
safe_str_client(extend_info_describe(info)),
|
||||||
|
get_service_anonymity_string(service),
|
||||||
safe_str_client(service->onion_address));
|
safe_str_client(service->onion_address));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
|
log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
|
||||||
"for service %s",
|
"for %s service %s",
|
||||||
safe_str_client(extend_info_describe(info)),
|
safe_str_client(extend_info_describe(info)),
|
||||||
safe_str_client(hex_str((const char *) data->rendezvous_cookie,
|
safe_str_client(hex_str((const char *) data->rendezvous_cookie,
|
||||||
REND_COOKIE_LEN)),
|
REND_COOKIE_LEN)),
|
||||||
|
get_service_anonymity_string(service),
|
||||||
safe_str_client(service->onion_address));
|
safe_str_client(service->onion_address));
|
||||||
tor_assert(circ->build_state);
|
tor_assert(circ->build_state);
|
||||||
/* Rendezvous circuit have a specific timeout for the time spent on trying
|
/* Rendezvous circuit have a specific timeout for the time spent on trying
|
||||||
|
@ -533,7 +554,10 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Using an extend info object ei, set all possible link specifiers in lspecs.
|
/* Using an extend info object ei, set all possible link specifiers in lspecs.
|
||||||
* IPv4, legacy ID and ed25519 ID are mandatory thus MUST be present in ei. */
|
* legacy ID is mandatory thus MUST be present in ei. If IPv4 is not present,
|
||||||
|
* logs a BUG() warning, and returns an empty smartlist. Clients never make
|
||||||
|
* direct connections to rendezvous points, so they should always have an
|
||||||
|
* IPv4 address in ei. */
|
||||||
static void
|
static void
|
||||||
get_lspecs_from_extend_info(const extend_info_t *ei, smartlist_t *lspecs)
|
get_lspecs_from_extend_info(const extend_info_t *ei, smartlist_t *lspecs)
|
||||||
{
|
{
|
||||||
|
@ -542,7 +566,11 @@ get_lspecs_from_extend_info(const extend_info_t *ei, smartlist_t *lspecs)
|
||||||
tor_assert(ei);
|
tor_assert(ei);
|
||||||
tor_assert(lspecs);
|
tor_assert(lspecs);
|
||||||
|
|
||||||
/* IPv4 is mandatory. */
|
/* We require IPv4, we will add IPv6 support in a later tor version */
|
||||||
|
if (BUG(!tor_addr_is_v4(&ei->addr))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ls = link_specifier_new();
|
ls = link_specifier_new();
|
||||||
link_specifier_set_ls_type(ls, LS_IPV4);
|
link_specifier_set_ls_type(ls, LS_IPV4);
|
||||||
link_specifier_set_un_ipv4_addr(ls, tor_addr_to_ipv4h(&ei->addr));
|
link_specifier_set_un_ipv4_addr(ls, tor_addr_to_ipv4h(&ei->addr));
|
||||||
|
@ -560,15 +588,15 @@ get_lspecs_from_extend_info(const extend_info_t *ei, smartlist_t *lspecs)
|
||||||
link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
|
link_specifier_set_ls_len(ls, link_specifier_getlen_un_legacy_id(ls));
|
||||||
smartlist_add(lspecs, ls);
|
smartlist_add(lspecs, ls);
|
||||||
|
|
||||||
/* ed25519 ID is mandatory. */
|
/* ed25519 ID is only included if the extend_info has it. */
|
||||||
ls = link_specifier_new();
|
if (!ed25519_public_key_is_zero(&ei->ed_identity)) {
|
||||||
link_specifier_set_ls_type(ls, LS_ED25519_ID);
|
ls = link_specifier_new();
|
||||||
memcpy(link_specifier_getarray_un_ed25519_id(ls), &ei->ed_identity,
|
link_specifier_set_ls_type(ls, LS_ED25519_ID);
|
||||||
link_specifier_getlen_un_ed25519_id(ls));
|
memcpy(link_specifier_getarray_un_ed25519_id(ls), &ei->ed_identity,
|
||||||
link_specifier_set_ls_len(ls, link_specifier_getlen_un_ed25519_id(ls));
|
link_specifier_getlen_un_ed25519_id(ls));
|
||||||
smartlist_add(lspecs, ls);
|
link_specifier_set_ls_len(ls, link_specifier_getlen_un_ed25519_id(ls));
|
||||||
|
smartlist_add(lspecs, ls);
|
||||||
/* XXX: IPv6 is not clearly a thing in extend_info_t? */
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Using the given descriptor intro point ip, the extend information of the
|
/* Using the given descriptor intro point ip, the extend information of the
|
||||||
|
@ -1053,6 +1081,14 @@ hs_circ_send_introduce1(origin_circuit_t *intro_circ,
|
||||||
* object which is used to build the content of the cell. */
|
* object which is used to build the content of the cell. */
|
||||||
setup_introduce1_data(ip, rend_circ->build_state->chosen_exit,
|
setup_introduce1_data(ip, rend_circ->build_state->chosen_exit,
|
||||||
subcredential, &intro1_data);
|
subcredential, &intro1_data);
|
||||||
|
/* If we didn't get any link specifiers, it's because our extend info was
|
||||||
|
* bad. */
|
||||||
|
if (BUG(!intro1_data.link_specifiers) ||
|
||||||
|
!smartlist_len(intro1_data.link_specifiers)) {
|
||||||
|
log_warn(LD_REND, "Unable to get link specifiers for INTRODUCE1 cell on "
|
||||||
|
"circuit %u.", TO_CIRCUIT(intro_circ)->n_circ_id);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Final step before we encode a cell, we setup the circuit identifier which
|
/* Final step before we encode a cell, we setup the circuit identifier which
|
||||||
* will generate both the rendezvous cookie and client keypair for this
|
* will generate both the rendezvous cookie and client keypair for this
|
||||||
|
|
|
@ -776,15 +776,24 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
|
||||||
const hs_descriptor_t *desc;
|
const hs_descriptor_t *desc;
|
||||||
const hs_desc_encrypted_data_t *enc_data;
|
const hs_desc_encrypted_data_t *enc_data;
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
|
/* Calculate the onion address for logging purposes */
|
||||||
|
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
|
||||||
|
|
||||||
tor_assert(service_pk);
|
tor_assert(service_pk);
|
||||||
|
|
||||||
desc = hs_cache_lookup_as_client(service_pk);
|
desc = hs_cache_lookup_as_client(service_pk);
|
||||||
|
/* Assume the service is v3 if the descriptor is missing. This is ok,
|
||||||
|
* because we only use the address in log messages */
|
||||||
|
hs_build_address(service_pk,
|
||||||
|
desc ? desc->plaintext_data.version : HS_VERSION_THREE,
|
||||||
|
onion_address);
|
||||||
if (desc == NULL || !hs_client_any_intro_points_usable(service_pk,
|
if (desc == NULL || !hs_client_any_intro_points_usable(service_pk,
|
||||||
desc)) {
|
desc)) {
|
||||||
log_info(LD_REND, "Unable to randomly select an introduction point "
|
log_info(LD_REND, "Unable to randomly select an introduction point "
|
||||||
"because descriptor %s.",
|
"for service %s because descriptor %s. We can't connect.",
|
||||||
(desc) ? "doesn't have usable intro point" : "is missing");
|
safe_str_client(onion_address),
|
||||||
|
(desc) ? "doesn't have any usable intro points"
|
||||||
|
: "is missing (assuming v3 onion address)");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,6 +821,10 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
|
||||||
if (ei == NULL) {
|
if (ei == NULL) {
|
||||||
/* We can get here for instance if the intro point is a private address
|
/* We can get here for instance if the intro point is a private address
|
||||||
* and we aren't allowed to extend to those. */
|
* and we aren't allowed to extend to those. */
|
||||||
|
log_info(LD_REND, "Unable to select introduction point with auth key %s "
|
||||||
|
"for service %s, because we could not extend to it.",
|
||||||
|
safe_str_client(ed25519_fmt(&ip->auth_key_cert->signed_key)),
|
||||||
|
safe_str_client(onion_address));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,14 +853,20 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
|
||||||
* set, we are forced to not use anything. */
|
* set, we are forced to not use anything. */
|
||||||
ei = ei_excluded;
|
ei = ei_excluded;
|
||||||
if (options->StrictNodes) {
|
if (options->StrictNodes) {
|
||||||
log_warn(LD_REND, "Every introduction points are in the ExcludeNodes set "
|
log_warn(LD_REND, "Every introduction point for service %s is in the "
|
||||||
"and StrictNodes is set. We can't connect.");
|
"ExcludeNodes set and StrictNodes is set. We can't connect.",
|
||||||
|
safe_str_client(onion_address));
|
||||||
extend_info_free(ei);
|
extend_info_free(ei);
|
||||||
ei = NULL;
|
ei = NULL;
|
||||||
|
} else {
|
||||||
|
log_fn(LOG_PROTOCOL_WARN, LD_REND, "Every introduction point for service "
|
||||||
|
"%s is unusable or we can't extend to it. We can't connect.",
|
||||||
|
safe_str_client(onion_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
smartlist_free(usable_ips);
|
smartlist_free(usable_ips);
|
||||||
|
memwipe(onion_address, 0, sizeof(onion_address));
|
||||||
return ei;
|
return ei;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1638,24 +1638,22 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str)
|
||||||
|
|
||||||
/* From a list of link specifier, an onion key and if we are requesting a
|
/* 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
|
* direct connection (ex: single onion service), return a newly allocated
|
||||||
* extend_info_t object. This function checks the firewall policies and if we
|
* extend_info_t object. This function always returns an extend info with
|
||||||
* are allowed to extend to the chosen address.
|
* an IPv4 address, or NULL.
|
||||||
*
|
*
|
||||||
* if either IPv4 or legacy ID is missing, error.
|
* It performs the following checks:
|
||||||
* if not direct_conn, IPv4 is prefered.
|
* if either IPv4 or legacy ID is missing, return NULL.
|
||||||
* if direct_conn, IPv6 is prefered if we have one available.
|
* if direct_conn, and we can't reach the IPv4 address, return NULL.
|
||||||
* if firewall does not allow the chosen address, error.
|
*/
|
||||||
*
|
|
||||||
* Return NULL if we can fulfill the conditions. */
|
|
||||||
extend_info_t *
|
extend_info_t *
|
||||||
hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
|
hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
|
||||||
const curve25519_public_key_t *onion_key,
|
const curve25519_public_key_t *onion_key,
|
||||||
int direct_conn)
|
int direct_conn)
|
||||||
{
|
{
|
||||||
int have_v4 = 0, have_v6 = 0, have_legacy_id = 0, have_ed25519_id = 0;
|
int have_v4 = 0, have_legacy_id = 0, have_ed25519_id = 0;
|
||||||
char legacy_id[DIGEST_LEN] = {0};
|
char legacy_id[DIGEST_LEN] = {0};
|
||||||
uint16_t port_v4 = 0, port_v6 = 0, port = 0;
|
uint16_t port_v4 = 0;
|
||||||
tor_addr_t addr_v4, addr_v6, *addr = NULL;
|
tor_addr_t addr_v4;
|
||||||
ed25519_public_key_t ed25519_pk;
|
ed25519_public_key_t ed25519_pk;
|
||||||
extend_info_t *info = NULL;
|
extend_info_t *info = NULL;
|
||||||
|
|
||||||
|
@ -1671,14 +1669,6 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
|
||||||
port_v4 = link_specifier_get_un_ipv4_port(ls);
|
port_v4 = link_specifier_get_un_ipv4_port(ls);
|
||||||
have_v4 = 1;
|
have_v4 = 1;
|
||||||
break;
|
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:
|
case LS_LEGACY_ID:
|
||||||
/* Make sure we do have enough bytes for the legacy ID. */
|
/* Make sure we do have enough bytes for the legacy ID. */
|
||||||
if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) {
|
if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) {
|
||||||
|
@ -1700,55 +1690,45 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
|
||||||
}
|
}
|
||||||
} SMARTLIST_FOREACH_END(ls);
|
} SMARTLIST_FOREACH_END(ls);
|
||||||
|
|
||||||
/* IPv4 and legacy ID are mandatory. */
|
/* Legacy ID is mandatory, and we require IPv4. */
|
||||||
if (!have_v4 || !have_legacy_id) {
|
if (!have_v4 || !have_legacy_id) {
|
||||||
goto done;
|
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
|
/* We know we have IPv4, because we just checked. */
|
||||||
* 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) {
|
if (!direct_conn) {
|
||||||
|
/* All clients can extend to any IPv4 via a 3-hop path. */
|
||||||
goto validate;
|
goto validate;
|
||||||
}
|
} else if (direct_conn &&
|
||||||
|
fascist_firewall_allows_address_addr(&addr_v4, port_v4,
|
||||||
/* From this point on, we have a request for a direct connection to the
|
FIREWALL_OR_CONNECTION,
|
||||||
* rendezvous point so make sure we can actually connect through our
|
0, 0)) {
|
||||||
* 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. */
|
/* Direct connection and we can reach it in IPv4 so go for it. */
|
||||||
addr = &addr_v4; port = port_v4;
|
|
||||||
goto validate;
|
goto validate;
|
||||||
|
|
||||||
|
/* We will add support for falling back to a 3-hop path in a later
|
||||||
|
* release. */
|
||||||
|
} else {
|
||||||
|
/* If we can't reach IPv4, return NULL. */
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We will add support for IPv6 in a later release. */
|
||||||
|
|
||||||
validate:
|
validate:
|
||||||
/* We'll validate now that the address we've picked isn't a private one. If
|
/* 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? */
|
* it is, are we allowing to extend to private address? */
|
||||||
if (!extend_info_addr_is_allowed(addr)) {
|
if (!extend_info_addr_is_allowed(&addr_v4)) {
|
||||||
log_warn(LD_REND, "Requested address is private and it is not "
|
log_fn(LOG_PROTOCOL_WARN, LD_REND,
|
||||||
"allowed to extend to it: %s:%u",
|
"Requested address is private and we are not allowed to extend to "
|
||||||
fmt_addr(&addr_v4), port_v4);
|
"it: %s:%u", fmt_addr(&addr_v4), port_v4);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do have everything for which we think we can connect successfully. */
|
/* We do have everything for which we think we can connect successfully. */
|
||||||
info = extend_info_new(NULL, legacy_id,
|
info = extend_info_new(NULL, legacy_id,
|
||||||
(have_ed25519_id) ? &ed25519_pk : NULL, NULL,
|
(have_ed25519_id) ? &ed25519_pk : NULL, NULL,
|
||||||
onion_key, addr, port);
|
onion_key, &addr_v4, port_v4);
|
||||||
done:
|
done:
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,11 +424,19 @@ config_generic_service(const config_line_t *line_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we are configured in non anonymous mode and single hop mode
|
/* Check if we are configured in non anonymous mode meaning every service
|
||||||
* meaning every service become single onion. */
|
* becomes a single onion service. */
|
||||||
if (rend_service_allow_non_anonymous_connection(options) &&
|
if (rend_service_non_anonymous_mode_enabled(options)) {
|
||||||
rend_service_non_anonymous_mode_enabled(options)) {
|
|
||||||
config->is_single_onion = 1;
|
config->is_single_onion = 1;
|
||||||
|
/* We will add support for IPv6-only v3 single onion services in a future
|
||||||
|
* Tor version. This won't catch "ReachableAddresses reject *4", but that
|
||||||
|
* option doesn't work anyway. */
|
||||||
|
if (options->ClientUseIPv4 == 0 && config->version == HS_VERSION_THREE) {
|
||||||
|
log_warn(LD_CONFIG, "IPv6-only v3 single onion services are not "
|
||||||
|
"supported. Set HiddenServiceSingleHopMode 0 and "
|
||||||
|
"HiddenServiceNonAnonymousMode 0, or set ClientUseIPv4 1.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
|
|
|
@ -375,7 +375,14 @@ service_intro_point_free_(void *obj)
|
||||||
|
|
||||||
/* Return a newly allocated service intro point and fully initialized from the
|
/* Return a newly allocated service intro point and fully initialized from the
|
||||||
* given extend_info_t ei if non NULL. If is_legacy is true, we also generate
|
* given extend_info_t ei if non NULL. If is_legacy is true, we also generate
|
||||||
* the legacy key. On error, NULL is returned. */
|
* the legacy key. On error, NULL is returned.
|
||||||
|
*
|
||||||
|
* If ei is NULL, returns a hs_service_intro_point_t with an empty link
|
||||||
|
* specifier list and no onion key. (This is used for testing.)
|
||||||
|
*
|
||||||
|
* ei must be an extend_info_t containing an IPv4 address. (We will add supoort
|
||||||
|
* for IPv6 in a later release.) When calling extend_info_from_node(), pass
|
||||||
|
* 0 in for_direct_connection to make sure ei always has an IPv4 address. */
|
||||||
STATIC hs_service_intro_point_t *
|
STATIC hs_service_intro_point_t *
|
||||||
service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
|
service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
|
||||||
{
|
{
|
||||||
|
@ -427,8 +434,8 @@ service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We'll try to add all link specifier. Legacy, IPv4 and ed25519 are
|
/* We'll try to add all link specifiers. Legacy is mandatory.
|
||||||
* mandatory. */
|
* IPv4 or IPv6 is required, and we always send IPv4. */
|
||||||
ls = hs_desc_link_specifier_new(ei, LS_IPV4);
|
ls = hs_desc_link_specifier_new(ei, LS_IPV4);
|
||||||
/* It is impossible to have an extend info object without a v4. */
|
/* It is impossible to have an extend info object without a v4. */
|
||||||
if (BUG(!ls)) {
|
if (BUG(!ls)) {
|
||||||
|
@ -450,11 +457,7 @@ service_intro_point_new(const extend_info_t *ei, unsigned int is_legacy)
|
||||||
smartlist_add(ip->base.link_specifiers, ls);
|
smartlist_add(ip->base.link_specifiers, ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IPv6 is optional. */
|
/* IPv6 is not supported in this release. */
|
||||||
ls = hs_desc_link_specifier_new(ei, LS_IPV6);
|
|
||||||
if (ls) {
|
|
||||||
smartlist_add(ip->base.link_specifiers, ls);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, copy onion key from the extend_info_t object. */
|
/* Finally, copy onion key from the extend_info_t object. */
|
||||||
memcpy(&ip->onion_key, &ei->curve25519_onion_key, sizeof(ip->onion_key));
|
memcpy(&ip->onion_key, &ei->curve25519_onion_key, sizeof(ip->onion_key));
|
||||||
|
@ -1520,10 +1523,17 @@ build_all_descriptors(time_t now)
|
||||||
/* Randomly pick a node to become an introduction point but not present in the
|
/* Randomly pick a node to become an introduction point but not present in the
|
||||||
* given exclude_nodes list. The chosen node is put in the exclude list
|
* given exclude_nodes list. The chosen node is put in the exclude list
|
||||||
* regardless of success or not because in case of failure, the node is simply
|
* regardless of success or not because in case of failure, the node is simply
|
||||||
* unsusable from that point on. If direct_conn is set, try to pick a node
|
* unsusable from that point on.
|
||||||
* that our local firewall/policy allows to directly connect to and if not,
|
*
|
||||||
* fallback to a normal 3-hop node. Return a newly allocated service intro
|
* If direct_conn is set, try to pick a node that our local firewall/policy
|
||||||
* point ready to be used for encoding. NULL on error. */
|
* allows us to connect to directly. If we can't find any, return NULL.
|
||||||
|
* This function supports selecting dual-stack nodes for direct single onion
|
||||||
|
* service IPv6 connections. But it does not send IPv6 addresses in link
|
||||||
|
* specifiers. (Current clients don't use IPv6 addresses to extend, and
|
||||||
|
* direct client connections to intro points are not supported.)
|
||||||
|
*
|
||||||
|
* Return a newly allocated service intro point ready to be used for encoding.
|
||||||
|
* Return NULL on error. */
|
||||||
static hs_service_intro_point_t *
|
static hs_service_intro_point_t *
|
||||||
pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
|
pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
|
||||||
{
|
{
|
||||||
|
@ -1537,12 +1547,9 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
|
||||||
|
|
||||||
node = router_choose_random_node(exclude_nodes, get_options()->ExcludeNodes,
|
node = router_choose_random_node(exclude_nodes, get_options()->ExcludeNodes,
|
||||||
direct_conn ? direct_flags : flags);
|
direct_conn ? direct_flags : flags);
|
||||||
if (node == NULL && direct_conn) {
|
/* Unable to find a node. When looking for a node for a direct connection,
|
||||||
/* Unable to find a node for direct connection, let's fall back to a
|
* we could try a 3-hop path instead. We'll add support for this in a later
|
||||||
* normal 3-hop node. */
|
* release. */
|
||||||
node = router_choose_random_node(exclude_nodes,
|
|
||||||
get_options()->ExcludeNodes, flags);
|
|
||||||
}
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -1553,8 +1560,11 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
|
||||||
smartlist_add(exclude_nodes, (void *) node);
|
smartlist_add(exclude_nodes, (void *) node);
|
||||||
|
|
||||||
/* We do this to ease our life but also this call makes appropriate checks
|
/* We do this to ease our life but also this call makes appropriate checks
|
||||||
* of the node object such as validating ntor support for instance. */
|
* of the node object such as validating ntor support for instance.
|
||||||
info = extend_info_from_node(node, direct_conn);
|
*
|
||||||
|
* We must provide an extend_info for clients to connect over a 3-hop path,
|
||||||
|
* so we don't pass direct_conn here. */
|
||||||
|
info = extend_info_from_node(node, 0);
|
||||||
if (BUG(info == NULL)) {
|
if (BUG(info == NULL)) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,10 @@ TESTS += src/test/test src/test/test-slow src/test/test-memwipe \
|
||||||
TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v2-min hs-v3-min \
|
TEST_CHUTNEY_FLAVORS = basic-min bridges-min hs-v2-min hs-v3-min \
|
||||||
single-onion-v23
|
single-onion-v23
|
||||||
# only run if we can ping6 ::1 (localhost)
|
# only run if we can ping6 ::1 (localhost)
|
||||||
|
# IPv6-only v3 single onion services don't work yet, so we don't test the
|
||||||
|
# single-onion-v23-ipv6 flavor
|
||||||
TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6 \
|
TEST_CHUTNEY_FLAVORS_IPV6 = bridges+ipv6-min ipv6-exit-min hs-v23-ipv6 \
|
||||||
single-onion-v23-ipv6
|
single-onion-ipv6
|
||||||
# only run if we can find a stable (or simply another) version of tor
|
# only run if we can find a stable (or simply another) version of tor
|
||||||
TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v23
|
TEST_CHUTNEY_FLAVORS_MIXED = mixed+hs-v23
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue