summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug149175
-rw-r--r--src/or/config.c14
-rw-r--r--src/or/routerset.c11
-rw-r--r--src/or/routerset.h1
4 files changed, 31 insertions, 0 deletions
diff --git a/changes/bug14917 b/changes/bug14917
new file mode 100644
index 0000000000..92a985ca7b
--- /dev/null
+++ b/changes/bug14917
@@ -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.
diff --git a/src/or/config.c b/src/or/config.c
index cb0abab613..02b3477eaf 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -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,
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 99de11ed5e..9fe5dffdeb 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -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
diff --git a/src/or/routerset.h b/src/or/routerset.h
index 8d41de8b6b..aca7c6e74e 100644
--- a/src/or/routerset.h
+++ b/src/or/routerset.h
@@ -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);