mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 15:10:48 +01:00
prop224: Client function to pick intro point
From an edge connection object, add a function that randomly pick an introduction point for the requested service. This follows the code design of rend_client_get_random_intro() and returns an extend_info_t object ready to be used to extend to. At this commit, it is not used yet. Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
c38144bb0f
commit
abb840bf64
2 changed files with 120 additions and 1 deletions
|
@ -20,6 +20,7 @@
|
||||||
#include "directory.h"
|
#include "directory.h"
|
||||||
#include "hs_client.h"
|
#include "hs_client.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
|
#include "routerset.h"
|
||||||
#include "circuitlist.h"
|
#include "circuitlist.h"
|
||||||
#include "circuituse.h"
|
#include "circuituse.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
@ -387,6 +388,109 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ)
|
||||||
hs_circ_send_establish_rendezvous(circ);
|
hs_circ_send_establish_rendezvous(circ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is an helper function that convert a descriptor intro point object ip
|
||||||
|
* to a newly allocated extend_info_t object fully initialized. Return NULL if
|
||||||
|
* we can't convert it for which chances are that we are missing or malformed
|
||||||
|
* link specifiers. */
|
||||||
|
static extend_info_t *
|
||||||
|
desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip)
|
||||||
|
{
|
||||||
|
extend_info_t *ei;
|
||||||
|
smartlist_t *lspecs = smartlist_new();
|
||||||
|
|
||||||
|
tor_assert(ip);
|
||||||
|
|
||||||
|
/* We first encode the descriptor link specifiers into the binary
|
||||||
|
* representation which is a trunnel object. */
|
||||||
|
SMARTLIST_FOREACH_BEGIN(ip->link_specifiers,
|
||||||
|
const hs_desc_link_specifier_t *, desc_lspec) {
|
||||||
|
link_specifier_t *lspec = hs_desc_encode_lspec(desc_lspec);
|
||||||
|
smartlist_add(lspecs, lspec);
|
||||||
|
} SMARTLIST_FOREACH_END(desc_lspec);
|
||||||
|
|
||||||
|
/* Explicitely put the direct connection option to 0 because this is client
|
||||||
|
* side and there is no such thing as a non anonymous client. */
|
||||||
|
ei = hs_get_extend_info_from_lspecs(lspecs, &ip->onion_key, 0);
|
||||||
|
|
||||||
|
SMARTLIST_FOREACH(lspecs, link_specifier_t *, ls, link_specifier_free(ls));
|
||||||
|
smartlist_free(lspecs);
|
||||||
|
return ei;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Using a descriptor desc, return a newly allocated extend_info_t object of a
|
||||||
|
* randomly picked introduction point from its list. Return NULL if none are
|
||||||
|
* usable. */
|
||||||
|
static extend_info_t *
|
||||||
|
client_get_random_intro(const ed25519_public_key_t *service_pk)
|
||||||
|
{
|
||||||
|
extend_info_t *ei = NULL, *ei_excluded = NULL;
|
||||||
|
smartlist_t *usable_ips = NULL;
|
||||||
|
const hs_descriptor_t *desc;
|
||||||
|
const hs_desc_encrypted_data_t *enc_data;
|
||||||
|
const or_options_t *options = get_options();
|
||||||
|
|
||||||
|
tor_assert(service_pk);
|
||||||
|
|
||||||
|
desc = hs_cache_lookup_as_client(service_pk);
|
||||||
|
if (desc == NULL || !hs_client_any_intro_points_usable(desc)) {
|
||||||
|
log_info(LD_REND, "Unable to randomly select an introduction point "
|
||||||
|
"because descriptor %s.",
|
||||||
|
(desc) ? "doesn't have usable intro point" : "is missing");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
enc_data = &desc->encrypted_data;
|
||||||
|
usable_ips = smartlist_new();
|
||||||
|
smartlist_add_all(usable_ips, enc_data->intro_points);
|
||||||
|
while (smartlist_len(usable_ips) != 0) {
|
||||||
|
int idx;
|
||||||
|
const hs_desc_intro_point_t *ip;
|
||||||
|
|
||||||
|
/* Pick a random intro point and immediately remove it from the usable
|
||||||
|
* list so we don't pick it again if we have to iterate more. */
|
||||||
|
idx = crypto_rand_int(smartlist_len(usable_ips));
|
||||||
|
ip = smartlist_get(usable_ips, idx);
|
||||||
|
smartlist_del(usable_ips, idx);
|
||||||
|
|
||||||
|
/* Generate an extend info object from the intro point object. */
|
||||||
|
ei = desc_intro_point_to_extend_info(ip);
|
||||||
|
if (ei == NULL) {
|
||||||
|
/* We can get here for instance if the intro point is a private address
|
||||||
|
* and we aren't allowed to extend to those. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test the pick against ExcludeNodes. */
|
||||||
|
if (routerset_contains_extendinfo(options->ExcludeNodes, ei)) {
|
||||||
|
/* If this pick is in the ExcludeNodes list, we keep its reference so if
|
||||||
|
* we ever end up not being able to pick anything else and StrictNodes is
|
||||||
|
* unset, we'll use it. */
|
||||||
|
ei_excluded = ei;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* XXX: Intro point can time out or just be unsuable, we need to keep
|
||||||
|
* track of this and check against such cache. */
|
||||||
|
|
||||||
|
/* Good pick! Let's go with this. */
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reaching this point means a couple of things. Either we can't use any of
|
||||||
|
* the intro point listed because the IP address can't be extended to or it
|
||||||
|
* is listed in the ExcludeNodes list. In the later case, if StrictNodes is
|
||||||
|
* set, we are forced to not use anything. */
|
||||||
|
ei = ei_excluded;
|
||||||
|
if (options->StrictNodes) {
|
||||||
|
log_warn(LD_REND, "Every introduction points are in the ExcludeNodes set "
|
||||||
|
"and StrictNodes is set. We can't connect.");
|
||||||
|
ei = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
smartlist_free(usable_ips);
|
||||||
|
return ei;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========== */
|
/* ========== */
|
||||||
/* Public API */
|
/* Public API */
|
||||||
/* ========== */
|
/* ========== */
|
||||||
|
@ -643,3 +747,16 @@ hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident)
|
||||||
smartlist_free(conns);
|
smartlist_free(conns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a newly allocated extend_info_t for a randomly chosen introduction
|
||||||
|
* point for the given edge connection identifier ident. Return NULL if we
|
||||||
|
* can't pick any usable introduction points. */
|
||||||
|
extend_info_t *
|
||||||
|
hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn)
|
||||||
|
{
|
||||||
|
tor_assert(edge_conn);
|
||||||
|
|
||||||
|
return (edge_conn->hs_ident) ?
|
||||||
|
client_get_random_intro(&edge_conn->hs_ident->identity_pk) :
|
||||||
|
rend_client_get_random_intro(edge_conn->rend_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,10 @@ void hs_client_circuit_has_opened(origin_circuit_t *circ);
|
||||||
int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
|
int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
|
||||||
const uint8_t *payload,
|
const uint8_t *payload,
|
||||||
size_t payload_len);
|
size_t payload_len);
|
||||||
|
|
||||||
void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
|
void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
|
||||||
|
|
||||||
|
extend_info_t *hs_client_get_random_intro_from_edge(
|
||||||
|
const edge_connection_t *edge_conn);
|
||||||
|
|
||||||
#endif /* TOR_HS_CLIENT_H */
|
#endif /* TOR_HS_CLIENT_H */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue