refuse excluded hidserv nodes if strictnodes

Make hidden services more flaky for people who set both ExcludeNodes
and StrictNodes. Not recommended, especially for hidden service operators.
This commit is contained in:
Roger Dingledine 2009-10-17 18:52:18 -04:00 committed by Nick Mathewson
parent f810a1afe9
commit 82178a81f6
2 changed files with 64 additions and 6 deletions

View File

@ -22,6 +22,9 @@
#include "rephist.h"
#include "routerlist.h"
static extend_info_t *rend_client_get_random_intro_impl(
const rend_data_t *rend_query, const int strict);
/** Called when we've established a circuit to an introduction point:
* send the introduction request. */
void
@ -738,11 +741,32 @@ rend_client_desc_trynow(const char *query)
*/
extend_info_t *
rend_client_get_random_intro(const rend_data_t *rend_query)
{
extend_info_t *result;
/* See if we can get a node that complies with ExcludeNodes */
if ((result = rend_client_get_random_intro_impl(rend_query, 1)))
return result;
/* If not, and StrictNodes is not set, see if we can return any old node
*/
if (!get_options()->StrictNodes)
return rend_client_get_random_intro_impl(rend_query, 0);
return NULL;
}
/** As rend_client_get_random_intro, except assume that StrictNodes is set
* iff <b>strict</b> is true.
*/
static extend_info_t *
rend_client_get_random_intro_impl(const rend_data_t *rend_query,
const int strict)
{
int i;
rend_cache_entry_t *entry;
rend_intro_point_t *intro;
routerinfo_t *router;
or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) {
log_warn(LD_REND,
@ -750,13 +774,26 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
safe_str_client(rend_query->onion_address));
return NULL;
}
/* We'll keep a separate list of the usable nodes. If this becomes empty,
* no nodes are usable. */
usable_nodes = smartlist_create();
smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
again:
if (smartlist_len(entry->parsed->intro_nodes) == 0)
if (smartlist_len(usable_nodes) == 0) {
if (n_excluded && get_options()->StrictNodes) {
/* We only want to warn if StrictNodes is really set. Otherwise
* we're just about to retry anyways.
*/
log_warn(LD_REND, "All introduction points for hidden service are "
"at excluded relays, and StrictNodes is set. Skipping.");
}
smartlist_free(usable_nodes);
return NULL;
}
i = crypto_rand_int(smartlist_len(entry->parsed->intro_nodes));
intro = smartlist_get(entry->parsed->intro_nodes, i);
i = crypto_rand_int(smartlist_len(usable_nodes));
intro = smartlist_get(usable_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
if (tor_digest_is_zero(intro->extend_info->identity_digest))
@ -766,13 +803,22 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
if (!router) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
rend_intro_point_free(intro);
smartlist_del(entry->parsed->intro_nodes, i);
smartlist_del(usable_nodes, i);
goto again;
}
extend_info_free(intro->extend_info);
intro->extend_info = extend_info_from_router(router);
}
/* Check if we should refuse to talk to this router. */
if (options->ExcludeNodes && strict &&
routerset_contains_extendinfo(options->ExcludeNodes,
intro->extend_info)) {
n_excluded++;
smartlist_del(usable_nodes, i);
goto again;
}
smartlist_free(usable_nodes);
return extend_info_dup(intro->extend_info);
}

View File

@ -848,6 +848,7 @@ clean_accepted_intros(rend_service_t *service, time_t now)
/** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
* rendezvous point.
*/
/* XXX022 this function sure could use some organizing. -RD */
int
rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
size_t request_len)
@ -875,6 +876,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
time_t now = time(NULL);
char diffie_hellman_hash[DIGEST_LEN];
time_t *access_time;
or_options_t *options = get_options();
tor_assert(circuit->rend_data);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@ -1047,6 +1050,15 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
/* Check if we'd refuse to talk to this router */
if (options->ExcludeNodes && options->StrictNodes &&
routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) {
log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
"exclude, and StrictNodes is set. Refusing service.");
reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */
goto err;
}
r_cookie = ptr;
base16_encode(hexcookie,9,r_cookie,4);