diff options
author | rubiate <cb@viennan.net> | 2016-11-10 10:16:18 +1300 |
---|---|---|
committer | rubiate <cb@viennan.net> | 2016-11-10 10:16:18 +1300 |
commit | d46c1b49a459f1249ef358b3751ef656d9e19038 (patch) | |
tree | 8063c1ba91b486fd9aeb6f35d71c2591e5e422a3 /src/or | |
parent | 0fed324c2c3862b1911a1add352f45c9a21f7a47 (diff) | |
download | tor-d46c1b49a459f1249ef358b3751ef656d9e19038.tar.gz tor-d46c1b49a459f1249ef358b3751ef656d9e19038.zip |
Do not serve a consensus if it is too old
Closes ticket 20511.
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/directory.c | 31 | ||||
-rw-r--r-- | src/or/networkstatus.c | 21 | ||||
-rw-r--r-- | src/or/networkstatus.h | 2 |
3 files changed, 52 insertions, 2 deletions
diff --git a/src/or/directory.c b/src/or/directory.c index ba6d38c426..b5c9d49d17 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2939,6 +2939,28 @@ handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args) return 0; } +/** Warn that the consensus <b>v</b> of type <b>flavor</b> is too old and will + * not be served to clients. Rate-limit the warning to avoid logging an entry + * on every request. + */ +static void +warn_consensus_is_too_old(networkstatus_t *v, const char *flavor, time_t now) +{ +#define TOO_OLD_WARNING_INTERVAL (60*60) + static ratelim_t warned = RATELIM_INIT(TOO_OLD_WARNING_INTERVAL); + char timestamp[ISO_TIME_LEN+1]; + char *dupes; + + if ((dupes = rate_limit_log(&warned, now))) { + format_local_iso_time(timestamp, v->valid_until); + log_warn(LD_DIRSERV, "Our %s%sconsensus is too old, so we will not " + "serve it to clients. It was valid until %s local time and we " + "continued to serve it for up to 24 hours after it expired.%s", + flavor ? flavor : "", flavor ? " " : "", timestamp, dupes); + tor_free(dupes); + } +} + /** Helper function for GET /tor/status-vote/current/consensus */ static int @@ -2983,6 +3005,15 @@ handle_get_current_consensus(dir_connection_t *conn, v = networkstatus_get_latest_consensus_by_flavor(flav); + if (v && !networkstatus_consensus_reasonably_live(v, now)) { + write_http_status_line(conn, 404, "Consensus is too old"); + warn_consensus_is_too_old(v, flavor, now); + smartlist_free(dir_fps); + geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND); + tor_free(flavor); + goto done; + } + if (v && want_fps && !client_likes_consensus(v, want_fps)) { write_http_status_line(conn, 404, "Consensus not signed by sufficient " diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index ed888fb53e..fde0b18a5a 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1342,6 +1342,24 @@ networkstatus_get_live_consensus,(time_t now)) return NULL; } +/** Determine if <b>consensus</b> is valid or expired recently enough that + * we can still use it. + * + * Return 1 if the consensus is reasonably live, or 0 if it is too old. + */ +int +networkstatus_consensus_reasonably_live(networkstatus_t *consensus, time_t now) +{ +#define REASONABLY_LIVE_TIME (24*60*60) + if (BUG(!consensus)) + return 0; + + if (now <= consensus->valid_until + REASONABLY_LIVE_TIME) + return 1; + + return 0; +} + /* XXXX remove this in favor of get_live_consensus. But actually, * leave something like it for bridge users, who need to not totally * lose if they spend a while fetching a new consensus. */ @@ -1350,12 +1368,11 @@ networkstatus_get_live_consensus,(time_t now)) networkstatus_t * networkstatus_get_reasonably_live_consensus(time_t now, int flavor) { -#define REASONABLY_LIVE_TIME (24*60*60) networkstatus_t *consensus = networkstatus_get_latest_consensus_by_flavor(flavor); if (consensus && consensus->valid_after <= now && - now <= consensus->valid_until+REASONABLY_LIVE_TIME) + networkstatus_consensus_reasonably_live(consensus, now)) return consensus; else return NULL; diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 71f36b69ed..172c0ea480 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -79,6 +79,8 @@ MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus,(void)); MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor, (consensus_flavor_t f)); MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now)); +int networkstatus_consensus_reasonably_live(networkstatus_t *consensus, + time_t now); networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now, int flavor); MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now)); |