Loading changes/bug13399 0 → 100644 +12 −0 Original line number Diff line number Diff line o Minor bugfixes: - Use a full 256 bits of the SHA256 digest of a microdescriptor when computing which microdescriptors to download. This keeps us from erroneous download behavior if two microdescriptor digests ever have the same first 160 bits. Fixes part of bug 13399; bugfix on 0.2.3.1-alpha. - Reset a router's status if its microdescriptor digest changes, even if the first 160 bits remain the same. Fixes part of bug 13399; bugfix on 0.2.3.1-alpha. src/or/microdesc.c +18 −18 Original line number Diff line number Diff line Loading @@ -163,19 +163,18 @@ microdescs_add_to_cache(microdesc_cache_t *cache, md->last_listed = listed_at); } if (requested_digests256) { digestmap_t *requested; /* XXXX actually we should just use a digest256map */ requested = digestmap_new(); digest256map_t *requested; requested = digest256map_new(); /* Set requested[d] to DIGEST_REQUESTED for every md we requested. */ SMARTLIST_FOREACH(requested_digests256, const char *, cp, digestmap_set(requested, cp, DIGEST_REQUESTED)); SMARTLIST_FOREACH(requested_digests256, const uint8_t *, cp, digest256map_set(requested, cp, DIGEST_REQUESTED)); /* Set requested[d] to DIGEST_INVALID for every md we requested which we * will never be able to parse. Remove the ones we didn't request from * invalid_digests. */ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, cp) { if (digestmap_get(requested, cp)) { digestmap_set(requested, cp, DIGEST_INVALID); SMARTLIST_FOREACH_BEGIN(invalid_digests, uint8_t *, cp) { if (digest256map_get(requested, cp)) { digest256map_set(requested, cp, DIGEST_INVALID); } else { tor_free(cp); SMARTLIST_DEL_CURRENT(invalid_digests, cp); Loading @@ -185,8 +184,9 @@ microdescs_add_to_cache(microdesc_cache_t *cache, * ones we never requested from the 'descriptors' smartlist. */ SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) { if (digestmap_get(requested, md->digest)) { digestmap_set(requested, md->digest, DIGEST_RECEIVED); if (digest256map_get(requested, (const uint8_t*)md->digest)) { digest256map_set(requested, (const uint8_t*)md->digest, DIGEST_RECEIVED); } else { log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microdesc"); microdesc_free(md); Loading @@ -195,14 +195,14 @@ microdescs_add_to_cache(microdesc_cache_t *cache, } SMARTLIST_FOREACH_END(md); /* Remove the ones we got or the invalid ones from requested_digests256. */ SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) { void *status = digestmap_get(requested, cp); SMARTLIST_FOREACH_BEGIN(requested_digests256, uint8_t *, cp) { void *status = digest256map_get(requested, cp); if (status == DIGEST_RECEIVED || status == DIGEST_INVALID) { tor_free(cp); SMARTLIST_DEL_CURRENT(requested_digests256, cp); } } SMARTLIST_FOREACH_END(cp); digestmap_free(requested, NULL); digest256map_free(requested, NULL); } /* For every requested microdescriptor that was unparseable, mark it Loading Loading @@ -794,7 +794,7 @@ microdesc_average_size(microdesc_cache_t *cache) * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */ smartlist_t * microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, int downloadable_only, digestmap_t *skip) int downloadable_only, digest256map_t *skip) { smartlist_t *result = smartlist_new(); time_t now = time(NULL); Loading @@ -806,7 +806,7 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, !download_status_is_ready(&rs->dl_status, now, get_options()->TestingMicrodescMaxDownloadTries)) continue; if (skip && digestmap_get(skip, rs->descriptor_digest)) if (skip && digest256map_get(skip, (const uint8_t*)rs->descriptor_digest)) continue; if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN)) continue; Loading @@ -831,7 +831,7 @@ update_microdesc_downloads(time_t now) const or_options_t *options = get_options(); networkstatus_t *consensus; smartlist_t *missing; digestmap_t *pending; digest256map_t *pending; if (should_delay_dir_fetches(options, NULL)) return; Loading @@ -845,14 +845,14 @@ update_microdesc_downloads(time_t now) if (!we_fetch_microdescriptors(options)) return; pending = digestmap_new(); pending = digest256map_new(); list_pending_microdesc_downloads(pending); missing = microdesc_list_missing_digest256(consensus, get_microdesc_cache(), 1, pending); digestmap_free(pending, NULL); digest256map_free(pending, NULL); launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, missing, NULL, now); Loading src/or/microdesc.h +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ size_t microdesc_average_size(microdesc_cache_t *cache); smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, int downloadable_only, digestmap_t *skip); digest256map_t *skip); void microdesc_free_(microdesc_t *md, const char *fname, int line); #define microdesc_free(md) \ Loading src/or/networkstatus.c +1 −1 Original line number Diff line number Diff line Loading @@ -1123,7 +1123,7 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, rs_new->last_dir_503_at = rs_old->last_dir_503_at; if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest, DIGEST_LEN)) { /* XXXX Change this to digest256_len */ DIGEST256_LEN)) { /* And the same descriptor too! */ memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t)); } Loading src/or/routerlist.c +18 −12 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ static const char *signed_descriptor_get_body_impl( const signed_descriptor_t *desc, int with_annotations); static void list_pending_downloads(digestmap_t *result, digest256map_t *result256, int purpose, const char *prefix); static void list_pending_fpsk_downloads(fp_pair_map_t *result); static void launch_dummy_descriptor_download_as_needed(time_t now, Loading Loading @@ -717,7 +718,8 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) * First, we get the lists of already pending downloads so we don't * duplicate effort. */ list_pending_downloads(pending_id, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); list_pending_downloads(pending_id, NULL, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); list_pending_fpsk_downloads(pending_cert); /* Loading Loading @@ -4268,7 +4270,7 @@ clear_dir_servers(void) * corresponding elements of <b>result</b> to a nonzero value. */ static void list_pending_downloads(digestmap_t *result, list_pending_downloads(digestmap_t *result, digest256map_t *result256, int purpose, const char *prefix) { const size_t p_len = strlen(prefix); Loading @@ -4278,7 +4280,7 @@ list_pending_downloads(digestmap_t *result, if (purpose == DIR_PURPOSE_FETCH_MICRODESC) flags = DSR_DIGEST256|DSR_BASE64; tor_assert(result); tor_assert(result || result256); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == CONN_TYPE_DIR && Loading @@ -4291,11 +4293,19 @@ list_pending_downloads(digestmap_t *result, } } SMARTLIST_FOREACH_END(conn); if (result) { SMARTLIST_FOREACH(tmp, char *, d, { digestmap_set(result, d, (void*)1); tor_free(d); }); } else if (result256) { SMARTLIST_FOREACH(tmp, uint8_t *, d, { digest256map_set(result256, d, (void*)1); tor_free(d); }); } smartlist_free(tmp); } Loading @@ -4307,20 +4317,16 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo) { int purpose = extrainfo ? DIR_PURPOSE_FETCH_EXTRAINFO : DIR_PURPOSE_FETCH_SERVERDESC; list_pending_downloads(result, purpose, "d/"); list_pending_downloads(result, NULL, purpose, "d/"); } /** For every microdescriptor we are currently downloading by descriptor * digest, set result[d] to (void*)1. (Note that microdescriptor digests * are 256-bit, and digestmap_t only holds 160-bit digests, so we're only * getting the first 20 bytes of each digest here.) * * XXXX Let there be a digestmap256_t, and use that instead. * digest, set result[d] to (void*)1. */ void list_pending_microdesc_downloads(digestmap_t *result) list_pending_microdesc_downloads(digest256map_t *result) { list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); list_pending_downloads(NULL, result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); } /** For every certificate we are currently downloading by (identity digest, Loading Loading
changes/bug13399 0 → 100644 +12 −0 Original line number Diff line number Diff line o Minor bugfixes: - Use a full 256 bits of the SHA256 digest of a microdescriptor when computing which microdescriptors to download. This keeps us from erroneous download behavior if two microdescriptor digests ever have the same first 160 bits. Fixes part of bug 13399; bugfix on 0.2.3.1-alpha. - Reset a router's status if its microdescriptor digest changes, even if the first 160 bits remain the same. Fixes part of bug 13399; bugfix on 0.2.3.1-alpha.
src/or/microdesc.c +18 −18 Original line number Diff line number Diff line Loading @@ -163,19 +163,18 @@ microdescs_add_to_cache(microdesc_cache_t *cache, md->last_listed = listed_at); } if (requested_digests256) { digestmap_t *requested; /* XXXX actually we should just use a digest256map */ requested = digestmap_new(); digest256map_t *requested; requested = digest256map_new(); /* Set requested[d] to DIGEST_REQUESTED for every md we requested. */ SMARTLIST_FOREACH(requested_digests256, const char *, cp, digestmap_set(requested, cp, DIGEST_REQUESTED)); SMARTLIST_FOREACH(requested_digests256, const uint8_t *, cp, digest256map_set(requested, cp, DIGEST_REQUESTED)); /* Set requested[d] to DIGEST_INVALID for every md we requested which we * will never be able to parse. Remove the ones we didn't request from * invalid_digests. */ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, cp) { if (digestmap_get(requested, cp)) { digestmap_set(requested, cp, DIGEST_INVALID); SMARTLIST_FOREACH_BEGIN(invalid_digests, uint8_t *, cp) { if (digest256map_get(requested, cp)) { digest256map_set(requested, cp, DIGEST_INVALID); } else { tor_free(cp); SMARTLIST_DEL_CURRENT(invalid_digests, cp); Loading @@ -185,8 +184,9 @@ microdescs_add_to_cache(microdesc_cache_t *cache, * ones we never requested from the 'descriptors' smartlist. */ SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) { if (digestmap_get(requested, md->digest)) { digestmap_set(requested, md->digest, DIGEST_RECEIVED); if (digest256map_get(requested, (const uint8_t*)md->digest)) { digest256map_set(requested, (const uint8_t*)md->digest, DIGEST_RECEIVED); } else { log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microdesc"); microdesc_free(md); Loading @@ -195,14 +195,14 @@ microdescs_add_to_cache(microdesc_cache_t *cache, } SMARTLIST_FOREACH_END(md); /* Remove the ones we got or the invalid ones from requested_digests256. */ SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) { void *status = digestmap_get(requested, cp); SMARTLIST_FOREACH_BEGIN(requested_digests256, uint8_t *, cp) { void *status = digest256map_get(requested, cp); if (status == DIGEST_RECEIVED || status == DIGEST_INVALID) { tor_free(cp); SMARTLIST_DEL_CURRENT(requested_digests256, cp); } } SMARTLIST_FOREACH_END(cp); digestmap_free(requested, NULL); digest256map_free(requested, NULL); } /* For every requested microdescriptor that was unparseable, mark it Loading Loading @@ -794,7 +794,7 @@ microdesc_average_size(microdesc_cache_t *cache) * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */ smartlist_t * microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, int downloadable_only, digestmap_t *skip) int downloadable_only, digest256map_t *skip) { smartlist_t *result = smartlist_new(); time_t now = time(NULL); Loading @@ -806,7 +806,7 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, !download_status_is_ready(&rs->dl_status, now, get_options()->TestingMicrodescMaxDownloadTries)) continue; if (skip && digestmap_get(skip, rs->descriptor_digest)) if (skip && digest256map_get(skip, (const uint8_t*)rs->descriptor_digest)) continue; if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN)) continue; Loading @@ -831,7 +831,7 @@ update_microdesc_downloads(time_t now) const or_options_t *options = get_options(); networkstatus_t *consensus; smartlist_t *missing; digestmap_t *pending; digest256map_t *pending; if (should_delay_dir_fetches(options, NULL)) return; Loading @@ -845,14 +845,14 @@ update_microdesc_downloads(time_t now) if (!we_fetch_microdescriptors(options)) return; pending = digestmap_new(); pending = digest256map_new(); list_pending_microdesc_downloads(pending); missing = microdesc_list_missing_digest256(consensus, get_microdesc_cache(), 1, pending); digestmap_free(pending, NULL); digest256map_free(pending, NULL); launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, missing, NULL, now); Loading
src/or/microdesc.h +1 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ size_t microdesc_average_size(microdesc_cache_t *cache); smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, int downloadable_only, digestmap_t *skip); digest256map_t *skip); void microdesc_free_(microdesc_t *md, const char *fname, int line); #define microdesc_free(md) \ Loading
src/or/networkstatus.c +1 −1 Original line number Diff line number Diff line Loading @@ -1123,7 +1123,7 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, rs_new->last_dir_503_at = rs_old->last_dir_503_at; if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest, DIGEST_LEN)) { /* XXXX Change this to digest256_len */ DIGEST256_LEN)) { /* And the same descriptor too! */ memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t)); } Loading
src/or/routerlist.c +18 −12 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ static const char *signed_descriptor_get_body_impl( const signed_descriptor_t *desc, int with_annotations); static void list_pending_downloads(digestmap_t *result, digest256map_t *result256, int purpose, const char *prefix); static void list_pending_fpsk_downloads(fp_pair_map_t *result); static void launch_dummy_descriptor_download_as_needed(time_t now, Loading Loading @@ -717,7 +718,8 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) * First, we get the lists of already pending downloads so we don't * duplicate effort. */ list_pending_downloads(pending_id, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); list_pending_downloads(pending_id, NULL, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/"); list_pending_fpsk_downloads(pending_cert); /* Loading Loading @@ -4268,7 +4270,7 @@ clear_dir_servers(void) * corresponding elements of <b>result</b> to a nonzero value. */ static void list_pending_downloads(digestmap_t *result, list_pending_downloads(digestmap_t *result, digest256map_t *result256, int purpose, const char *prefix) { const size_t p_len = strlen(prefix); Loading @@ -4278,7 +4280,7 @@ list_pending_downloads(digestmap_t *result, if (purpose == DIR_PURPOSE_FETCH_MICRODESC) flags = DSR_DIGEST256|DSR_BASE64; tor_assert(result); tor_assert(result || result256); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == CONN_TYPE_DIR && Loading @@ -4291,11 +4293,19 @@ list_pending_downloads(digestmap_t *result, } } SMARTLIST_FOREACH_END(conn); if (result) { SMARTLIST_FOREACH(tmp, char *, d, { digestmap_set(result, d, (void*)1); tor_free(d); }); } else if (result256) { SMARTLIST_FOREACH(tmp, uint8_t *, d, { digest256map_set(result256, d, (void*)1); tor_free(d); }); } smartlist_free(tmp); } Loading @@ -4307,20 +4317,16 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo) { int purpose = extrainfo ? DIR_PURPOSE_FETCH_EXTRAINFO : DIR_PURPOSE_FETCH_SERVERDESC; list_pending_downloads(result, purpose, "d/"); list_pending_downloads(result, NULL, purpose, "d/"); } /** For every microdescriptor we are currently downloading by descriptor * digest, set result[d] to (void*)1. (Note that microdescriptor digests * are 256-bit, and digestmap_t only holds 160-bit digests, so we're only * getting the first 20 bytes of each digest here.) * * XXXX Let there be a digestmap256_t, and use that instead. * digest, set result[d] to (void*)1. */ void list_pending_microdesc_downloads(digestmap_t *result) list_pending_microdesc_downloads(digest256map_t *result) { list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); list_pending_downloads(NULL, result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); } /** For every certificate we are currently downloading by (identity digest, Loading