Bladeren bron

Merge remote-tracking branch 'origin/maint-0.2.2'

Conflicts:
	src/or/routerlist.c
Nick Mathewson 12 jaren geleden
bovenliggende
commit
d4526e1d4a
2 gewijzigde bestanden met toevoegingen van 31 en 5 verwijderingen
  1. 7 0
      changes/bug5343
  2. 24 5
      src/or/routerlist.c

+ 7 - 0
changes/bug5343

@@ -0,0 +1,7 @@
+  o Security fixes:
+    - Only build circuits if we have a sufficient threshold of the total
+      descriptors marked in the consensus with the "Exit" flag.  This
+      mitigates an attack proposed by wanoskarnet, in which all of a
+      client's bridges collude to restrict the exit nodes that the
+      client knows about.  Fixes bug 5343.
+

+ 24 - 5
src/or/routerlist.c

@@ -4891,19 +4891,22 @@ get_dir_info_status_string(void)
  * them seem like ones we'd use, and how many of <em>those</em> we have
  * descriptors for.  Store the former in *<b>num_usable</b> and the latter in
  * *<b>num_present</b>.  If <b>in_set</b> is non-NULL, only consider those
- * routers in <b>in_set</b>.
+ * routers in <b>in_set</b>.  If <b>exit_only</b> is true, only consider nodes
+ * with the Exit flag.
  */
 static void
 count_usable_descriptors(int *num_present, int *num_usable,
                          const networkstatus_t *consensus,
                          const or_options_t *options, time_t now,
-                         routerset_t *in_set)
+                         routerset_t *in_set, int exit_only)
 {
   const int md = (consensus->flavor == FLAV_MICRODESC);
   *num_present = 0, *num_usable=0;
 
   SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
     {
+       if (exit_only && ! rs->is_exit)
+         continue;
        if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
          continue;
        if (client_would_use_router(rs, now, options)) {
@@ -4941,7 +4944,7 @@ count_loading_descriptors_progress(void)
     return 0; /* can't count descriptors if we have no list of them */
 
   count_usable_descriptors(&num_present, &num_usable,
-                           consensus, get_options(), now, NULL);
+                           consensus, get_options(), now, NULL, 0);
 
   if (num_usable == 0)
     return 0; /* don't div by 0 */
@@ -4960,6 +4963,7 @@ static void
 update_router_have_minimum_dir_info(void)
 {
   int num_present = 0, num_usable=0;
+  int num_exit_present = 0, num_exit_usable = 0;
   time_t now = time(NULL);
   int res;
   const or_options_t *options = get_options();
@@ -4989,7 +4993,9 @@ update_router_have_minimum_dir_info(void)
   using_md = consensus->flavor == FLAV_MICRODESC;
 
   count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
-                           NULL);
+                           NULL, 0);
+  count_usable_descriptors(&num_exit_present, &num_exit_usable,
+                           consensus, options, now, options->ExitNodes, 1);
 
   if (num_present < num_usable/4) {
     tor_snprintf(dir_info_status, sizeof(dir_info_status),
@@ -5004,12 +5010,25 @@ update_router_have_minimum_dir_info(void)
                  num_present, using_md ? "micro" : "", num_present ? "" : "s");
     res = 0;
     goto done;
+  } else if (num_exit_present < num_exit_usable / 3) {
+    tor_snprintf(dir_info_status, sizeof(dir_info_status),
+                 "We have only %d/%d usable exit node descriptors.",
+                 num_exit_present, num_exit_usable);
+    res = 0;
+    control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
+    goto done;
+  } else if (num_exit_present < 2) {
+    tor_snprintf(dir_info_status, sizeof(dir_info_status),
+                 "Only %d descriptor%s here and believed reachable!",
+                 num_exit_present, num_exit_present ? "" : "s");
+    res = 0;
+    goto done;
   }
 
   /* Check for entry nodes. */
   if (options->EntryNodes) {
     count_usable_descriptors(&num_present, &num_usable, consensus, options,
-                             now, options->EntryNodes);
+                             now, options->EntryNodes, 0);
 
     if (!num_usable || !num_present) {
       tor_snprintf(dir_info_status, sizeof(dir_info_status),