aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-09-11 20:17:28 +0000
committerNick Mathewson <nickm@torproject.org>2007-09-11 20:17:28 +0000
commite73fb2f102c714b96436d594a298566c6e8393f6 (patch)
tree058bc89abadea3586fa965b689979a553392c191 /src
parent4de4f53abd0d5dc5b39e4756b777e71ea846992d (diff)
downloadtor-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.c8
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/routerlist.c97
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) {