diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-07-26 20:49:04 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-07-26 20:49:04 +0000 |
commit | 6c4864f35100b0774269a368a69266335ca8ca11 (patch) | |
tree | f4a00d6742c46b4ef6e1ef4378fb07d0bb2cfc91 | |
parent | fb2f3c035b503ed9de3ad9612b12481ee162f718 (diff) | |
download | tor-6c4864f35100b0774269a368a69266335ca8ca11.tar.gz tor-6c4864f35100b0774269a368a69266335ca8ca11.zip |
r13924@catbus: nickm | 2007-07-26 16:46:45 -0400
We can have multiple authority certificates for an authority at a time: make the code reflect that.
svn:r10937
-rw-r--r-- | src/or/dirvote.c | 24 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/routerlist.c | 62 | ||||
-rw-r--r-- | src/or/routerparse.c | 26 |
4 files changed, 69 insertions, 47 deletions
diff --git a/src/or/dirvote.c b/src/or/dirvote.c index f8df2c74bb..d8c143e9fe 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -726,18 +726,17 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, voter, { - trusted_dir_server_t *ds = - trusteddirserver_get_by_v3_auth_digest(voter->identity_digest); - if (!ds) { - ++n_unknown; - continue; - } - if (voter->signature) { - tor_assert(!voter->good_signature && !voter->bad_signature); - if (!ds->v3_cert || - networkstatus_check_voter_signature(consensus, voter, - ds->v3_cert) < 0) { - ++n_missing_key; + if (!voter->good_signature && !voter->bad_signature && voter->signature) { + /* we can try to check the signature. */ + authority_cert_t *cert = + authority_cert_get_by_digests(voter->identity_digest, + voter->signing_key_digest); + if (! cert) { + ++n_unknown; + continue; + } + if (networkstatus_check_voter_signature(consensus, voter, cert) < 0) { + ++n_missing_key; /* XXXX020 what, really? */ continue; } } @@ -840,7 +839,6 @@ networkstatus_add_consensus_signatures(networkstatus_vote_t *target, return r; } - /* ===== * Certificate functions * ===== */ diff --git a/src/or/or.h b/src/or/or.h index 755c69e7df..c238efc9c8 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1408,6 +1408,7 @@ typedef struct authority_cert_t { signed_descriptor_t cache_info; crypto_pk_env_t *identity_key; crypto_pk_env_t *signing_key; + char signing_key_digest[DIGEST_LEN]; time_t expires; } authority_cert_t; @@ -3275,8 +3276,7 @@ typedef struct trusted_dir_server_t { /** What kind of authority is this? (Bitfield.) */ authority_type_t type; - /* XXXX020 this should be a list. */ - authority_cert_t *v3_cert; /**< V3 key certificate for this authority */ + smartlist_t *v3_certs; /**< V3 key certificates for this authority */ int n_networkstatus_failures; /**< How many times have we asked for this * server's network-status unsuccessfully? */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 5c327073bf..b0d15e922b 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -207,6 +207,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store) for (s = contents; *s; s = eos) { authority_cert_t *cert = authority_cert_parse_from_string(s, &eos); + int found; if (!cert) break; ds = trusteddirserver_get_by_v3_auth_digest( @@ -217,22 +218,28 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store) authority_cert_free(cert); continue; } + if (!ds->v3_certs) + ds->v3_certs = smartlist_create(); - if (ds->v3_cert) { - if (ds->v3_cert->expires < cert->expires) { - authority_cert_free(ds->v3_cert); - ds->v3_cert = NULL; /* redundant, but let's be safe. */ - } else { - /* This also covers the case where the certificate is the same - * as the one we have. */ - authority_cert_free(cert); - continue; - } - } + SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, c, + { + if (memcmp(c->cache_info.signed_descriptor_digest, + cert->cache_info.signed_descriptor_digest, + DIGEST_LEN)) { + /* we already have this one. continue. */ + authority_cert_free(cert); + found = 1; + break; + } + }); + + if (found) + continue; cert->cache_info.signed_descriptor_body = tor_strndup(s, eos-s); cert->cache_info.signed_descriptor_len = eos-s; - ds->v3_cert = cert; + smartlist_add(ds->v3_certs, cert); + if (!from_store) trusted_dir_servers_certs_changed = 1; } @@ -250,11 +257,14 @@ trusted_dirs_flush_certs_to_disk(void) get_options()->DataDirectory); SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { - if (ds->v3_cert) { - sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t)); - c->bytes = ds->v3_cert->cache_info.signed_descriptor_body; - c->len = ds->v3_cert->cache_info.signed_descriptor_len; - smartlist_add(chunks, c); + if (ds->v3_certs) { + SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert, + { + sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t)); + c->bytes = cert->cache_info.signed_descriptor_body; + c->len = cert->cache_info.signed_descriptor_len; + smartlist_add(chunks, c); + }); } }); if (write_chunks_to_file(filename, chunks, 0)) { @@ -271,16 +281,15 @@ authority_cert_t * authority_cert_get_by_digests(const char *id_digest, const char *sk_digest) { - char d[DIGEST_LEN]; trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest); - if (!ds || !ds->v3_cert) - return NULL; - crypto_pk_get_digest(ds->v3_cert->signing_key, d); - if (memcmp(d, sk_digest, DIGEST_LEN)) + if (!ds || !ds->v3_certs) return NULL; + SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert, + if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN)) + return cert; ); - return ds->v3_cert; + return NULL; } /* Router descriptor storage. @@ -3705,8 +3714,11 @@ add_trusted_dir_server(const char *nickname, const char *address, static void trusted_dir_server_free(trusted_dir_server_t *ds) { - if (ds->v3_cert) - authority_cert_free(ds->v3_cert); + if (ds->v3_certs) { + SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert, + authority_cert_free(cert)); + smartlist_free(ds->v3_certs); + } tor_free(ds->nickname); tor_free(ds->description); tor_free(ds->address); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 8c025668a3..4e948c7945 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1306,6 +1306,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) char *eos; size_t len; trusted_dir_server_t *ds; + int found; s = eat_whitespace(s); eos = strstr(s, "\n-----END SIGNATURE-----\n"); @@ -1340,6 +1341,8 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) tor_assert(tok && tok->key); cert->signing_key = tok->key; tok->key = NULL; + if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest)) + goto err; tok = find_first_by_keyword(tokens, K_DIR_IDENTITY_KEY); tor_assert(tok && tok->key); @@ -1385,13 +1388,22 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) /* If we already have this cert, don't bother checking the signature. */ ds = trusteddirserver_get_by_v3_auth_digest( cert->cache_info.identity_digest); - if (ds && ds->v3_cert && - ds->v3_cert->cache_info.signed_descriptor_len == len && - ds->v3_cert->cache_info.signed_descriptor_body && - ! memcmp(s, ds->v3_cert->cache_info.signed_descriptor_body, len)) { - log_debug(LD_DIR, "We already checked the signature on this certificate;" - " no need to do so again."); - } else { + found = 0; + if (ds && ds->v3_certs) { + SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, c, + { + /* XXXX020 can we just compare signed_descriptor_digest ? */ + if (c->cache_info.signed_descriptor_len == len && + c->cache_info.signed_descriptor_body && + !memcmp(s, c->cache_info.signed_descriptor_body, len)) { + log_debug(LD_DIR, "We already checked the signature on this " + "certificate; no need to do so again."); + found = 1; + break; + } + }); + } + if (!found) { if (check_signature_token(digest, tok, cert->identity_key, 0, "key certificate")) { goto err; |