Commit 6b46c6a1 authored by Andrea Shepard's avatar Andrea Shepard
Browse files

When downloading certificates, distinguish requesting by identity digest from...

When downloading certificates, distinguish requesting by identity digest from requesting by ID digest, signing key pair; fixes bug 5595
parent f691e9f5
Loading
Loading
Loading
Loading

changes/bug5595

0 → 100644
+8 −0
Original line number Diff line number Diff line
  o Critical bugfixes:
    - Distinguish downloading an authority certificate by identity digest from
      downloading one by identity digest/signing key digest pair; formerly we
      always request them only by identity digest and get the newest one even
      when we wanted one with a different signing key.  Then we would complain
      about being given a certificate we already had, and never get the one we
      really wanted.  Now we use the "fp-sk/" resource as well as the "fp/"
      resource to request the one we want.  Fixes bug 5595.
+55 −14
Original line number Diff line number Diff line
@@ -809,13 +809,34 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
  if (!conn->requested_resource)
    return;
  failed = smartlist_new();
  /*
   * We have two cases download by fingerprint (resource starts
   * with "fp/") or download by fingerprint/signing key pair
   * (resource starts with "fp-sk/").
   */
  if (!strcmpstart(conn->requested_resource, "fp/")) {
    /* Download by fingerprint case */
    dir_split_resource_into_fingerprints(conn->requested_resource + 3,
                                         failed, NULL, DSR_HEX);
  SMARTLIST_FOREACH(failed, char *, cp,
  {
    authority_cert_dl_failed(cp, status);
    SMARTLIST_FOREACH_BEGIN(failed, char *, cp) {
      /* Null signing key digest indicates download by fp only */
      authority_cert_dl_failed(cp, NULL, status);
      tor_free(cp);
  });
    } SMARTLIST_FOREACH_END(cp);
  } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
    /* Download by (fp,sk) pairs */
    dir_split_resource_into_fingerprint_pairs(conn->requested_resource + 5,
                                              failed);
    SMARTLIST_FOREACH_BEGIN(failed, fp_pair_t *, cp) {
      authority_cert_dl_failed(cp->first, cp->second, status);
      tor_free(cp);
    } SMARTLIST_FOREACH_END(cp);
  } else {
    log_warn(LD_DIR,
             "Don't know what to do with failure for cert fetch %s",
             conn->requested_resource);
  }

  smartlist_free(failed);

  update_certificate_downloads(time(NULL));
@@ -1589,6 +1610,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
                       conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
  int was_compressed=0;
  time_t now = time(NULL);
  int src_code;

  switch (connection_fetch_from_buf_http(TO_CONN(conn),
                              &headers, MAX_HEADERS_SIZE,
@@ -1857,7 +1879,19 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
    }
    log_info(LD_DIR,"Received authority certificates (size %d) from server "
             "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
    if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
    /*
     * Tell trusted_dirs_load_certs_from_string() whether it was by fp
     * or fp-sk pair.
     */
    src_code = -1;
    if (!strcmpstart(conn->requested_resource, "fp/")) {
      src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST;
    } else if (!strcmpstart(conn->requested_resource, "fp-sk/")) {
      src_code = TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST;
    }

    if (src_code != -1) {
      if (trusted_dirs_load_certs_from_string(body, src_code, 1)<0) {
        log_warn(LD_DIR, "Unable to parse fetched certificates");
        /* if we fetched more than one and only some failed, the successful
         * ones got flushed to disk so it's safe to call this on them */
@@ -1866,6 +1900,13 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
        directory_info_has_arrived(now, 0);
        log_info(LD_DIR, "Successfully loaded certificates from fetch.");
      }
    } else {
      log_warn(LD_DIR,
               "Couldn't figure out what to do with fetched certificates for "
               "unknown resource %s",
               conn->requested_resource);
      connection_dir_download_cert_failed(conn, status_code);
    }
  }
  if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
    const char *msg;
+1 −1
Original line number Diff line number Diff line
@@ -2947,7 +2947,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
    /* Hey, it's a new cert! */
    trusted_dirs_load_certs_from_string(
                               vote->cert->cache_info.signed_descriptor_body,
                               0 /* from_store */, 1 /*flush*/);
                               TRUSTED_DIRS_CERTS_SRC_FROM_VOTE, 1 /*flush*/);
    if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
                                       vote->cert->signing_key_digest)) {
      log_warn(LD_BUG, "We added a cert, but still couldn't find it.");
+2 −1
Original line number Diff line number Diff line
@@ -758,7 +758,8 @@ init_keys(void)
  if (cert) { /* add my own cert to the list of known certs */
    log_info(LD_DIR, "adding my own v3 cert");
    if (trusted_dirs_load_certs_from_string(
                      cert->cache_info.signed_descriptor_body, 0, 0)<0) {
                      cert->cache_info.signed_descriptor_body,
                      TRUSTED_DIRS_CERTS_SRC_SELF, 0)<0) {
      log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing.");
      return -1;
    }
+354 −73

File changed.

Preview size limit exceeded, changes collapsed.

Loading