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
This commit is contained in:
Nick Mathewson 2007-09-11 20:17:28 +00:00
parent 4de4f53abd
commit e73fb2f102
4 changed files with 96 additions and 20 deletions

View File

@ -53,12 +53,12 @@ Things we'd like to do in 0.2.0.x:
o Download as needed.
o Code to download
. Code to retry download.
. Code to generate consensus from a list of votes
* Detect whether votes are really all for the same period.
o Code to generate consensus from a list of votes
o Detect whether votes are really all for the same period.
. Push/pull documents as appropriate.
- Pull votes and signatures if we don't get them.
- Cache votes and signatures on disk.
- Code to keep consensus docs in limbo if they don't have
o Code to keep consensus docs in limbo if they don't have
have enough signatures.
o Have clients know which authorities are v3 authorities, and what
their keys are.

View File

@ -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.");

View File

@ -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);

View File

@ -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 (networkstatus_set_current_consensus(s, 1)) {
log_warn(LD_FS, "Couldn't load consensus networkstatus from \"%s\"",
filename);
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);
}
tor_free(s);
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);
}
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) {