mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 14:51:11 +01:00
Dir: when Tor's clock is behind, use a future consensus to bootstrap
When Tor's clock is behind the clocks on the authorities, allow Tor to bootstrap successfully. Fixes bug 28591; bugfix on 0.2.0.9-alpha.
This commit is contained in:
parent
bd29b3531a
commit
7a45bc74a4
6 changed files with 58 additions and 26 deletions
4
changes/bug28591
Normal file
4
changes/bug28591
Normal file
|
@ -0,0 +1,4 @@
|
|||
o Minor bugfixes (client, bootstrap):
|
||||
- When Tor's clock is behind the clocks on the authorities, allow Tor to
|
||||
bootstrap successfully. Fixes bug 28591; bugfix on 0.2.0.9-alpha.
|
||||
|
|
@ -110,8 +110,9 @@ microdesc_note_outdated_dirserver(const char *relay_digest)
|
|||
|
||||
/* If we have a reasonably live consensus, then most of our dirservers should
|
||||
* still be caching all the microdescriptors in it. Reasonably live
|
||||
* consensuses are up to a day old. But microdescriptors expire 7 days after
|
||||
* the last consensus that referenced them. */
|
||||
* consensuses are up to a day old (or a day in the future). But
|
||||
* microdescriptors expire 7 days after the last consensus that referenced
|
||||
* them. */
|
||||
if (!networkstatus_get_reasonably_live_consensus(approx_time(),
|
||||
FLAV_MICRODESC)) {
|
||||
return;
|
||||
|
@ -544,8 +545,8 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
|
|||
size_t bytes_dropped = 0;
|
||||
time_t now = time(NULL);
|
||||
|
||||
/* If we don't know a live consensus, don't believe last_listed values: we
|
||||
* might be starting up after being down for a while. */
|
||||
/* If we don't know a reasonably live consensus, don't believe last_listed
|
||||
* values: we might be starting up after being down for a while. */
|
||||
if (! force &&
|
||||
! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC))
|
||||
return;
|
||||
|
@ -973,6 +974,7 @@ update_microdesc_downloads(time_t now)
|
|||
if (directory_too_idle_to_fetch_descriptors(options, now))
|
||||
return;
|
||||
|
||||
/* Give up if we don't have a reasonably live consensus. */
|
||||
consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
|
||||
if (!consensus)
|
||||
return;
|
||||
|
|
|
@ -1377,7 +1377,7 @@ networkstatus_get_dl_status_by_flavor_running,(consensus_flavor_t flavor))
|
|||
}
|
||||
|
||||
/** Return the most recent consensus that we have downloaded, or NULL if we
|
||||
* don't have one. */
|
||||
* don't have one. May return future or expired consensuses. */
|
||||
MOCK_IMPL(networkstatus_t *,
|
||||
networkstatus_get_latest_consensus,(void))
|
||||
{
|
||||
|
@ -1388,7 +1388,7 @@ networkstatus_get_latest_consensus,(void))
|
|||
}
|
||||
|
||||
/** Return the latest consensus we have whose flavor matches <b>f</b>, or NULL
|
||||
* if we don't have one. */
|
||||
* if we don't have one. May return future or expired consensuses. */
|
||||
MOCK_IMPL(networkstatus_t *,
|
||||
networkstatus_get_latest_consensus_by_flavor,(consensus_flavor_t f))
|
||||
{
|
||||
|
@ -1422,10 +1422,11 @@ networkstatus_is_live(const networkstatus_t *ns, time_t now)
|
|||
return (ns->valid_after <= now && now <= ns->valid_until);
|
||||
}
|
||||
|
||||
/** Determine if <b>consensus</b> is valid or expired recently enough that
|
||||
* we can still use it.
|
||||
/** Determine if <b>consensus</b> is valid, or expired recently enough, or not
|
||||
* too far in the future, so that we can still use it.
|
||||
*
|
||||
* Return 1 if the consensus is reasonably live, or 0 if it is too old.
|
||||
* Return 1 if the consensus is reasonably live, or 0 if it is too old or
|
||||
* too new.
|
||||
*/
|
||||
int
|
||||
networkstatus_consensus_reasonably_live(const networkstatus_t *consensus,
|
||||
|
@ -1434,29 +1435,42 @@ networkstatus_consensus_reasonably_live(const networkstatus_t *consensus,
|
|||
if (BUG(!consensus))
|
||||
return 0;
|
||||
|
||||
return networkstatus_valid_until_is_reasonably_live(consensus->valid_until,
|
||||
return networkstatus_valid_after_is_reasonably_live(consensus->valid_after,
|
||||
now) &&
|
||||
networkstatus_valid_until_is_reasonably_live(consensus->valid_until,
|
||||
now);
|
||||
}
|
||||
|
||||
#define REASONABLY_LIVE_TIME (24*60*60)
|
||||
|
||||
/** As networkstatus_consensus_reasonably_live, but takes a valid_after
|
||||
* time, and checks to see if it is in the past, or not too far in the future.
|
||||
*/
|
||||
int
|
||||
networkstatus_valid_after_is_reasonably_live(time_t valid_after,
|
||||
time_t now)
|
||||
{
|
||||
return (now >= valid_after - REASONABLY_LIVE_TIME);
|
||||
}
|
||||
|
||||
/** As networkstatus_consensus_reasonably_live, but takes a valid_until
|
||||
* time rather than an entire consensus. */
|
||||
* time, and checks to see if it is in the future, or not too far in the past.
|
||||
*/
|
||||
int
|
||||
networkstatus_valid_until_is_reasonably_live(time_t valid_until,
|
||||
time_t now)
|
||||
{
|
||||
#define REASONABLY_LIVE_TIME (24*60*60)
|
||||
return (now <= valid_until + REASONABLY_LIVE_TIME);
|
||||
}
|
||||
|
||||
/** As networkstatus_get_live_consensus(), but is way more tolerant of expired
|
||||
* consensuses. */
|
||||
* and future consensuses. */
|
||||
MOCK_IMPL(networkstatus_t *,
|
||||
networkstatus_get_reasonably_live_consensus,(time_t now, int flavor))
|
||||
{
|
||||
networkstatus_t *consensus =
|
||||
networkstatus_get_latest_consensus_by_flavor(flavor);
|
||||
if (consensus &&
|
||||
consensus->valid_after <= now &&
|
||||
networkstatus_consensus_reasonably_live(consensus, now))
|
||||
return consensus;
|
||||
else
|
||||
|
@ -2082,7 +2096,6 @@ networkstatus_set_current_consensus(const char *consensus,
|
|||
|
||||
nodelist_set_consensus(c);
|
||||
|
||||
/* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/
|
||||
update_consensus_networkstatus_fetch_time(now);
|
||||
|
||||
/* Change the cell EWMA settings */
|
||||
|
|
|
@ -87,6 +87,8 @@ MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now));
|
|||
int networkstatus_is_live(const networkstatus_t *ns, time_t now);
|
||||
int networkstatus_consensus_reasonably_live(const networkstatus_t *consensus,
|
||||
time_t now);
|
||||
int networkstatus_valid_after_is_reasonably_live(time_t valid_after,
|
||||
time_t now);
|
||||
int networkstatus_valid_until_is_reasonably_live(time_t valid_until,
|
||||
time_t now);
|
||||
MOCK_DECL(networkstatus_t *,networkstatus_get_reasonably_live_consensus,
|
||||
|
|
|
@ -127,6 +127,9 @@ big_fake_network_cleanup(const struct testcase_t *testcase, void *ptr)
|
|||
return 1; /* NOP */
|
||||
}
|
||||
|
||||
#define REASONABLY_FUTURE " reasonably-future"
|
||||
#define REASONABLY_PAST " reasonably-past"
|
||||
|
||||
/* Unittest setup function: Setup a fake network. */
|
||||
static void *
|
||||
big_fake_network_setup(const struct testcase_t *testcase)
|
||||
|
@ -138,9 +141,10 @@ big_fake_network_setup(const struct testcase_t *testcase)
|
|||
const int N_NODES = 271;
|
||||
|
||||
const char *argument = testcase->setup_data;
|
||||
int reasonably_live_consensus = 0;
|
||||
int reasonably_future_consensus = 0, reasonably_past_consensus = 0;
|
||||
if (argument) {
|
||||
reasonably_live_consensus = strstr(argument, "reasonably-live") != NULL;
|
||||
reasonably_future_consensus = strstr(argument, REASONABLY_FUTURE) != NULL;
|
||||
reasonably_past_consensus = strstr(argument, REASONABLY_PAST) != NULL;
|
||||
}
|
||||
|
||||
big_fake_net_nodes = smartlist_new();
|
||||
|
@ -198,11 +202,15 @@ big_fake_network_setup(const struct testcase_t *testcase)
|
|||
|
||||
dummy_state = tor_malloc_zero(sizeof(or_state_t));
|
||||
dummy_consensus = tor_malloc_zero(sizeof(networkstatus_t));
|
||||
if (reasonably_live_consensus) {
|
||||
/* Make the dummy consensus valid from 4 hours ago, but expired an hour
|
||||
if (reasonably_future_consensus) {
|
||||
/* Make the dummy consensus valid in 6 hours, and expiring in 7 hours. */
|
||||
dummy_consensus->valid_after = approx_time() + 6*3600;
|
||||
dummy_consensus->valid_until = approx_time() + 7*3600;
|
||||
} else if (reasonably_past_consensus) {
|
||||
/* Make the dummy consensus valid from 16 hours ago, but expired 12 hours
|
||||
* ago. */
|
||||
dummy_consensus->valid_after = approx_time() - 4*3600;
|
||||
dummy_consensus->valid_until = approx_time() - 3600;
|
||||
dummy_consensus->valid_after = approx_time() - 16*3600;
|
||||
dummy_consensus->valid_until = approx_time() - 12*3600;
|
||||
} else {
|
||||
/* Make the dummy consensus valid for an hour either side of now. */
|
||||
dummy_consensus->valid_after = approx_time() - 3600;
|
||||
|
@ -3035,13 +3043,17 @@ static const struct testcase_setup_t upgrade_circuits = {
|
|||
|
||||
#define BFN_TEST(name) \
|
||||
EN_TEST_BASE(name, TT_FORK, &big_fake_network, NULL), \
|
||||
{ #name "_reasonably_live", test_entry_guard_ ## name, TT_FORK, \
|
||||
&big_fake_network, (void*)("reasonably-live") }
|
||||
{ #name "_reasonably_future", test_entry_guard_ ## name, TT_FORK, \
|
||||
&big_fake_network, (void*)(REASONABLY_FUTURE) }, \
|
||||
{ #name "_reasonably_past", test_entry_guard_ ## name, TT_FORK, \
|
||||
&big_fake_network, (void*)(REASONABLY_PAST) }
|
||||
|
||||
#define UPGRADE_TEST(name, arg) \
|
||||
EN_TEST_BASE(name, TT_FORK, &upgrade_circuits, arg), \
|
||||
{ #name "_reasonably_live", test_entry_guard_ ## name, TT_FORK, \
|
||||
&upgrade_circuits, (void*)(arg " reasonably-live") }
|
||||
{ #name "_reasonably_future", test_entry_guard_ ## name, TT_FORK, \
|
||||
&upgrade_circuits, (void*)(arg REASONABLY_FUTURE) }, \
|
||||
{ #name "_reasonably_past", test_entry_guard_ ## name, TT_FORK, \
|
||||
&upgrade_circuits, (void*)(arg REASONABLY_PAST) }
|
||||
|
||||
struct testcase_t entrynodes_tests[] = {
|
||||
NO_PREFIX_TEST(node_preferred_orport),
|
||||
|
|
|
@ -301,7 +301,6 @@ test_router_pick_directory_server_impl(void *arg)
|
|||
tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until
|
||||
+ 24*60*60));
|
||||
/* These times are outside the test validity period */
|
||||
tt_assert(networkstatus_consensus_is_bootstrapping(now));
|
||||
tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
|
||||
tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue