diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-09-11 20:17:28 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-09-11 20:17:28 +0000 |
commit | e73fb2f102c714b96436d594a298566c6e8393f6 (patch) | |
tree | 058bc89abadea3586fa965b689979a553392c191 /src | |
parent | 4de4f53abd0d5dc5b39e4756b777e71ea846992d (diff) | |
download | tor-e73fb2f102c714b96436d594a298566c6e8393f6.tar.gz tor-e73fb2f102c714b96436d594a298566c6e8393f6.zip |
r15049@catbus: nickm | 2007-09-11 16:05:50 -0400
When we get a consensus for which we are missing the right certificates, keep it around pending more certificates; do not just drop it.
svn:r11430
Diffstat (limited to 'src')
-rw-r--r-- | src/or/dirvote.c | 8 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 97 |
3 files changed, 92 insertions, 16 deletions
diff --git a/src/or/dirvote.c b/src/or/dirvote.c index c39cff866a..634f7f9419 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -735,7 +735,7 @@ networkstatus_check_voter_signature(networkstatus_vote_t *consensus, /** Given a v3 networkstatus consensus in <b>consensus</b>, check every * as-yet-unchecked signature on <b>consensus. Return 0 if there are enough * good signatures from recognized authorities on it, and -1 otherwise. - * DOCDOC warn. */ + * DOCDOC warn. DOCDOC -2 rerturn. */ int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus, int warn) @@ -832,8 +832,10 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus, if (n_good >= n_required) return 0; - else + else if (n_good + n_missing_key >= n_required) return -1; + else + return -2; } /** Given a consensus vote <b>target</b> and a list of @@ -1681,7 +1683,7 @@ dirvote_publish_consensus(void) return -1; } - if (networkstatus_set_current_consensus(pending_consensus_body, 0)) + if (networkstatus_set_current_consensus(pending_consensus_body, 0, 0)) log_warn(LD_DIR, "Error publishing consensus"); else log_warn(LD_DIR, "Consensus published."); diff --git a/src/or/or.h b/src/or/or.h index 24a3f9d4be..3a30e36254 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3550,7 +3550,8 @@ local_routerstatus_t *router_get_combined_status_by_descriptor_digest( int router_reload_consensus_networkstatus(void); networkstatus_vote_t *networkstatus_get_latest_consensus(void); networkstatus_vote_t *networkstatus_get_live_consensus(time_t now); -int networkstatus_set_current_consensus(const char *consensus, int from_cache); +int networkstatus_set_current_consensus(const char *consensus, int from_cache, + int was_waiting_for_certs); //routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest); int should_delay_dir_fetches(or_options_t *options); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index d8f266ec68..33ce081173 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -65,9 +65,14 @@ static routerlist_t *routerlist = NULL; * about. This list is kept sorted by published_on. */ static smartlist_t *networkstatus_list = NULL; -/** Most recently received v3 consensus network status. */ +/** Most recently received and validated v3 consensus network status. */ static networkstatus_vote_t *current_consensus = NULL; +/** A v3 consensus networkstatus that we've received, but which we don't + * have enough certificates to be happy about. */ +static networkstatus_vote_t *consensus_waiting_for_certs = NULL; +static char *consensus_waiting_for_certs_body = NULL; + /** Global list of local_routerstatus_t for each router, known or unknown. * Kept sorted by digest. */ static smartlist_t *routerstatus_list = NULL; @@ -184,14 +189,26 @@ router_reload_consensus_networkstatus(void) tor_snprintf(filename,sizeof(filename),"%s"PATH_SEPARATOR"cached-consensus", get_options()->DataDirectory); s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); - if (!s) - return 0; + if (s) { + if (networkstatus_set_current_consensus(s, 1, 0)) { + log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", + filename); + } + tor_free(s); + } - if (networkstatus_set_current_consensus(s, 1)) { - log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", - filename); + tor_snprintf(filename,sizeof(filename), + "%s"PATH_SEPARATOR"unverified-consensus", + get_options()->DataDirectory); + s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL); + if (s) { + if (networkstatus_set_current_consensus(s, 1, 1)) { + log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"", + filename); + } + tor_free(s); } - tor_free(s); + return 0; } @@ -266,6 +283,16 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store) trusted_dirs_flush_certs_to_disk(); + if (consensus_waiting_for_certs) { + if (!networkstatus_check_consensus_signature( + consensus_waiting_for_certs, 0)) { + if (!networkstatus_set_current_consensus( + consensus_waiting_for_certs_body, 0, 1)) { + tor_free(consensus_waiting_for_certs_body); + } + } + } + return 0; } @@ -2501,6 +2528,15 @@ routerlist_free_all(void) if (named_server_map) { strmap_free(named_server_map, _tor_free); } + if (current_consensus) { + networkstatus_vote_free(current_consensus); + current_consensus = NULL; + } + if (consensus_waiting_for_certs) { + networkstatus_vote_free(current_consensus); + current_consensus = NULL; + } + tor_free(consensus_waiting_for_certs_body); } /** Free all storage held by the routerstatus object <b>rs</b>. */ @@ -4027,9 +4063,11 @@ networkstatus_get_live_consensus(time_t now) /** DOCDOC */ int -networkstatus_set_current_consensus(const char *consensus, int from_cache) +networkstatus_set_current_consensus(const char *consensus, int from_cache, + int was_waiting_for_certs) { networkstatus_vote_t *c; + int r; /* Make sure it's parseable. */ c = networkstatus_parse_vote_from_string(consensus, 0); if (!c) { @@ -4038,15 +4076,50 @@ networkstatus_set_current_consensus(const char *consensus, int from_cache) } /* Make sure it's signed enough. */ - if (networkstatus_check_consensus_signature(c, 1)<0) { - log_warn(LD_DIR, "Not enough good signatures on networkstatus consensus"); - networkstatus_vote_free(c); - return -1; + if ((r=networkstatus_check_consensus_signature(c, 1))<0) { + if (r == -1 && !was_waiting_for_certs) { + /* Okay, so it _might_ be signed enough if we get more certificates. */ + if (!was_waiting_for_certs) + log_notice(LD_DIR, "Not enough certificates to check networkstatus " + "consensus"); + if (!current_consensus || + c->valid_after > current_consensus->valid_after) { + if (consensus_waiting_for_certs) + networkstatus_vote_free(consensus_waiting_for_certs); + tor_free(consensus_waiting_for_certs_body); + consensus_waiting_for_certs = c; + consensus_waiting_for_certs_body = tor_strdup(consensus); + if (!from_cache) { + or_options_t *options = get_options(); + char filename[512]; + tor_snprintf(filename, sizeof(filename), + "%s"PATH_SEPARATOR"unverified-consensus", + options->DataDirectory); + write_str_to_file(filename, consensus, 0); + } + /* XXXX020 trigger the certificate download. */ + } + return -1; + } else { + if (!was_waiting_for_certs) + log_warn(LD_DIR, "Not enough good signatures on networkstatus " + "consensus"); + networkstatus_vote_free(c); + return -1; + } } if (current_consensus) networkstatus_vote_free(current_consensus); + if (consensus_waiting_for_certs && + consensus_waiting_for_certs->valid_after <= c->valid_after) { + networkstatus_vote_free(consensus_waiting_for_certs); + consensus_waiting_for_certs = NULL; + if (consensus != consensus_waiting_for_certs_body) + tor_free(consensus_waiting_for_certs_body); + } + current_consensus = c; if (!from_cache) { |