[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r13304: Fix bug 571: associate certificates with keys, not dirserver (in tor/trunk: . src/or)
Author: nickm
Date: 2008-01-26 18:18:30 -0500 (Sat, 26 Jan 2008)
New Revision: 13304
Modified:
tor/trunk/ChangeLog
tor/trunk/src/or/directory.c
tor/trunk/src/or/or.h
tor/trunk/src/or/routerlist.c
tor/trunk/src/or/routerparse.c
Log:
Fix bug 571: associate certificates with keys, not dirservers, so that we can have certificates for dirservers we do not recognize.
Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog 2008-01-26 23:00:21 UTC (rev 13303)
+++ tor/trunk/ChangeLog 2008-01-26 23:18:30 UTC (rev 13304)
@@ -1,4 +1,8 @@
Changes in version 0.2.0.19-alpha - 2008-0?-??
+ o Minor bugfixes:
+ - Directory caches now fetch certificates from all authorities
+ listed in a networkstatus consensus, even when they do not
+ recognize them. Fixes bug 571. Bugfix on 0.2.0.x.
Changes in version 0.2.0.18-alpha - 2008-01-25
Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c 2008-01-26 23:00:21 UTC (rev 13303)
+++ tor/trunk/src/or/directory.c 2008-01-26 23:18:30 UTC (rev 13304)
@@ -601,9 +601,7 @@
failed, NULL, 1, 0);
SMARTLIST_FOREACH(failed, char *, cp,
{
- trusted_dir_server_t *dir = trusteddirserver_get_by_v3_auth_digest(cp);
- if (dir)
- download_status_failed(&dir->cert_dl_status, status);
+ authority_cert_dl_failed(cp, status);
tor_free(cp);
});
smartlist_free(failed);
@@ -2494,14 +2492,7 @@
smartlist_t *certs = smartlist_create();
ssize_t len = -1;
if (!strcmp(url, "/tor/keys/all")) {
- SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
- trusted_dir_server_t *, ds,
- {
- if (!ds->v3_certs)
- continue;
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
- smartlist_add(certs, cert));
- });
+ authority_cert_get_all(certs);
} else if (!strcmp(url, "/tor/keys/authority")) {
authority_cert_t *cert = get_my_v3_authority_cert();
if (cert)
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2008-01-26 23:00:21 UTC (rev 13303)
+++ tor/trunk/src/or/or.h 2008-01-26 23:18:30 UTC (rev 13304)
@@ -3030,6 +3030,10 @@
char *directory_dump_request_log(void);
int router_supports_extrainfo(const char *identity_digest, int is_authority);
+void directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
+ int seconds_valid);
+int directory_get_from_hs_dir(const char *desc_id, const char *query);
+
time_t download_status_increment_failure(download_status_t *dls,
int status_code, const char *item,
int server, time_t now);
@@ -3813,9 +3817,11 @@
/** What kind of authority is this? (Bitfield.) */
authority_type_t type;
+#if 0
smartlist_t *v3_certs; /**< V3 key certificates for this authority */
download_status_t cert_dl_status; /**< Status of downloading this server's
* latest certificate. */
+#endif
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */
time_t addr_current_at; /**< When was the document that we derived the
@@ -3840,6 +3846,8 @@
authority_cert_t *authority_cert_get_by_sk_digest(const char *sk_digest);
authority_cert_t *authority_cert_get_by_digests(const char *id_digest,
const char *sk_digest);
+void authority_cert_get_all(smartlist_t *certs_out);
+void authority_cert_dl_failed(const char *id_digest, int status);
void authority_certs_fetch_missing(networkstatus_vote_t *status, time_t now);
int router_reload_router_list(void);
smartlist_t *router_get_trusted_dir_servers(void);
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2008-01-26 23:00:21 UTC (rev 13303)
+++ tor/trunk/src/or/routerlist.c 2008-01-26 23:18:30 UTC (rev 13304)
@@ -47,8 +47,16 @@
/** Global list of a trusted_dir_server_t object for each trusted directory
* server. */
static smartlist_t *trusted_dir_servers = NULL;
-/** True iff the key certificate in at least one member of
- * <b>trusted_dir_server_t</b> has changed since we last flushed the
+
+/** DOCDOC */
+typedef struct cert_list_t {
+ download_status_t dl_status;
+ smartlist_t *certs;
+} cert_list_t;
+/** Map from v3 identity key digest to cert_list_t. */
+static digestmap_t *trusted_dir_certs = NULL;
+/** True iff any key certificate in at least one member of
+ * <b>trusted_dir_certs</b> has changed since we last flushed the
* certificates to disk. */
static int trusted_dir_servers_certs_changed = 0;
@@ -80,6 +88,22 @@
#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
+/** DOCDOC */
+static cert_list_t *
+get_cert_list(const char *id_digest)
+{
+ cert_list_t *cl;
+ if (!trusted_dir_certs)
+ trusted_dir_certs = digestmap_new();
+ cl = digestmap_get(trusted_dir_certs, id_digest);
+ if (!cl) {
+ cl = tor_malloc_zero(sizeof(cert_list_t));
+ cl->certs = smartlist_create();
+ digestmap_set(trusted_dir_certs, id_digest, cl);
+ }
+ return cl;
+}
+
/** Reload the cached v3 key certificates from the cached-certs file in
* the data directory. Return 0 on success, -1 on failure. */
int
@@ -108,6 +132,7 @@
trusted_dirs_load_certs_from_string(const char *contents, int from_store)
{
trusted_dir_server_t *ds;
+ cert_list_t *cl;
const char *s, *eos;
for (s = contents; *s; s = eos) {
@@ -117,17 +142,20 @@
break;
ds = trusteddirserver_get_by_v3_auth_digest(
cert->cache_info.identity_digest);
- if (!ds) {
- log_info(LD_DIR, "Found %s certificate whose key didn't match "
- "any v3 authority we recognized; skipping.",
- from_store ? "cached" : "downloaded");
- authority_cert_free(cert);
- continue;
+
+#if 0
+ if (drop_unknown && !ds) {
+ log_info(LD_DIR, "Found %s certificate whose key didn't match "
+ "any v3 authority we recognized; skipping.",
+ from_store ? "cached" : "downloaded");
+ authority_cert_free(cert);
+ continue;
+ }
}
- if (!ds->v3_certs)
- ds->v3_certs = smartlist_create();
+#endif
+ cl = get_cert_list(cert->cache_info.identity_digest);
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, c,
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c,
{
if (!memcmp(c->cache_info.signed_descriptor_digest,
cert->cache_info.signed_descriptor_digest,
@@ -145,12 +173,19 @@
if (found)
continue;
- 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));
+ if (ds) {
+ 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));
+ } else {
+ log_info(LD_DIR, "Adding %s certificate for unrecognized directory "
+ "authority with signing key %s",
+ from_store ? "cached" : "downloaded",
+ hex_str(cert->signing_key_digest,DIGEST_LEN));
+ }
- smartlist_add(ds->v3_certs, cert);
- if (cert->cache_info.published_on > ds->addr_current_at) {
+ smartlist_add(cl->certs, cert);
+ if (ds && cert->cache_info.published_on > ds->addr_current_at) {
/* Check to see whether we should update our view of the authority's
* address. */
if (cert->addr && cert->dir_port &&
@@ -185,23 +220,20 @@
char *filename;
smartlist_t *chunks;
- if (!trusted_dir_servers_certs_changed)
+ if (!trusted_dir_servers_certs_changed || !trusted_dir_certs)
return;
chunks = smartlist_create();
-
- SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
- {
- if (ds->v3_certs) {
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
+ SMARTLIST_FOREACH(cl->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);
});
- }
- });
+ } DIGESTMAP_FOREACH_END
+
filename = get_datadir_fname("cached-certs");
if (write_chunks_to_file(filename, chunks, 0)) {
log_warn(LD_FS, "Error writing certificates to disk.");
@@ -221,23 +253,23 @@
trusted_dirs_remove_old_certs(void)
{
#define OLD_CERT_LIFETIME (48*60*60)
- SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
- {
- authority_cert_t *newest = NULL;
- if (!ds->v3_certs)
- continue;
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ if (!trusted_dir_certs)
+ return;
+
+ DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
+ authority_cert_t *newest = NULL;
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
if (!newest || (cert->cache_info.published_on >
newest->cache_info.published_on))
newest = cert);
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
if (newest && (newest->cache_info.published_on >
cert->cache_info.published_on + OLD_CERT_LIFETIME)) {
- SMARTLIST_DEL_CURRENT(ds->v3_certs, cert);
+ SMARTLIST_DEL_CURRENT(cl->certs, cert);
authority_cert_free(cert);
trusted_dir_servers_certs_changed = 1;
});
- });
+ } DIGESTMAP_FOREACH_END
#undef OLD_CERT_LIFETIME
trusted_dirs_flush_certs_to_disk();
@@ -249,11 +281,11 @@
authority_cert_t *
authority_cert_get_newest_by_id(const char *id_digest)
{
- trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest);
+ cert_list_t *cl;
authority_cert_t *best = NULL;
- if (!ds || !ds->v3_certs)
+ if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
return NULL;
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
{
if (!best || cert->cache_info.published_on > best->cache_info.published_on)
best = cert;
@@ -267,18 +299,16 @@
authority_cert_t *
authority_cert_get_by_sk_digest(const char *sk_digest)
{
- if (!trusted_dir_servers)
+ if (!trusted_dir_certs)
return NULL;
- SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
- {
- if (!ds->v3_certs)
- continue;
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+
+ DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
{
if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
return cert;
});
- });
+ } DIGESTMAP_FOREACH_END
return NULL;
}
@@ -289,17 +319,40 @@
authority_cert_get_by_digests(const char *id_digest,
const char *sk_digest)
{
- trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest);
-
- if (!ds || !ds->v3_certs)
+ cert_list_t *cl;
+ if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
return NULL;
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
return cert; );
return NULL;
}
+/** DOCDOC */
+void
+authority_cert_get_all(smartlist_t *certs_out)
+{
+ if (!trusted_dir_certs)
+ return;
+
+ DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c,
+ smartlist_add(certs_out, c));
+ } DIGESTMAP_FOREACH_END
+}
+
+/** DOCDOC */
+void
+authority_cert_dl_failed(const char *id_digest, int status)
+{
+ cert_list_t *cl;
+ if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
+ return;
+
+ download_status_failed(&cl->dl_status, status);
+}
+
/** How many times will we try to fetch a certificate before giving up? */
#define MAX_CERT_DL_FAILURES 8
@@ -315,6 +368,8 @@
digestmap_t *pending;
smartlist_t *missing_digests;
char *resource = NULL;
+ cert_list_t *cl;
+ const int cache = directory_caches_dir_info(get_options());
if (should_delay_dir_fetches(get_options()))
return;
@@ -326,24 +381,22 @@
if (status) {
SMARTLIST_FOREACH(status->voters, networkstatus_voter_info_t *, voter,
{
- trusted_dir_server_t *ds
- = trusteddirserver_get_by_v3_auth_digest(voter->identity_digest);
- if (!ds) /* XXXX020 This is wrong!! If we're a cache, we should
- * download unrecognized signing keys so we can serve
- * them. */
- continue;
if (tor_digest_is_zero(voter->signing_key_digest))
continue; /* This authority never signed this consensus, so don't
* go looking for a cert with key digest 0000000000. */
+ if (!cache &&
+ !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest))
+ continue; /* We are not a cache, and we don't know this authority.*/
+ cl = get_cert_list(voter->identity_digest);
if (authority_cert_get_by_digests(voter->identity_digest,
voter->signing_key_digest)) {
- download_status_reset(&ds->cert_dl_status);
+ download_status_reset(&cl->dl_status);
continue;
}
- if (download_status_is_ready(&ds->cert_dl_status, now,
+ if (download_status_is_ready(&cl->dl_status, now,
MAX_CERT_DL_FAILURES)) {
- log_notice(LD_DIR, "We're missing a certificate from authority %s "
- "with signing key %s: launching request.", ds->nickname,
+ log_notice(LD_DIR, "We're missing a certificate from authority "
+ "with signing key %s: launching request.",
hex_str(voter->signing_key_digest, DIGEST_LEN));
smartlist_add(missing_digests, voter->identity_digest);
}
@@ -356,19 +409,18 @@
continue;
if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
continue;
- if (!ds->v3_certs)
- ds->v3_certs = smartlist_create();
- SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ cl = get_cert_list(ds->v3_identity_digest);
+ SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
{
if (!ftime_definitely_after(now, cert->expires)) {
/* It's not expired, and we weren't looking for something to
* verify a consensus with. Call it done. */
- download_status_reset(&ds->cert_dl_status);
+ download_status_reset(&cl->dl_status);
found = 1;
break;
}
});
- if (!found && download_status_is_ready(&ds->cert_dl_status, now,
+ if (!found && download_status_is_ready(&cl->dl_status, now,
MAX_CERT_DL_FAILURES)) {
log_notice(LD_DIR, "No current certificate known for authority %s; "
"launching request.", ds->nickname);
@@ -3403,11 +3455,6 @@
static void
trusted_dir_server_free(trusted_dir_server_t *ds)
{
- 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);
Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c 2008-01-26 23:00:21 UTC (rev 13303)
+++ tor/trunk/src/or/routerparse.c 2008-01-26 23:18:30 UTC (rev 13304)
@@ -1433,14 +1433,13 @@
authority_cert_t *
authority_cert_parse_from_string(const char *s, const char **end_of_string)
{
- authority_cert_t *cert = NULL;
+ authority_cert_t *cert = NULL, *old_cert;
smartlist_t *tokens = NULL;
char digest[DIGEST_LEN];
directory_token_t *tok;
char fp_declared[DIGEST_LEN];
char *eos;
size_t len;
- trusted_dir_server_t *ds;
int found;
s = eat_whitespace(s);
@@ -1531,22 +1530,19 @@
}
/* If we already have this cert, don't bother checking the signature. */
- ds = trusteddirserver_get_by_v3_auth_digest(
- cert->cache_info.identity_digest);
+ old_cert = authority_cert_get_by_digests(
+ cert->cache_info.identity_digest,
+ cert->signing_key_digest);
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 (old_cert) {
+ /* XXXX020 can we just compare signed_descriptor_digest ? */
+ if (old_cert->cache_info.signed_descriptor_len == len &&
+ old_cert->cache_info.signed_descriptor_body &&
+ !memcmp(s, old_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.");
+ found = 1;
+ }
}
if (!found) {
if (check_signature_token(digest, tok, cert->identity_key, 0,