]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Prohibit the use of one entry node with an HS
authorDavid Goulet <dgoulet@ev0ke.net>
Wed, 2 Sep 2015 12:53:39 +0000 (14:53 +0200)
committerNick Mathewson <nickm@torproject.org>
Wed, 2 Sep 2015 14:47:20 +0000 (10:47 -0400)
In a nutshell, since a circuit can not exit at its entry point, it's very
easy for an attacker to find the hidden service guard if only one EntryNodes
is specified since for that guard, the HS will refuse to build a rendezvous
circuit to it.

For now, the best solution is to stop tor to allow a single EntryNodes for
an hidden service.

Fixes #14917

Signed-off-by: David Goulet <dgoulet@ev0ke.net>
changes/bug14917 [new file with mode: 0644]
src/or/config.c
src/or/routerset.c
src/or/routerset.h

diff --git a/changes/bug14917 b/changes/bug14917
new file mode 100644 (file)
index 0000000..92a985c
--- /dev/null
@@ -0,0 +1,5 @@
+  o Major bugfix
+    - For an hidden service, it is now prohibited to use one single
+      EntryNodes to avoid a very easy guard discovery attack. For more
+      details, see the ticket description here:
+      https://trac.torproject.org/projects/tor/ticket/14917. Fixes #14917.
index cb0abab613328a4de1369d47e8aebb938b1b484a..02b3477eaf1ca4e519da182035a70f670ee39e0c 100644 (file)
@@ -3173,6 +3173,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
              "http://freehaven.net/anonbib/#hs-attack06 for details.");
   }
 
+  if (routerset_is_list(options->EntryNodes) &&
+      (routerset_len(options->EntryNodes) == 1) &&
+      (options->RendConfigLines != NULL)) {
+    tor_asprintf(msg,
+             "You have one single EntryNodes and at least one hidden service "
+             "configured. This is bad because it's very easy to locate your "
+             "entry guard which can then lead to the deanonymization of your "
+             "hidden service -- for more details, see "
+             "https://trac.torproject.org/projects/tor/ticket/14917. "
+             "For this reason, the use of one EntryNodes with an hidden "
+             "service is prohibited until a better solution is found.");
+    return -1;
+  }
+
   if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout &&
       options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) {
     log_warn(LD_CONFIG,
index 99de11ed5ee3541b9aa9a97d5db9c5472fb85c7b..9fe5dffdeb88cb0786fdbc9cef94a5ccb6a4e69c 100644 (file)
@@ -162,6 +162,17 @@ routerset_is_empty(const routerset_t *set)
   return !set || smartlist_len(set->list) == 0;
 }
 
+/** Return the number of entries in <b>set</b>. This does NOT return a
+ * negative value. */
+int
+routerset_len(const routerset_t *set)
+{
+  if (!set) {
+    return 0;
+  }
+  return smartlist_len(set->list);
+}
+
 /** Helper.  Return true iff <b>set</b> contains a router based on the other
  * provided fields.  Return higher values for more specific subentries: a
  * single router is more specific than an address range of routers, which is
index 8d41de8b6b8e9e482fb1ac512de11bf09d87e3b7..aca7c6e74efa06a3ff8e157f498013d9fd069acf 100644 (file)
@@ -38,6 +38,7 @@ void routerset_subtract_nodes(smartlist_t *out,
 char *routerset_to_string(const routerset_t *routerset);
 int routerset_equal(const routerset_t *old, const routerset_t *new);
 void routerset_free(routerset_t *routerset);
+int routerset_len(const routerset_t *set);
 
 #ifdef ROUTERSET_PRIVATE
 STATIC char * routerset_get_countryname(const char *c);