diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-05-22 18:52:32 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-05-22 18:52:32 +0000 |
commit | 38300735cdd301ac8491c7a1368acb72fe2c3ee7 (patch) | |
tree | 3603b000ddd2d32439184e190915a5fd50544a24 /src | |
parent | 9e0acc0c11877d4df2db0b1fda0b998c5e9231bf (diff) | |
download | tor-38300735cdd301ac8491c7a1368acb72fe2c3ee7.tar tor-38300735cdd301ac8491c7a1368acb72fe2c3ee7.tar.gz |
r12902@catbus: nickm | 2007-05-22 14:52:29 -0400
First draft of code to generate votes. needs testing. does not yet upload or serve votes. Shares most of its code with the old generate_v2_networkstatus.
svn:r10295
Diffstat (limited to 'src')
-rw-r--r-- | src/or/dirserv.c | 178 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/router.c | 14 | ||||
-rw-r--r-- | src/or/routerparse.c | 34 |
4 files changed, 180 insertions, 49 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 77561c837..a0fad00b6 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1414,6 +1414,10 @@ dirserv_get_runningrouters(const char **rr, int compress) /** For authoritative directories: the current (v2) network status. */ static cached_dir_t *the_v2_networkstatus = NULL; +/** For authoritative directories: out most recent vote for the (v3) network + * status */ +static cached_dir_t *the_v3_networkstatus_vote = 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 @@ -1602,7 +1606,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, ipaddr, (int)rs->or_port, (int)rs->dir_port, - + /* These must stay in alphabetical order. */ f_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", @@ -1641,11 +1645,21 @@ routerstatus_format_entry(char *buf, size_t buf_len, return 0; } +/** DOCDOC */ +static int +_compare_routerinfo_by_id_digest(const void **a, const void **b) +{ + routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; + return memcmp(first->cache_info.identity_digest, + second->cache_info.identity_digest, + DIGEST_LEN); +} + /** For v2 authoritative directories only: replace the contents of * <b>the_v2_networkstatus</b> with a newly generated network status - * object. */ + * object. DOCDOC v2*/ static cached_dir_t * -generate_v2_networkstatus(void) +generate_networkstatus_opinion(int v2) { /** Longest status flag name that we generate. */ #define LONGEST_STATUS_FLAG_NAME_LEN 9 @@ -1671,7 +1685,7 @@ generate_v2_networkstatus(void) char digest[DIGEST_LEN]; struct in_addr in; uint32_t addr; - crypto_pk_env_t *private_key = get_identity_key(); + crypto_pk_env_t *private_key; routerlist_t *rl = router_get_routerlist(); time_t now = time(NULL); time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; @@ -1680,6 +1694,20 @@ generate_v2_networkstatus(void) int listbadexits = options->AuthDirListBadExits; int exits_can_be_guards; const char *contact; + authority_cert_t *cert = NULL; + char *version_lines = NULL; + smartlist_t *routers = NULL; + + if (v2) { + private_key = get_identity_key(); + } else { + private_key = get_my_v3_authority_signing_key(); + cert = get_my_v3_authority_cert(); + if (!private_key || !cert) { + log_warn(LD_NET, "Didn't find key/certificate to generate v3 vote"); + goto done; + } + } if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); @@ -1699,29 +1727,47 @@ generate_v2_networkstatus(void) goto done; } - if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) { - log_err(LD_BUG, "Error computing fingerprint"); - goto done; + if (v2) { + if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) { + log_err(LD_BUG, "Error computing fingerprint"); + goto done; + } + } else { + base16_encode(fingerprint, sizeof(fingerprint), + cert->cache_info.identity_digest, DIGEST_LEN); } contact = get_options()->ContactInfo; if (!contact) contact = "(none)"; - len = 2048+strlen(client_versions)+strlen(server_versions); + if (versioning) { + size_t v_len = 32+strlen(client_versions)+strlen(server_versions); + version_lines = tor_malloc(v_len); + tor_snprintf(version_lines, v_len, + "client-versions %s\nserver-versions %s\n", + client_versions, server_versions); + } else { + version_lines = tor_strdup(""); + } + + len = 4096+strlen(client_versions)+strlen(server_versions); len += identity_pkey_len*2; len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); + if (!v2) { + len += cert->cache_info.signed_descriptor_len; + } status = tor_malloc(len); - tor_snprintf(status, len, + if (v2) { + tor_snprintf(status, len, "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\n" - "%s%s" /* client versions %s */ - "%s%s%s" /* \nserver versions %s \n */ + "%s" /* client version line, server version line. */ "dir-signing-key\n%s\n", hostname, ipaddr, (int)options->DirPort, fingerprint, @@ -1730,14 +1776,38 @@ generate_v2_networkstatus(void) naming ? " Names" : "", listbadexits ? " BadExits" : "", versioning ? " Versions" : "", - versioning ? "client-versions " : "", - versioning ? client_versions : "", - versioning ? "\nserver-versions " : "", - versioning ? server_versions : "", - versioning ? "\n" : "", + version_lines, identity_pkey); - outp = status + strlen(status); - endp = status + len; + outp = status + strlen(status); + endp = status + len; + } else { + tor_snprintf(status, len, + "network-status-version 3\n" + "vote-status vote\n" + "published %s\n" + "valid-after %s\n" + "valid-until %s\n" + "%s" /* versions */ + "known-flags Authority Exit Fast Guard Stable " + "Running Valid V2Dir%s%s\n" + "dir-source %s %s %s %s %d\n" + "contact %s\n", + published, + published, /* XXXX020 should be valid-after*/ + published, /* XXXX020 should be valid-until*/ + version_lines, + naming ? " Named" : "", + listbadexits ? " BadExit" : "", + options->Nickname, fingerprint, options->Address, + ipaddr, (int)options->DirPort, + contact); + outp = status + strlen(status); + endp = status + len; + tor_assert(outp + cert->cache_info.signed_descriptor_len < endp); + memcpy(outp, cert->cache_info.signed_descriptor_body, + cert->cache_info.signed_descriptor_len); + outp += cert->cache_info.signed_descriptor_len; + } /* precompute this part, since we need it to decide what "stable" * means. */ @@ -1751,7 +1821,11 @@ generate_v2_networkstatus(void) * total_exit_bandwidth is close to total_bandwidth/3. */ exits_can_be_guards = total_exit_bandwidth >= (total_bandwidth / 3); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { + routers = smartlist_create(); + smartlist_add_all(routers, rl->routers); + smartlist_sort(routers, _compare_routerinfo_by_id_digest); + + SMARTLIST_FOREACH(routers, routerinfo_t *, ri, { if (ri->cache_info.published_on >= cutoff) { /* Already set by compute_performance_thresholds. */ int f_exit = ri->is_exit; @@ -1808,15 +1882,35 @@ generate_v2_networkstatus(void) } }); - if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", - get_options()->Nickname)<0) { - log_warn(LD_BUG, "Unable to write signature line."); - goto done; - } - - if (router_get_networkstatus_v2_hash(status, digest)<0) { - log_warn(LD_BUG, "Unable to hash network status"); - goto done; + if (v2) { + if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", + get_options()->Nickname)<0) { + log_warn(LD_BUG, "Unable to write signature line."); + goto done; + } + if (router_get_networkstatus_v2_hash(status, digest)<0) { + log_warn(LD_BUG, "Unable to hash network status"); + goto done; + } + outp += strlen(outp); + } else { + char hex_digest[HEX_DIGEST_LEN+1]; + if (tor_snprintf(outp, endp-outp, "directory-signature %s ", + fingerprint)<0) { + log_warn(LD_BUG, "Unable to start signature line."); + goto done; + } + if (router_get_networkstatus_v3_hash(status, digest)<0) { + log_warn(LD_BUG, "Unable to hash network status vote"); + goto done; + } + base16_encode(hex_digest, sizeof(hex_digest), digest, DIGEST_LEN); + outp += strlen(outp); + if (tor_snprintf(outp, endp-outp, "%s\n", hex_digest)<0) { + log_warn(LD_BUG, "Unable to end signature line."); + goto done; + } + outp += strlen(outp); } note_crypto_pk_op(SIGN_DIR); @@ -1825,20 +1919,28 @@ generate_v2_networkstatus(void) goto done; } - if (the_v2_networkstatus) - cached_dir_decref(the_v2_networkstatus); - the_v2_networkstatus = new_cached_dir(status, now); - status = NULL; /* So it doesn't get double-freed. */ - the_v2_networkstatus_is_dirty = 0; - router_set_networkstatus(the_v2_networkstatus->dir, - now, NS_GENERATED, NULL); - r = the_v2_networkstatus; + { + cached_dir_t **ns_ptr = + v2 ? &the_v2_networkstatus : &the_v3_networkstatus_vote; + if (*ns_ptr) + cached_dir_decref(*ns_ptr); + *ns_ptr = new_cached_dir(status, now); + status = NULL; /* So it doesn't get double-freed. */ + if (v2) + the_v2_networkstatus_is_dirty = 0; + router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL); + r = *ns_ptr; + } + done: tor_free(client_versions); tor_free(server_versions); + tor_free(version_lines); tor_free(status); tor_free(hostname); tor_free(identity_pkey); + if (routers) + smartlist_free(routers); return r; } @@ -1855,7 +1957,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, cached_v2_networkstatus = digestmap_new(); if (should_generate_v2_networkstatus()) - generate_v2_networkstatus(); + generate_networkstatus_opinion(1); if (!strcmp(key,"authority")) { if (authdir_mode_v2(get_options())) { @@ -1910,7 +2012,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result, SMARTLIST_FOREACH(fingerprints, const char *, fp, { if (router_digest_is_me(fp) && should_generate_v2_networkstatus()) - generate_v2_networkstatus(); + generate_networkstatus_opinion(1); cached = digestmap_get(cached_v2_networkstatus, fp); if (cached) { smartlist_add(result, cached); diff --git a/src/or/or.h b/src/or/or.h index 89dc21286..51c75edde 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2994,6 +2994,8 @@ time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); int identity_key_is_set(void); +authority_cert_t *get_my_v3_authority_cert(void); +crypto_pk_env_t *get_my_v3_authority_signing_key(void); void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); void rotate_onion_key(void); crypto_pk_env_t *init_key_from_file(const char *fname); @@ -3258,6 +3260,7 @@ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_get_runningrouters_hash(const char *s, char *digest); int router_get_networkstatus_v2_hash(const char *s, char *digest); +int router_get_networkstatus_v3_hash(const char *s, char *digest); int router_get_extrainfo_hash(const char *s, char *digest); int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, diff --git a/src/or/router.c b/src/or/router.c index 1cae710df..7b299958e 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -122,6 +122,20 @@ identity_key_is_set(void) return identitykey != NULL; } +/** DOCDOC */ +authority_cert_t * +get_my_v3_authority_cert(void) +{ + return authority_key_certificate; +} + +/** DOCDOC */ +crypto_pk_env_t * +get_my_v3_authority_signing_key(void) +{ + return authority_signing_key; +} + /** Replace the previous onion key with the current onion key, and generate * a new previous onion key. Immediately after calling this function, * the OR should: diff --git a/src/or/routerparse.c b/src/or/routerparse.c index b14e86807..ebc6bb129 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -352,7 +352,8 @@ static addr_policy_t *router_parse_addr_policy(directory_token_t *tok); static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok); static int router_get_hash_impl(const char *s, char *digest, - const char *start_str, const char *end_str); + const char *start_str, const char *end_str, + char end_char); static void token_free(directory_token_t *tok); static smartlist_t *find_all_exitpolicy(smartlist_t *s); static directory_token_t *find_first_by_keyword(smartlist_t *s, @@ -377,7 +378,7 @@ int router_get_dir_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest, - "signed-directory","\ndirectory-signature"); + "signed-directory","\ndirectory-signature",'\n'); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in @@ -387,7 +388,7 @@ int router_get_router_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest, - "router ","\nrouter-signature"); + "router ","\nrouter-signature", '\n'); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers @@ -397,7 +398,7 @@ int router_get_runningrouters_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest, - "network-status","\ndirectory-signature"); + "network-status","\ndirectory-signature", '\n'); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status @@ -406,7 +407,18 @@ int router_get_networkstatus_v2_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest, - "network-status-version","\ndirectory-signature"); + "network-status-version","\ndirectory-signature", + '\n'); +} + +/** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status + * string in <b>s</b>. Return 0 on success, -1 on failure. */ +int +router_get_networkstatus_v3_hash(const char *s, char *digest) +{ + return router_get_hash_impl(s,digest, + "network-status-version","\ndirectory-signature", + ' '); } /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo @@ -414,7 +426,7 @@ router_get_networkstatus_v2_hash(const char *s, char *digest) int router_get_extrainfo_hash(const char *s, char *digest) { - return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature"); + return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature",'\n'); } /** Helper: used to generate signatures for routers, directories and @@ -1317,7 +1329,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) goto err; } if (router_get_hash_impl(s, digest, "dir-key-certificate-version", - "\ndir-key-certification") < 0) + "\ndir-key-certification", '\n') < 0) goto err; tok = smartlist_get(tokens, 0); if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) { @@ -2215,8 +2227,8 @@ find_all_exitpolicy(smartlist_t *s) } /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first - * occurrence of <b>start_str</b> through the first newline after the first - * subsequent occurrence of <b>end_str</b>; store the 20-byte result in + * occurrence of <b>start_str</b> through the first instance of c after the + * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in * <b>digest</b>; return 0 on success. * * If no such substring exists, return -1. @@ -2224,7 +2236,7 @@ find_all_exitpolicy(smartlist_t *s) static int router_get_hash_impl(const char *s, char *digest, const char *start_str, - const char *end_str) + const char *end_str, char end_c) { char *start, *end; start = strstr(s, start_str); @@ -2243,7 +2255,7 @@ router_get_hash_impl(const char *s, char *digest, log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str); return -1; } - end = strchr(end+strlen(end_str), '\n'); + end = strchr(end+strlen(end_str), end_c); if (!end) { log_warn(LD_DIR,"couldn't find EOL"); return -1; |