tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit 559195ea82bf1c0610898fd96cd5a835b2e4f9a7
parent 733ce556ad6a59a111b63a860904799c30513a24
Author: Nick Mathewson <nickm@torproject.org>
Date:   Tue, 27 Jun 2017 18:28:38 -0400

Merge branch 'maint-0.3.1'

Diffstat:
Achanges/bug22702 | 5+++++
Msrc/or/consdiffmgr.c | 18++++++++++++++++++
Msrc/or/consdiffmgr.h | 3+++
Msrc/or/directory.c | 31+++++++++++++++++++++++++++++++
Msrc/or/dirserv.c | 6++++++
5 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/changes/bug22702 b/changes/bug22702 @@ -0,0 +1,5 @@ + o Major bugfixes (directory protocol): + - Ensure that we sent "304 Not modified" as HTTP status code when a + client is attempting to fetch a consensus or consensus diff that + matches the latest consensus we have available. Fixes bug 22702; + bugfix on 0.3.1.1-alpha. diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c @@ -1840,3 +1840,21 @@ consensus_cache_entry_get_valid_until(const consensus_cache_entry_t *ent, return 0; } +/** Read the valid after timestamp from the cached object <b>ent</b> into + * *<b>out</b> and return 0, or return -1 if no such time was recorded. */ +int +consensus_cache_entry_get_valid_after(const consensus_cache_entry_t *ent, + time_t *out) +{ + tor_assert(ent); + tor_assert(out); + + const char *s; + s = consensus_cache_entry_get_value(ent, LABEL_VALID_AFTER); + + if (s == NULL || parse_iso_time_nospace(s, out) < 0) + return -1; + else + return 0; +} + diff --git a/src/or/consdiffmgr.h b/src/or/consdiffmgr.h @@ -44,6 +44,9 @@ int consensus_cache_entry_get_fresh_until( int consensus_cache_entry_get_valid_until( const struct consensus_cache_entry_t *ent, time_t *out); +int consensus_cache_entry_get_valid_after( + const struct consensus_cache_entry_t *ent, + time_t *out); void consdiffmgr_rescan(void); int consdiffmgr_cleanup(void); diff --git a/src/or/directory.c b/src/or/directory.c @@ -3883,6 +3883,30 @@ find_best_compression_method(unsigned compression_methods, int stream) return NO_METHOD; } +/** Check if any of the digests in <b>digests</b> matches the latest consensus + * flavor (given in <b>flavor</b>) that we have available. */ +static int +digest_list_contains_best_consensus(consensus_flavor_t flavor, + const smartlist_t *digests) +{ + const networkstatus_t *ns = NULL; + + if (digests == NULL) + return 0; + + ns = networkstatus_get_latest_consensus_by_flavor(flavor); + + if (ns == NULL) + return 0; + + SMARTLIST_FOREACH_BEGIN(digests, const uint8_t *, digest) { + if (tor_memeq(ns->digest_sha3_as_signed, digest, DIGEST256_LEN)) + return 1; + } SMARTLIST_FOREACH_END(digest); + + return 0; +} + /** Check if the given compression method is allowed for a connection that is * supposed to be anonymous. Returns 1 if the compression method is allowed, * otherwise 0. */ @@ -4052,6 +4076,13 @@ handle_get_current_consensus(dir_connection_t *conn, goto done; } + if (digest_list_contains_best_consensus(req.flav, + req.diff_from_digests)) { + write_http_status_line(conn, 304, "Not modified"); + geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED); + goto done; + } + struct consensus_cache_entry_t *cached_consensus = NULL; compress_method_t compression_used = NO_METHOD; diff --git a/src/or/dirserv.c b/src/or/dirserv.c @@ -14,6 +14,7 @@ #include "connection.h" #include "connection_or.h" #include "conscache.h" +#include "consdiffmgr.h" #include "control.h" #include "directory.h" #include "dirserv.h" @@ -3530,6 +3531,11 @@ spooled_resource_estimate_size(const spooled_resource_t *spooled, } else { cached_dir_t *cached; if (spooled->consensus_cache_entry) { + if (published_out) { + consensus_cache_entry_get_valid_after( + spooled->consensus_cache_entry, published_out); + } + return spooled->cce_len; } if (spooled->cached_dir_ref) {