diff options
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r-- | src/or/dirserv.c | 191 |
1 files changed, 86 insertions, 105 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index dafaed8bf2..34db06355b 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -19,10 +19,12 @@ #include "dirvote.h" #include "hibernate.h" #include "keypin.h" +#include "main.h" #include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" +#include "protover.h" #include "rephist.h" #include "router.h" #include "routerlist.h" @@ -34,6 +36,24 @@ * \file dirserv.c * \brief Directory server core implementation. Manages directory * contents and generates directories. + * + * This module implements most of directory cache functionality, and some of + * the directory authority functionality. The directory.c module delegates + * here in order to handle incoming requests from clients, via + * connection_dirserv_flushed_some() and its kin. In order to save RAM, this + * module is reponsible for spooling directory objects (in whole or in part) + * onto buf_t instances, and then closing the dir_connection_t once the + * objects are totally flushed. + * + * The directory.c module also delegates here for handling descriptor uploads + * via dirserv_add_multiple_descriptors(). + * + * Additionally, this module handles some aspects of voting, including: + * deciding how to vote on individual flags (based on decisions reached in + * rephist.c), of formatting routerstatus lines, and deciding what relays to + * include in an authority's vote. (TODO: Those functions could profitably be + * split off. They only live in this file because historically they were + * shared among the v1, v2, and v3 directory code.) */ /** How far in the future do we allow a router to get? (seconds) */ @@ -44,10 +64,6 @@ * directory authorities. */ #define MAX_UNTRUSTED_NETWORKSTATUSES 16 -extern time_t time_of_process_start; /* from main.c */ - -extern long stats_n_seconds_working; /* from main.c */ - /** Total number of routers with measured bandwidth; this is set by * dirserv_count_measured_bws() before the loop in * dirserv_generate_networkstatus_vote_obj() and checked by @@ -125,7 +141,8 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list, fingerprint = tor_strdup(fp); tor_strstrip(fingerprint, " "); - if (base16_decode(d, DIGEST_LEN, fingerprint, strlen(fingerprint))) { + if (base16_decode(d, DIGEST_LEN, + fingerprint, strlen(fingerprint)) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"", escaped(fp)); tor_free(fingerprint); @@ -202,7 +219,7 @@ dirserv_load_fingerprint_file(void) tor_strstrip(fingerprint, " "); /* remove spaces */ if (strlen(fingerprint) != HEX_DIGEST_LEN || base16_decode(digest_tmp, sizeof(digest_tmp), - fingerprint, HEX_DIGEST_LEN) < 0) { + fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) { log_notice(LD_CONFIG, "Invalid fingerprint (nickname '%s', " "fingerprint %s). Skipping.", @@ -257,6 +274,20 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg, return FP_REJECT; } + /* dirserv_get_status_impl already rejects versions older than 0.2.4.18-rc, + * and onion_curve25519_pkey was introduced in 0.2.4.8-alpha. + * But just in case a relay doesn't provide or lies about its version, or + * doesn't include an ntor key in its descriptor, check that it exists, + * and is non-zero (clients check that it's non-zero before using it). */ + if (!routerinfo_has_curve25519_onion_key(router)) { + log_fn(severity, LD_DIR, + "Descriptor from router %s is missing an ntor curve25519 onion " + "key.", router_describe(router)); + if (msg) + *msg = "Missing ntor curve25519 onion key. Please upgrade!"; + return FP_REJECT; + } + if (router->cache_info.signing_key_cert) { /* This has an ed25519 identity key. */ if (KEYPIN_MISMATCH == @@ -349,7 +380,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, if (result & FP_REJECT) { if (msg) - *msg = "Fingerprint is marked rejected"; + *msg = "Fingerprint is marked rejected -- please contact us?"; return FP_REJECT; } else if (result & FP_INVALID) { if (msg) @@ -367,7 +398,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'", nickname, fmt_addr32(addr)); if (msg) - *msg = "Authdir is rejecting routers in this range."; + *msg = "Suspicious relay address range -- please contact us?"; return FP_REJECT; } if (!authdir_policy_valid_address(addr, or_port)) { @@ -823,7 +854,7 @@ running_long_enough_to_decide_unreachable(void) void dirserv_set_router_is_running(routerinfo_t *router, time_t now) { - /*XXXX024 This function is a mess. Separate out the part that calculates + /*XXXX This function is a mess. Separate out the part that calculates whether it's reachable and the part that tells rephist that the router was unreachable. */ @@ -985,94 +1016,6 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) return 1; } -/** Generate a new v1 directory and write it into a newly allocated string. - * Point *<b>dir_out</b> to the allocated string. Sign the - * directory with <b>private_key</b>. Return 0 on success, -1 on - * failure. If <b>complete</b> is set, give us all the descriptors; - * otherwise leave out non-running and non-valid ones. - */ -int -dirserv_dump_directory_to_string(char **dir_out, - crypto_pk_t *private_key) -{ - /* XXXX 024 Get rid of this function if we can confirm that nobody's - * fetching these any longer */ - char *cp; - char *identity_pkey; /* Identity key, DER64-encoded. */ - char *recommended_versions; - char digest[DIGEST_LEN]; - char published[ISO_TIME_LEN+1]; - char *buf = NULL; - size_t buf_len; - size_t identity_pkey_len; - time_t now = time(NULL); - - tor_assert(dir_out); - *dir_out = NULL; - - if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey, - &identity_pkey_len)<0) { - log_warn(LD_BUG,"write identity_pkey to string failed!"); - return -1; - } - - recommended_versions = - format_versions_list(get_options()->RecommendedVersions); - - format_iso_time(published, now); - - buf_len = 2048+strlen(recommended_versions); - - buf = tor_malloc(buf_len); - /* We'll be comparing against buf_len throughout the rest of the - function, though strictly speaking we shouldn't be able to exceed - it. This is C, after all, so we may as well check for buffer - overruns.*/ - - tor_snprintf(buf, buf_len, - "signed-directory\n" - "published %s\n" - "recommended-software %s\n" - "router-status %s\n" - "dir-signing-key\n%s\n", - published, recommended_versions, "", - identity_pkey); - - tor_free(recommended_versions); - tor_free(identity_pkey); - - cp = buf + strlen(buf); - *cp = '\0'; - - /* These multiple strlcat calls are inefficient, but dwarfed by the RSA - signature. */ - if (strlcat(buf, "directory-signature ", buf_len) >= buf_len) - goto truncated; - if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len) - goto truncated; - if (strlcat(buf, "\n", buf_len) >= buf_len) - goto truncated; - - if (router_get_dir_hash(buf,digest)) { - log_warn(LD_BUG,"couldn't compute digest"); - tor_free(buf); - return -1; - } - note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(buf,buf_len,digest,DIGEST_LEN, - private_key)<0) { - tor_free(buf); - return -1; - } - - *dir_out = buf; - return 0; - truncated: - log_warn(LD_BUG,"tried to exceed string length."); - tor_free(buf); - return -1; -} - /********************************************************************/ /* A set of functions to answer questions about how we'd like to behave @@ -1090,7 +1033,8 @@ directory_fetches_from_authorities(const or_options_t *options) return 1; if (options->BridgeRelay == 1) return 0; - if (server_mode(options) && router_pick_published_address(options, &addr)<0) + if (server_mode(options) && + router_pick_published_address(options, &addr, 1) < 0) return 1; /* we don't know our IP address; ask an authority. */ refuseunknown = ! router_my_exit_policy_is_reject_star() && should_refuse_unknown_exits(options); @@ -1329,7 +1273,7 @@ dirserv_thinks_router_is_unreliable(time_t now, { if (need_uptime) { if (!enough_mtbf_info) { - /* XXX024 Once most authorities are on v3, we should change the rule from + /* XXXX We should change the rule from * "use uptime if we don't have mtbf data" to "don't advertise Stable on * v3 if we don't have enough mtbf data." Or maybe not, since if we ever * hit a point where we need to reset a lot of authorities at once, @@ -1871,6 +1815,7 @@ version_from_platform(const char *platform) */ char * routerstatus_format_entry(const routerstatus_t *rs, const char *version, + const char *protocols, routerstatus_format_type_t format, const vote_routerstatus_t *vrs) { @@ -1934,6 +1879,9 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) { smartlist_add_asprintf(chunks, "v %s\n", version); } + if (protocols) { + smartlist_add_asprintf(chunks, "pr %s\n", protocols); + } if (format != NS_V2) { const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); @@ -2152,8 +2100,8 @@ routers_make_ed_keys_unique(smartlist_t *routers) const time_t ri2_pub = ri2->cache_info.published_on; if (ri2_pub < ri_pub || (ri2_pub == ri_pub && - memcmp(ri->cache_info.signed_descriptor_digest, - ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) { + fast_memcmp(ri->cache_info.signed_descriptor_digest, + ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) { digest256map_set(by_ed_key, pk, ri); ri2->omit_from_vote = 1; } else { @@ -2206,7 +2154,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_valid = node->is_valid; - if (node->is_fast && + if (node->is_fast && node->is_stable && ((options->AuthDirGuardBWGuarantee && routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) || routerbw_kb >= MIN(guard_bandwidth_including_exits_kb, @@ -2365,7 +2313,8 @@ guardfraction_file_parse_guard_line(const char *guard_line, inputs_tmp = smartlist_get(sl, 0); if (strlen(inputs_tmp) != HEX_DIGEST_LEN || - base16_decode(guard_id, DIGEST_LEN, inputs_tmp, HEX_DIGEST_LEN)) { + base16_decode(guard_id, DIGEST_LEN, + inputs_tmp, HEX_DIGEST_LEN) != DIGEST_LEN) { tor_asprintf(err_msg, "bad digest '%s'", inputs_tmp); goto done; } @@ -2669,7 +2618,8 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) cp+=strlen("node_id=$"); if (strlen(cp) != HEX_DIGEST_LEN || - base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN)) { + base16_decode(out->node_id, DIGEST_LEN, + cp, HEX_DIGEST_LEN) != DIGEST_LEN) { log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s", escaped(orig_line)); tor_free(line); @@ -2910,6 +2860,12 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, rs->is_flagged_running = 0; vrs->version = version_from_platform(ri->platform); + if (ri->protocol_list) { + vrs->protocols = tor_strdup(ri->protocol_list); + } else { + vrs->protocols = tor_strdup( + protover_compute_for_old_tor(vrs->version)); + } vrs->microdesc = dirvote_format_all_microdesc_vote_lines(ri, now, microdescriptors); @@ -2982,6 +2938,31 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, v3_out->client_versions = client_versions; v3_out->server_versions = server_versions; + + /* These are hardwired, to avoid disaster. */ + v3_out->recommended_relay_protocols = + tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " + "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2"); + v3_out->recommended_client_protocols = + tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " + "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2"); + v3_out->required_client_protocols = + tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " + "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2"); + v3_out->required_relay_protocols = + tor_strdup("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " + "Link=3-4 LinkAuth=1 Microdesc=1 Relay=1-2"); + + /* We are not allowed to vote to require anything we don't have. */ + tor_assert(protover_all_supported(v3_out->required_relay_protocols, NULL)); + tor_assert(protover_all_supported(v3_out->required_client_protocols, NULL)); + + /* We should not recommend anything we don't have. */ + tor_assert_nonfatal(protover_all_supported( + v3_out->recommended_relay_protocols, NULL)); + tor_assert_nonfatal(protover_all_supported( + v3_out->recommended_client_protocols, NULL)); + v3_out->package_lines = smartlist_new(); { config_line_t *cl; @@ -3340,7 +3321,7 @@ lookup_cached_dir_by_fp(const char *fp) d = strmap_get(cached_consensuses, "ns"); } else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses && (d = strmap_get(cached_consensuses, fp))) { - /* this here interface is a nasty hack XXXX024 */; + /* this here interface is a nasty hack XXXX */; } return d; } |