Browse Source

consdiffmgr: function to re-validate stored sha3 digests at startup

Nick Mathewson 7 years ago
parent
commit
655f1c8e01
3 changed files with 59 additions and 2 deletions
  1. 55 2
      src/or/consdiffmgr.c
  2. 1 0
      src/or/consdiffmgr.h
  3. 3 0
      src/test/test_consdiffmgr.c

+ 55 - 2
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());
@@ -390,6 +388,61 @@ consdiffmgr_configure(const consdiff_cfg_t *cfg)
   (void) cdm_cache_get();
 }
 
+/**
+ * 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
  */

+ 1 - 0
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);

+ 3 - 0
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]);