diff options
author | Nick Mathewson <nickm@torproject.org> | 2008-05-12 02:14:01 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2008-05-12 02:14:01 +0000 |
commit | f3f6ecef48b019fe18fac371b64c3f3466ef3388 (patch) | |
tree | 29075075ca19e72f6e593c31ca0db4092ba5741b /src/or/dirvote.c | |
parent | b7a80920e26f53e354975a7252e3a1f33ef9192b (diff) | |
download | tor-f3f6ecef48b019fe18fac371b64c3f3466ef3388.tar.gz tor-f3f6ecef48b019fe18fac371b64c3f3466ef3388.zip |
r19690@catbus: nickm | 2008-05-11 22:13:31 -0400
Implement a proposal to let a directory authority migrate its identity key without ceasing to sign consensuses.
svn:r14584
Diffstat (limited to 'src/or/dirvote.c')
-rw-r--r-- | src/or/dirvote.c | 126 |
1 files changed, 100 insertions, 26 deletions
diff --git a/src/or/dirvote.c b/src/or/dirvote.c index e4afacc61d..683389341d 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -105,7 +105,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, tor_snprintf(status, len, "network-status-version 3\n" "vote-status vote\n" - "consensus-methods 1 2\n" + "consensus-methods 1 2 3\n" "published %s\n" "valid-after %s\n" "fresh-until %s\n" @@ -125,6 +125,14 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key, tor_free(flags); outp = status + strlen(status); endp = status + len; + + if (!tor_digest_is_zero(voter->legacy_id_digest)) { + char fpbuf[HEX_DIGEST_LEN+1]; + base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN); + tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf); + outp += strlen(outp); + } + tor_assert(outp + cert->cache_info.signed_descriptor_len < endp); memcpy(outp, cert->cache_info.signed_descriptor_body, cert->cache_info.signed_descriptor_len); @@ -207,6 +215,12 @@ get_voter(const networkstatus_t *vote) return smartlist_get(vote->voters, 0); } +typedef struct { + networkstatus_t *v; + const char *digest; + int is_legacy; +} dir_src_ent_t; + /** Helper for sorting networkstatus_t votes (not consensuses) by the * hash of their voters' identity digests. */ static int @@ -217,6 +231,19 @@ _compare_votes_by_authority_id(const void **_a, const void **_b) get_voter(b)->identity_digest, DIGEST_LEN); } +static int +_compare_dir_src_ents_by_authority_id(const void **_a, const void **_b) +{ + const dir_src_ent_t *a = *_a, *b = *_b; + const networkstatus_voter_info_t *a_v = get_voter(a->v), + *b_v = get_voter(b->v); + const char *a_id, *b_id; + a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest; + b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest; + + return memcmp(a_id, b_id, DIGEST_LEN); +} + /** Given a sorted list of strings <b>in</b>, add every member to <b>out</b> * that occurs more than <b>min</b> times. */ static void @@ -416,7 +443,7 @@ compute_consensus_method(smartlist_t *votes) static int consensus_method_is_supported(int method) { - return (method >= 1) && (method <= 2); + return (method >= 1) && (method <= 3); } /** Given a list of vote networkstatus_t in <b>votes</b>, our public @@ -581,33 +608,64 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Sort the votes. */ smartlist_sort(votes, _compare_votes_by_authority_id); /* Add the authority sections. */ - SMARTLIST_FOREACH(votes, networkstatus_t *, v, { - char buf[1024]; - struct in_addr in; - char ip[INET_NTOA_BUF_LEN]; - char fingerprint[HEX_DIGEST_LEN+1]; - char votedigest[HEX_DIGEST_LEN+1]; - networkstatus_voter_info_t *voter = get_voter(v); + smartlist_t *dir_sources = smartlist_create(); + SMARTLIST_FOREACH(votes, networkstatus_t *, v, + { + dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t)); + e->v = v; + e->digest = get_voter(v)->identity_digest; + e->is_legacy = 0; + smartlist_add(dir_sources, e); + if (consensus_method >= 3 && + !tor_digest_is_zero(get_voter(v)->legacy_id_digest)) { + dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t)); + e_legacy->v = v; + e_legacy->digest = get_voter(v)->legacy_id_digest; + e_legacy->is_legacy = 1; + smartlist_add(dir_sources, e); + } + }); + smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id); - in.s_addr = htonl(voter->addr); - tor_inet_ntoa(&in, ip, sizeof(ip)); - base16_encode(fingerprint, sizeof(fingerprint), voter->identity_digest, - DIGEST_LEN); - base16_encode(votedigest, sizeof(votedigest), voter->vote_digest, - DIGEST_LEN); + SMARTLIST_FOREACH(dir_sources, const dir_src_ent_t *, e, + { + char buf[1024]; + struct in_addr in; + char ip[INET_NTOA_BUF_LEN]; + char fingerprint[HEX_DIGEST_LEN+1]; + char votedigest[HEX_DIGEST_LEN+1]; + networkstatus_t *v = e->v; + networkstatus_voter_info_t *voter = get_voter(v); + + if (e->is_legacy) + tor_assert(consensus_method >= 2); + + in.s_addr = htonl(voter->addr); + tor_inet_ntoa(&in, ip, sizeof(ip)); + base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN); + base16_encode(votedigest, sizeof(votedigest), voter->vote_digest, + DIGEST_LEN); - tor_snprintf(buf, sizeof(buf), - "dir-source %s %s %s %s %d %d\n" - "contact %s\n" - "vote-digest %s\n", - voter->nickname, fingerprint, voter->address, ip, - voter->dir_port, - voter->or_port, - voter->contact, - votedigest); - smartlist_add(chunks, tor_strdup(buf)); - }); + tor_snprintf(buf, sizeof(buf), + "dir-source %s%s %s %s %s %d %d\n", + voter->nickname, e->is_legacy ? "-legacy" : "", + fingerprint, voter->address, ip, + voter->dir_port, + voter->or_port); + smartlist_add(chunks, tor_strdup(buf)); + if (! e->is_legacy) { + tor_snprintf(buf, sizeof(buf), + "contact %s\n" + "vote-digest %s\n", + voter->contact, + votedigest); + smartlist_add(chunks, tor_strdup(buf)); + } + }); + SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e)); + smartlist_free(dir_sources); + } /* Add the actual router entries. */ { @@ -904,6 +962,22 @@ networkstatus_compute_consensus(smartlist_t *votes, return NULL; /* This leaks, but it should never happen. */ } smartlist_add(chunks, tor_strdup(buf)); + + if (get_options()->V3AuthUseLegacyKey && consensus_method >= 3) { + crypto_pk_env_t *legacy_key = get_my_v3_legacy_signing_key(); + authority_cert_t *legacy_cert = get_my_v3_legacy_cert(); + smartlist_add(chunks, tor_strdup("directory-signature ")); + crypto_pk_get_fingerprint(legacy_cert->identity_key, fingerprint, 0); + crypto_pk_get_fingerprint(legacy_key, signing_key_fingerprint, 0); + tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint, + signing_key_fingerprint); + if (router_append_dirobj_signature(buf, sizeof(buf), digest, + signing_key)) { + log_warn(LD_BUG, "Couldn't sign consensus networkstatus."); + return NULL; /* This leaks, but it should never happen. */ + } + smartlist_add(chunks, tor_strdup(buf)); + } } result = smartlist_join_strings(chunks, "", 0, NULL); |