Loading changes/bug5343 0 → 100644 +7 −0 Original line number Diff line number Diff line 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. src/or/routerlist.c +24 −5 Original line number Diff line number Diff line Loading @@ -4788,18 +4788,21 @@ 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, or_options_t *options, time_t now, routerset_t *in_set) routerset_t *in_set, int exit_only) { *num_present = 0, *num_usable=0; SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, { if (exit_only && ! rs->is_exit) continue; if (in_set && ! routerset_contains_routerstatus(in_set, rs)) continue; if (client_would_use_router(rs, now, options)) { Loading Loading @@ -4830,7 +4833,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 */ Loading @@ -4849,6 +4852,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; or_options_t *options = get_options(); Loading @@ -4875,7 +4879,9 @@ update_router_have_minimum_dir_info(void) } 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), Loading @@ -4889,12 +4895,25 @@ update_router_have_minimum_dir_info(void) num_present, 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), Loading Loading
changes/bug5343 0 → 100644 +7 −0 Original line number Diff line number Diff line 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.
src/or/routerlist.c +24 −5 Original line number Diff line number Diff line Loading @@ -4788,18 +4788,21 @@ 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, or_options_t *options, time_t now, routerset_t *in_set) routerset_t *in_set, int exit_only) { *num_present = 0, *num_usable=0; SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, { if (exit_only && ! rs->is_exit) continue; if (in_set && ! routerset_contains_routerstatus(in_set, rs)) continue; if (client_would_use_router(rs, now, options)) { Loading Loading @@ -4830,7 +4833,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 */ Loading @@ -4849,6 +4852,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; or_options_t *options = get_options(); Loading @@ -4875,7 +4879,9 @@ update_router_have_minimum_dir_info(void) } 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), Loading @@ -4889,12 +4895,25 @@ update_router_have_minimum_dir_info(void) num_present, 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), Loading