Commit e73fb2f1 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

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
parent 4de4f53a
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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.
+5 −3
Original line number Diff line number Diff line
@@ -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.");
+2 −1
Original line number Diff line number Diff line
@@ -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);
+85 −12
Original line number Diff line number Diff line
@@ -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)) {
  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");
  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) {