commit 82178a81f6748c9b26bdc8a5da36dd34b689281b Author: Roger Dingledine arma@torproject.org Date: Sat Oct 17 18:52:18 2009 -0400
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. --- src/or/rendclient.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---- src/or/rendservice.c | 14 +++++++++++- 2 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 8ac909f..90304c3 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -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 @@ -739,10 +742,31 @@ 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); }
diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 4503982..88f1ba3 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -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);
@@ -1394,7 +1406,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a * live introduction point, and note that the service descriptor is - * now out-of-date.*/ + * now out-of-date. */ int rend_service_intro_established(origin_circuit_t *circuit, const uint8_t *request,
tor-commits@lists.torproject.org