diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/router.c | 131 | ||||
-rw-r--r-- | src/or/routerlist.c | 31 | ||||
-rw-r--r-- | src/or/routerparse.c | 2 | ||||
-rw-r--r-- | src/or/test.c | 1 |
5 files changed, 154 insertions, 15 deletions
diff --git a/src/or/or.h b/src/or/or.h index 5660d36a7..fabecde0a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2892,6 +2892,7 @@ void check_descriptor_ipaddress_changed(time_t now); void router_new_address_suggestion(const char *suggestion); int router_compare_to_my_exit_policy(edge_connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); +const char *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); int router_digest_is_me(const char *digest); int router_is_me(routerinfo_t *router); @@ -2900,6 +2901,8 @@ int router_pick_published_address(or_options_t *options, uint32_t *addr); int router_rebuild_descriptor(int force); int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); +int extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, + crypto_pk_env_t *ident_key); int is_legal_nickname(const char *s); int is_legal_nickname_or_hexdigest(const char *s); int is_legal_hexdigest(const char *s); @@ -3048,6 +3051,7 @@ void networkstatus_list_update_recent(time_t now); void router_reset_descriptor_download_failures(void); void router_reset_status_download_failures(void); int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2); +int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei); const char *esc_router_info(routerinfo_t *router); char *networkstatus_getinfo_helper_single(routerstatus_t *rs); diff --git a/src/or/router.c b/src/or/router.c index fc6c62e07..c7d3b4aac 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -710,6 +710,8 @@ router_is_clique_mode(routerinfo_t *router) /** My routerinfo. */ static routerinfo_t *desc_routerinfo = NULL; +/** DOCDOC */ +static extrainfo_t *desc_extrainfo = NULL; /** Since when has our descriptor been "clean"? 0 if we need to regenerate it * now. */ static time_t desc_clean_since = 0; @@ -812,6 +814,17 @@ router_get_my_descriptor(void) return body; } +/** DOCDOC */ +const char * +router_get_my_extrainfo(void) +{ + if (!server_mode(get_options())) + return NULL; + if (router_rebuild_descriptor(0)) + return NULL; + return desc_extrainfo->cache_info.signed_descriptor_body; +} + /** A list of nicknames that we've warned about including in our family * declaration verbatim rather than as digests. */ static smartlist_t *warned_nonexistent_family = NULL; @@ -839,11 +852,13 @@ router_pick_published_address(or_options_t *options, uint32_t *addr) /** If <b>force</b> is true, or our descriptor is out-of-date, rebuild * a fresh routerinfo and signed server descriptor for this OR. * Return 0 on success, -1 on temporary error. + * DOCDOC extrainfo. */ int router_rebuild_descriptor(int force) { routerinfo_t *ri; + extrainfo_t *ei; uint32_t addr; char platform[256]; int hibernating = we_are_hibernating(); @@ -946,6 +961,27 @@ router_rebuild_descriptor(int force) smartlist_free(family); } + + /* Now generate the extrainfo. */ + ei = tor_malloc_zero(sizeof(extrainfo_t)); + strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname)); + ei->cache_info.published_on = ri->cache_info.published_on; + memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, + DIGEST_LEN); + ei->cache_info.signed_descriptor_body = tor_malloc(8192); + if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192, + ei, get_identity_key()) < 0) { + log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); + return -1; + } + ei->cache_info.signed_descriptor_len = + strlen(ei->cache_info.signed_descriptor_body); + router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, + ei->cache_info.signed_descriptor_digest); + + /* Now finish the router descriptor. */ + memcpy(ri->extra_info_digest, ei->cache_info.signed_descriptor_digest, + DIGEST_LEN); ri->cache_info.signed_descriptor_body = tor_malloc(8192); if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192, ri, get_identity_key())<0) { @@ -954,13 +990,19 @@ router_rebuild_descriptor(int force) } ri->cache_info.signed_descriptor_len = strlen(ri->cache_info.signed_descriptor_body); + /* XXXX020 router_get_router_hash??? */ crypto_digest(ri->cache_info.signed_descriptor_digest, ri->cache_info.signed_descriptor_body, ri->cache_info.signed_descriptor_len); + tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei)); + if (desc_routerinfo) routerinfo_free(desc_routerinfo); desc_routerinfo = ri; + if (desc_extrainfo) + extrainfo_free(desc_extrainfo); + desc_extrainfo = ei; desc_clean_since = time(NULL); desc_needs_upload = 1; @@ -1161,17 +1203,13 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, char digest[DIGEST_LEN]; char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; + char extra_info_digest[HEX_DIGEST_LEN+1]; size_t onion_pkeylen, identity_pkeylen; size_t written; int result=0; addr_policy_t *tmpe; char *bandwidth_usage; char *family_line; -#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING - char *s_dup; - const char *cp; - routerinfo_t *ri_tmp; -#endif or_options_t *options = get_options(); /* Make sure the identity key matches the one in the routerinfo. */ @@ -1219,6 +1257,9 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, family_line = tor_strdup(""); } + base16_encode(extra_info_digest, sizeof(extra_info_digest), + router->extra_info_digest, DIGEST_LEN); + /* Generate the easy portion of the router descriptor. */ result = tor_snprintf(s, maxlen, "router %s %s %d 0 %d\n" @@ -1227,6 +1268,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, "opt fingerprint %s\n" "uptime %ld\n" "bandwidth %d %d %d\n" + "opt extra-info-digest %s\n" "onion-key\n%s" "signing-key\n%s" "%s%s%s", @@ -1241,6 +1283,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->bandwidthcapacity, + extra_info_digest, onion_pkey, identity_pkey, family_line, bandwidth_usage, we_are_hibernating() ? "opt hibernating 1\n" : ""); @@ -1319,21 +1362,78 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, s[written+1] = 0; #ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING - cp = s_dup = tor_strdup(s); - ri_tmp = router_parse_entry_from_string(cp, NULL, 1); - if (!ri_tmp) { - log_err(LD_BUG, - "We just generated a router descriptor we can't parse."); - log_err(LD_BUG, "Descriptor was: <<%s>>", s); - return -1; + { + char *s_dup; + const char *cp; + routerinfo_t *ri_tmp; + cp = s_dup = tor_strdup(s); + ri_tmp = router_parse_entry_from_string(cp, NULL, 1); + if (!ri_tmp) { + log_err(LD_BUG, + "We just generated a router descriptor we can't parse."); + log_err(LD_BUG, "Descriptor was: <<%s>>", s); + return -1; + } + tor_free(s_dup); + routerinfo_free(ri_tmp); } - tor_free(s_dup); - routerinfo_free(ri_tmp); #endif return written+1; } +/** DOCDOC */ +int +extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, + crypto_pk_env_t *ident_key) +{ + char identity[HEX_DIGEST_LEN+1]; + char published[ISO_TIME_LEN+1]; + char digest[DIGEST_LEN]; + char *bandwidth_usage; + int result; + size_t len; + + base16_encode(identity, sizeof(identity), + extrainfo->cache_info.identity_digest, DIGEST_LEN); + format_iso_time(published, extrainfo->cache_info.published_on); + bandwidth_usage = rep_hist_get_bandwidth_lines(); + + result = tor_snprintf(s, maxlen, + "extra-info %s %s\n" + "published %s\n%s" + "router-signature\n", + extrainfo->nickname, identity, + published, bandwidth_usage); + tor_free(bandwidth_usage); + if (result<0) + return -1; + len = strlen(s); + if (router_get_extrainfo_hash(s, digest)<0) + return -1; + if (router_append_dirobj_signature(s+len, maxlen-len, digest, ident_key)<0) + return -1; + +#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING + { + char *cp, *s_dup; + extrainfo_t *ei_tmp; + cp = s_dup = tor_strdup(s); + ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL); + if (!ei_tmp) { + log_err(LD_BUG, + "We just generated an extrainfo descriptor we can't parse."); + log_err(LD_BUG, "Descriptor was: <<%s>>", s); + return -1; + } + tor_free(s_dup); + extrainfo_free(ei_tmp); + } +#endif + + return strlen(s)+1; +} + /** Return true iff <b>s</b> is a legally valid server nickname. */ int is_legal_nickname(const char *s) @@ -1420,6 +1520,9 @@ router_free_all(void) tor_mutex_free(key_lock); if (desc_routerinfo) routerinfo_free(desc_routerinfo); + if (desc_extrainfo) + extrainfo_free(desc_extrainfo); + if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); smartlist_free(warned_nonexistent_family); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 1e9b87c8e..9b1f60e42 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -4422,6 +4422,37 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) return 1; } +/** DOCDOC */ +int +routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei) +{ + tor_assert(ri); + tor_assert(ei); + + if (strcmp(ri->nickname, ei->nickname) || + memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest, + DIGEST_LEN)) + return 1; /* different servers */ + + if (ei->pending_sig) { + char signed_digest[128]; + if (crypto_pk_public_checksig(ri->identity_pkey, signed_digest, + ei->pending_sig, 128) != 20 || + memcmp(signed_digest, ei->cache_info.signed_descriptor_digest, + DIGEST_LEN)) + return 1; /* Bad signature, or no match. */ + + tor_free(ei->pending_sig); + } + + if (ei->cache_info.published_on < ei->cache_info.published_on) + return 1; + else if (ei->cache_info.published_on > ei->cache_info.published_on) + return -1; + + return 0; +} + /** Generate networkstatus lines for a single routerstatus_t object, and * return the result in a newly allocated string. Used only by controller * interface (for now.) */ diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 2722eae7d..9398d14f0 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -835,7 +835,6 @@ router_parse_entry_from_string(const char *s, const char *end, router->cache_info.signed_descriptor_len = end-s; memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); - router->nickname = tor_strdup(tok->args[0]); if (!is_legal_nickname(router->nickname)) { log_warn(LD_DIR,"Router nickname is invalid"); @@ -1070,6 +1069,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s); extrainfo->cache_info.signed_descriptor_len = end-s; memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); + tor_assert(tok->n_args >= 2); if (!is_legal_nickname(tok->args[0])) { log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0])); diff --git a/src/or/test.c b/src/or/test.c index 0d6cfd270..6d2736555 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -1743,6 +1743,7 @@ test_dir_format(void) * uptime, that still wouldn't make it right, because the two * descriptors might be made on different seconds... hm. */ "bandwidth 1000 5000 10000\n" + "opt extra-info-digest 0000000000000000000000000000000000000000\n" "onion-key\n", sizeof(buf2)); strlcat(buf2, pk1_str, sizeof(buf2)); strlcat(buf2, "signing-key\n", sizeof(buf2)); |