diff options
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r-- | src/or/dirserv.c | 397 |
1 files changed, 6 insertions, 391 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 8d2da5b502..80a35c4e71 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1272,14 +1272,6 @@ directory_fetches_dir_info_later(const or_options_t *options) return options->UseBridges != 0; } -/** Return 1 if we want to cache v2 dir info (each status file). - */ -int -directory_caches_v2_dir_info(const or_options_t *options) -{ - return options->DirPort_set; -} - /** Return true iff we want to fetch and keep certificates for authorities * that we don't acknowledge as aurthorities ourself. */ @@ -1348,10 +1340,6 @@ static cached_dir_t *cached_directory = NULL; * if requested. */ static cached_dir_t cached_runningrouters; -/** Used for other dirservers' v2 network statuses. Map from hexdigest to - * cached_dir_t. */ -static digestmap_t *cached_v2_networkstatus = NULL; - /** Map from flavor name to the cached_dir_t for the v3 consensuses that we're * currently serving. */ static strmap_t *cached_consensuses = NULL; @@ -1452,70 +1440,6 @@ dirserv_set_cached_directory(const char *directory, time_t published) cached_directory = new_cached_dir(tor_strdup(directory), published); } -/** If <b>networkstatus</b> is non-NULL, we've just received a v2 - * network-status for an authoritative directory with identity digest - * <b>identity</b> published at <b>published</b> -- store it so we can - * serve it to others. - * - * If <b>networkstatus</b> is NULL, remove the entry with the given - * identity fingerprint from the v2 cache. - */ -void -dirserv_set_cached_networkstatus_v2(const char *networkstatus, - const char *identity, - time_t published) -{ - cached_dir_t *d, *old_d; - if (!cached_v2_networkstatus) - cached_v2_networkstatus = digestmap_new(); - - old_d = digestmap_get(cached_v2_networkstatus, identity); - if (!old_d && !networkstatus) - return; - - if (networkstatus) { - if (!old_d || published > old_d->published) { - d = new_cached_dir(tor_strdup(networkstatus), published); - digestmap_set(cached_v2_networkstatus, identity, d); - if (old_d) - cached_dir_decref(old_d); - } - } else { - if (old_d) { - digestmap_remove(cached_v2_networkstatus, identity); - cached_dir_decref(old_d); - } - } - - /* Now purge old entries. */ - - if (digestmap_size(cached_v2_networkstatus) > - get_n_authorities(V2_DIRINFO) + MAX_UNTRUSTED_NETWORKSTATUSES) { - /* We need to remove the oldest untrusted networkstatus. */ - const char *oldest = NULL; - time_t oldest_published = TIME_MAX; - digestmap_iter_t *iter; - - for (iter = digestmap_iter_init(cached_v2_networkstatus); - !digestmap_iter_done(iter); - iter = digestmap_iter_next(cached_v2_networkstatus, iter)) { - const char *ident; - void *val; - digestmap_iter_get(iter, &ident, &val); - d = val; - if (d->published < oldest_published && - !router_digest_is_trusted_dir(ident)) { - oldest = ident; - oldest_published = d->published; - } - } - tor_assert(oldest); - d = digestmap_remove(cached_v2_networkstatus, oldest); - if (d) - cached_dir_decref(d); - } -} - /** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that * we're serving with <b>networkstatus</b>, published at <b>published</b>. No * validation is performed. */ @@ -1538,30 +1462,6 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus, cached_dir_decref(old_networkstatus); } -/** Remove any v2 networkstatus from the directory cache that was published - * before <b>cutoff</b>. */ -void -dirserv_clear_old_networkstatuses(time_t cutoff) -{ - if (!cached_v2_networkstatus) - return; - - DIGESTMAP_FOREACH_MODIFY(cached_v2_networkstatus, id, cached_dir_t *, dir) { - if (dir->published < cutoff) { - char *fname; - fname = networkstatus_get_cache_filename(id); - if (file_status(fname) == FN_FILE) { - log_info(LD_DIR, "Removing too-old untrusted networkstatus in %s", - fname); - unlink(fname); - } - tor_free(fname); - cached_dir_decref(dir); - MAP_DEL_CURRENT(id); - } - } DIGESTMAP_FOREACH_END -} - /** Remove any v1 info from the directory cache that was published * too long ago. */ void @@ -1590,8 +1490,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src, dirinfo_type_t auth_type) { const or_options_t *options = get_options(); - int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) || - (auth_type == V2_DIRINFO && authdir_mode_v2(options)); + int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)); if (!authority || authdir_mode_bridge(options)) { return cache_src; @@ -1728,19 +1627,6 @@ dirserv_get_consensus(const char *flavor_name) return strmap_get(cached_consensuses, flavor_name); } -/** For authoritative directories: the current (v2) network status. */ -static cached_dir_t *the_v2_networkstatus = NULL; - -/** Return true iff our opinion of the routers has been stale for long - * enough that we should generate a new v2 network status doc. */ -static int -should_generate_v2_networkstatus(void) -{ - return authdir_mode_v2(get_options()) && - the_v2_networkstatus_is_dirty && - the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL); -} - /** If a router's uptime is at least this value, then it is always * considered stable, regardless of the rest of the network. This * way we resist attacks where an attacker doubles the size of the @@ -2411,7 +2297,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_unnamed?" Unnamed":"", - rs->is_v2_dir?" V2Dir":"", + (rs->dir_port!=0)?" V2Dir":"", rs->is_valid?" Valid":""); /* length of "opt v \n" */ @@ -2735,7 +2621,6 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_bad_exit = listbadexits && node->is_bad_exit; node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now); rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir; - rs->is_v2_dir = ri->dir_port != 0; if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME)) rs->is_named = rs->is_unnamed = 0; @@ -2766,7 +2651,7 @@ static void clear_status_flags_on_sybil(routerstatus_t *rs) { rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = - rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir = + rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit = rs->is_bad_directory = 0; /* FFFF we might want some mechanism to check later on if we @@ -3190,270 +3075,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, return v3_out; } -/** For v2 authoritative directories only: Replace the contents of - * <b>the_v2_networkstatus</b> with a newly generated network status - * object. */ -STATIC cached_dir_t * -generate_v2_networkstatus_opinion(void) -{ - cached_dir_t *r = NULL; - size_t identity_pkey_len; - char *status = NULL, *client_versions = NULL, *server_versions = NULL, - *identity_pkey = NULL, *hostname = NULL; - const or_options_t *options = get_options(); - char fingerprint[FINGERPRINT_LEN+1]; - char published[ISO_TIME_LEN+1]; - char digest[DIGEST_LEN]; - uint32_t addr; - crypto_pk_t *private_key; - routerlist_t *rl = router_get_routerlist(); - time_t now = time(NULL); - time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; - int naming = options->NamingAuthoritativeDir; - int versioning = options->VersioningAuthoritativeDir; - int listbaddirs = options->AuthDirListBadDirs; - int listbadexits = options->AuthDirListBadExits; - int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2; - const char *contact; - char *version_lines = NULL; - smartlist_t *routers = NULL; - digestmap_t *omit_as_sybil = NULL; - smartlist_t *chunks = NULL; - - private_key = get_server_identity_key(); - - if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) { - log_warn(LD_NET, "Couldn't resolve my hostname"); - goto done; - } - if (!hostname) - hostname = tor_dup_ip(addr); - - format_iso_time(published, now); - - client_versions = format_versions_list(options->RecommendedClientVersions); - server_versions = format_versions_list(options->RecommendedServerVersions); - - if (crypto_pk_write_public_key_to_string(private_key, &identity_pkey, - &identity_pkey_len)<0) { - log_warn(LD_BUG,"Writing public key to string failed."); - goto done; - } - - if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) { - log_err(LD_BUG, "Error computing fingerprint"); - goto done; - } - - contact = options->ContactInfo; - if (!contact) - contact = "(none)"; - - if (versioning) { - tor_asprintf(&version_lines, - "client-versions %s\nserver-versions %s\n", - client_versions, server_versions); - } else { - version_lines = tor_strdup(""); - } - - chunks = smartlist_new(); - smartlist_add_asprintf(chunks, - "network-status-version 2\n" - "dir-source %s %s %d\n" - "fingerprint %s\n" - "contact %s\n" - "published %s\n" - "dir-options%s%s%s%s\n" - "%s" /* client version line, server version line. */ - "dir-signing-key\n%s", - hostname, fmt_addr32(addr), - (int)router_get_advertised_dir_port(options, 0), - fingerprint, - contact, - published, - naming ? " Names" : "", - listbaddirs ? " BadDirectories" : "", - listbadexits ? " BadExits" : "", - versioning ? " Versions" : "", - version_lines, - identity_pkey); - - /* precompute this part, since we need it to decide what "stable" - * means. */ - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { - dirserv_set_router_is_running(ri, now); - }); - - routers = smartlist_new(); - smartlist_add_all(routers, rl->routers); - routers_sort_by_identity(routers); - omit_as_sybil = get_possible_sybil_list(routers); - - dirserv_compute_performance_thresholds(rl, omit_as_sybil); - - SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { - if (ri->cache_info.published_on >= cutoff) { - routerstatus_t rs; - char *version = version_from_platform(ri->platform); - node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest); - if (!node) { - tor_free(version); - continue; - } - set_routerstatus_from_routerinfo(&rs, node, ri, now, - naming, listbadexits, listbaddirs, - vote_on_hsdirs); - - if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) - clear_status_flags_on_sybil(&rs); - - { - char *rsf = routerstatus_format_entry(&rs, version, NS_V2, NULL); - if (rsf) - smartlist_add(chunks, rsf); - } - tor_free(version); - } - } SMARTLIST_FOREACH_END(ri); - - smartlist_add_asprintf(chunks, "directory-signature %s\n", - options->Nickname); - - crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); - - note_crypto_pk_op(SIGN_DIR); - { - char *sig; - if (!(sig = router_get_dirobj_signature(digest,DIGEST_LEN, - private_key))) { - log_warn(LD_BUG, "Unable to sign router status."); - goto done; - } - smartlist_add(chunks, sig); - } - - status = smartlist_join_strings(chunks, "", 0, NULL); - - { - networkstatus_v2_t *ns; - if (!(ns = networkstatus_v2_parse_from_string(status))) { - log_err(LD_BUG,"Generated a networkstatus we couldn't parse."); - goto done; - } - networkstatus_v2_free(ns); - } - - { - cached_dir_t **ns_ptr = &the_v2_networkstatus; - if (*ns_ptr) - cached_dir_decref(*ns_ptr); - *ns_ptr = new_cached_dir(status, now); - status = NULL; /* So it doesn't get double-freed. */ - the_v2_networkstatus_is_dirty = 0; - router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL); - r = *ns_ptr; - } - - done: - if (chunks) { - SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); - smartlist_free(chunks); - } - tor_free(client_versions); - tor_free(server_versions); - tor_free(version_lines); - tor_free(status); - tor_free(hostname); - tor_free(identity_pkey); - smartlist_free(routers); - digestmap_free(omit_as_sybil, NULL); - return r; -} - -/** Given the portion of a networkstatus request URL after "tor/status/" in - * <b>key</b>, append to <b>result</b> the digests of the identity keys of the - * networkstatus objects that the client has requested. */ -void -dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, - const char *key) -{ - tor_assert(result); - - if (!cached_v2_networkstatus) - cached_v2_networkstatus = digestmap_new(); - - if (should_generate_v2_networkstatus()) - generate_v2_networkstatus_opinion(); - - if (!strcmp(key,"authority")) { - if (authdir_mode_v2(get_options())) { - const routerinfo_t *me = router_get_my_routerinfo(); - if (me) - smartlist_add(result, - tor_memdup(me->cache_info.identity_digest, DIGEST_LEN)); - } - } else if (!strcmp(key, "all")) { - if (digestmap_size(cached_v2_networkstatus)) { - digestmap_iter_t *iter; - iter = digestmap_iter_init(cached_v2_networkstatus); - while (!digestmap_iter_done(iter)) { - const char *ident; - void *val; - digestmap_iter_get(iter, &ident, &val); - smartlist_add(result, tor_memdup(ident, DIGEST_LEN)); - iter = digestmap_iter_next(cached_v2_networkstatus, iter); - } - } else { - SMARTLIST_FOREACH(router_get_trusted_dir_servers(), - dir_server_t *, ds, - if (ds->type & V2_DIRINFO) - smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN))); - } - smartlist_sort_digests(result); - if (smartlist_len(result) == 0) - log_info(LD_DIRSERV, - "Client requested 'all' network status objects; we have none."); - } else if (!strcmpstart(key, "fp/")) { - dir_split_resource_into_fingerprints(key+3, result, NULL, - DSR_HEX|DSR_SORT_UNIQ); - } -} - -/** Look for a network status object as specified by <b>key</b>, which should - * be either "authority" (to find a network status generated by us), a hex - * identity digest (to find a network status generated by given directory), or - * "all" (to return all the v2 network status objects we have). - */ -void -dirserv_get_networkstatus_v2(smartlist_t *result, - const char *key) -{ - cached_dir_t *cached; - smartlist_t *fingerprints = smartlist_new(); - tor_assert(result); - - if (!cached_v2_networkstatus) - cached_v2_networkstatus = digestmap_new(); - - dirserv_get_networkstatus_v2_fingerprints(fingerprints, key); - SMARTLIST_FOREACH_BEGIN(fingerprints, const char *, fp) { - if (router_digest_is_me(fp) && should_generate_v2_networkstatus()) - generate_v2_networkstatus_opinion(); - cached = digestmap_get(cached_v2_networkstatus, fp); - if (cached) { - smartlist_add(result, cached); - } else { - char hexbuf[HEX_DIGEST_LEN+1]; - base16_encode(hexbuf, sizeof(hexbuf), fp, DIGEST_LEN); - log_info(LD_DIRSERV, "Don't know about any network status with " - "fingerprint '%s'", hexbuf); - } - } SMARTLIST_FOREACH_END(fp); - SMARTLIST_FOREACH(fingerprints, char *, cp, tor_free(cp)); - smartlist_free(fingerprints); -} - /** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t * pointers, adds copies of digests to fps_out, and doesn't use the * /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other @@ -3753,15 +3374,12 @@ static cached_dir_t * lookup_cached_dir_by_fp(const char *fp) { cached_dir_t *d = NULL; - if (tor_digest_is_zero(fp) && cached_consensuses) + if (tor_digest_is_zero(fp) && cached_consensuses) { d = strmap_get(cached_consensuses, "ns"); - else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses && + } else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses && (d = strmap_get(cached_consensuses, fp))) { /* this here interface is a nasty hack XXXX024 */; - } else if (router_digest_is_me(fp) && the_v2_networkstatus) - d = the_v2_networkstatus; - else if (cached_v2_networkstatus) - d = digestmap_get(cached_v2_networkstatus, fp); + } return d; } @@ -4156,12 +3774,9 @@ dirserv_free_all(void) cached_dir_decref(the_directory); clear_cached_dir(&the_runningrouters); - cached_dir_decref(the_v2_networkstatus); cached_dir_decref(cached_directory); clear_cached_dir(&cached_runningrouters); - digestmap_free(cached_v2_networkstatus, free_cached_dir_); - cached_v2_networkstatus = NULL; strmap_free(cached_consensuses, free_cached_dir_); cached_consensuses = NULL; |