Переглянути джерело

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.
Roger Dingledine 14 роки тому
батько
коміт
82178a81f6
2 змінених файлів з 64 додано та 6 видалено
  1. 51 5
      src/or/rendclient.c
  2. 13 1
      src/or/rendservice.c

+ 51 - 5
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
@@ -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);
 }
 

+ 13 - 1
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,