commit 655f1c8e011a52910152ba52fc24c6e5b85023b4 Author: Nick Mathewson nickm@torproject.org Date: Sat Apr 15 11:43:53 2017 -0400
consdiffmgr: function to re-validate stored sha3 digests at startup --- src/or/consdiffmgr.c | 57 +++++++++++++++++++++++++++++++++++++++++++-- src/or/consdiffmgr.h | 1 + src/test/test_consdiffmgr.c | 3 +++ 3 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c index a9938d2..dce8c8b 100644 --- a/src/or/consdiffmgr.c +++ b/src/or/consdiffmgr.c @@ -370,8 +370,6 @@ consdiffmgr_cleanup(void) smartlist_free(objects); smartlist_free(consensuses); smartlist_free(diffs); - // XXXX for anything where the sha3 doesn't match -- delete it. But not - // XXXX here. Somewhere else?
// Actually remove files, if they're not used. consensus_cache_delete_pending(cdm_cache_get()); @@ -391,6 +389,61 @@ consdiffmgr_configure(const consdiff_cfg_t *cfg) }
/** + * Scan the consensus diff manager's cache for any grossly malformed entries, + * and mark them as deletable. Return 0 if no problems were found; 1 + * if problems were found and fixed. + */ +int +consdiffmgr_validate(void) +{ + /* Right now, we only check for entries that have bad sha3 values */ + int problems = 0; + + smartlist_t *objects = smartlist_new(); + consensus_cache_find_all(objects, cdm_cache_get(), + NULL, NULL); + SMARTLIST_FOREACH_BEGIN(objects, consensus_cache_entry_t *, obj) { + const char *lv_sha3 = + consensus_cache_entry_get_value(obj, LABEL_SHA3_DIGEST); + if (lv_sha3 == NULL) + continue; + + uint8_t sha3_expected[DIGEST256_LEN]; + uint8_t sha3_received[DIGEST256_LEN]; + int r = cdm_entry_get_sha3_value(sha3_expected, obj, LABEL_SHA3_DIGEST); + if (r == -1) { + /* digest isn't there; that's allowed */ + continue; + } else if (r == -2) { + /* digest is malformed; that's not allowed */ + problems = 1; + consensus_cache_entry_mark_for_removal(obj); + continue; + } + const uint8_t *body; + size_t bodylen; + consensus_cache_entry_incref(obj); + r = consensus_cache_entry_get_body(obj, &body, &bodylen); + if (r == 0) { + crypto_digest256((char *)sha3_received, (const char *)body, bodylen, + DIGEST_SHA3_256); + } + consensus_cache_entry_decref(obj); + if (r < 0) + continue; + + if (fast_memneq(sha3_received, sha3_expected, DIGEST256_LEN)) { + problems = 1; + consensus_cache_entry_mark_for_removal(obj); + continue; + } + + } SMARTLIST_FOREACH_END(obj); + smartlist_free(objects); + return problems; +} + +/** * Helper: build new diffs of <b>flavor</b> as needed */ static void diff --git a/src/or/consdiffmgr.h b/src/or/consdiffmgr.h index 2b3cee2..3e89ea2 100644 --- a/src/or/consdiffmgr.h +++ b/src/or/consdiffmgr.h @@ -33,6 +33,7 @@ void consdiffmgr_rescan(void); int consdiffmgr_cleanup(void); void consdiffmgr_configure(const consdiff_cfg_t *cfg); void consdiffmgr_free_all(void); +int consdiffmgr_validate(void);
#ifdef CONSDIFFMGR_PRIVATE STATIC consensus_cache_t *cdm_cache_get(void); diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c index 4eb9e7a..5161587 100644 --- a/src/test/test_consdiffmgr.c +++ b/src/test/test_consdiffmgr.c @@ -556,6 +556,9 @@ test_consdiffmgr_cleanup_old_diffs(void *arg) tt_int_op(0, OP_EQ, consdiffmgr_add_consensus(md_body[3], md_ns[3])); tt_int_op(2, OP_EQ, consdiffmgr_cleanup());
+ /* Everything should be valid at this point */ + tt_int_op(0, OP_EQ, consdiffmgr_validate()); + done: for (i = 0; i < N; ++i) { tor_free(md_body[i]);