Improves the fix to #18963.
o Minor bugfix (bootstrap):
- - Remember the directory we fetched the consensus from, and use
- it to fetch authority certificates as well.
+ - Remember the directory we fetched the consensus or previous
+ certificates from, and use it to fetch future authority
+ certificates.
Resolves ticket 18963; fix on #4483 in 0.2.8.1-alpha.
}
if (src_code != -1) {
- if (trusted_dirs_load_certs_from_string(body, src_code, 1)<0) {
+ if (trusted_dirs_load_certs_from_string(body, src_code, 1,
+ conn->identity_digest)<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 */
/* Hey, it's a new cert! */
trusted_dirs_load_certs_from_string(
vote->cert->cache_info.signed_descriptor_body,
- TRUSTED_DIRS_CERTS_SRC_FROM_VOTE, 1 /*flush*/);
+ TRUSTED_DIRS_CERTS_SRC_FROM_VOTE, 1 /*flush*/,
+ NULL);
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.");
* consensus, even if it comes from many days in the past.
*
* If source_dir is non-NULL, it's the identity digest for a directory that
- * we've just successfully retrieved a consensus from, so try it first to
- * fetch any missing certificates.
+ * we've just successfully retrieved a consensus or certificates from, so try
+ * it first to fetch any missing certificates.
*
* Return 0 on success, <0 on failure. On failure, caller should increment
* the failure count as appropriate.
}
/** Called when we have gotten more certificates: see whether we can
- * now verify a pending consensus. */
+ * now verify a pending consensus.
+ *
+ * If source_dir is non-NULL, it's the identity digest for a directory that
+ * we've just successfully retrieved certificates from, so try it first to
+ * fetch any missing certificates.
+ */
void
-networkstatus_note_certs_arrived(void)
+networkstatus_note_certs_arrived(const char *source_dir)
{
int i;
for (i=0; i<N_CONSENSUS_FLAVORS; ++i) {
waiting_body,
networkstatus_get_flavor_name(i),
NSSET_WAS_WAITING_FOR_CERTS,
- NULL)) {
+ source_dir)) {
tor_free(waiting_body);
}
}
const char *flavor,
unsigned flags,
const char *source_dir);
-void networkstatus_note_certs_arrived(void);
+void networkstatus_note_certs_arrived(const char *source_dir);
void routers_update_all_from_networkstatus(time_t now, int dir_version);
void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures);
log_info(LD_DIR, "adding my own v3 cert");
if (trusted_dirs_load_certs_from_string(
cert->cache_info.signed_descriptor_body,
- TRUSTED_DIRS_CERTS_SRC_SELF, 0)<0) {
+ TRUSTED_DIRS_CERTS_SRC_SELF, 0,
+ NULL)<0) {
log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing.");
return -1;
}
return 0;
r = trusted_dirs_load_certs_from_string(
contents,
- TRUSTED_DIRS_CERTS_SRC_FROM_STORE, 1);
+ TRUSTED_DIRS_CERTS_SRC_FROM_STORE, 1, NULL);
tor_free(contents);
return r;
}
* or TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_SK_DIGEST. If <b>flush</b> is true, we
* need to flush any changed certificates to disk now. Return 0 on success,
* -1 if any certs fail to parse.
+ *
+ * If source_dir is non-NULL, it's the identity digest for a directory that
+ * we've just successfully retrieved certificates from, so try it first to
+ * fetch any missing certificates.
*/
int
trusted_dirs_load_certs_from_string(const char *contents, int source,
- int flush)
+ int flush, const char *source_dir)
{
dir_server_t *ds;
const char *s, *eos;
int failure_code = 0;
int from_store = (source == TRUSTED_DIRS_CERTS_SRC_FROM_STORE);
+ int added_trusted_cert = 0;
for (s = contents; *s; s = eos) {
authority_cert_t *cert = authority_cert_parse_from_string(s, &eos);
}
if (ds) {
+ added_trusted_cert = 1;
log_info(LD_DIR, "Adding %s certificate for directory authority %s with "
"signing key %s", from_store ? "cached" : "downloaded",
ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN));
trusted_dirs_flush_certs_to_disk();
/* call this even if failure_code is <0, since some certs might have
- * succeeded. */
- networkstatus_note_certs_arrived();
+ * succeeded, but only pass source_dir if there were no failures,
+ * and at least one more authority certificate was added to the store.
+ * This avoids retrying a directory that's serving bad or entirely duplicate
+ * certificates. */
+ if (failure_code == 0 && added_trusted_cert) {
+ networkstatus_note_certs_arrived(source_dir);
+ } else {
+ networkstatus_note_certs_arrived(NULL);
+ }
return failure_code;
}
* already have.
*
* If dir_hint is non-NULL, it's the identity digest for a directory that
- * we've just successfully retrieved a consensus from, so try it first to
- * fetch any missing certificates.
+ * we've just successfully retrieved a consensus or certificates from, so try
+ * it first to fetch any missing certificates.
**/
void
authority_certs_fetch_missing(networkstatus_t *status, time_t now,
#define TRUSTED_DIRS_CERTS_SRC_FROM_VOTE 4
int trusted_dirs_load_certs_from_string(const char *contents, int source,
- int flush);
+ int flush, const char *source_dir);
void trusted_dirs_flush_certs_to_disk(void);
authority_cert_t *authority_cert_get_newest_by_id(const char *id_digest);
authority_cert_t *authority_cert_get_by_sk_digest(const char *sk_digest);
base16_decode(ds->v3_identity_digest, DIGEST_LEN,
TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
char req[71];
routerlist_free_all();
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
char req[71];
dir_server_add(ds);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
conn = dir_connection_new(tor_addr_family(&MOCK_TOR_ADDR));
dir_server_add(ds);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
MOCK(get_options, mock_get_options);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
base16_decode(ds->v3_identity_digest, DIGEST_LEN,
TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
init_mock_options();
mock_options->AuthoritativeDir = 1;
TEST_CERT_IDENT_KEY, HEX_DIGEST_LEN);
tt_int_op(0, OP_EQ, trusted_dirs_load_certs_from_string(TEST_CERTIFICATE,
- TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1));
+ TRUSTED_DIRS_CERTS_SRC_DL_BY_ID_DIGEST, 1, NULL));
init_mock_options();
mock_options->AuthoritativeDir = 1;