From 01786266caa4b15207f559a10a8759532f4cdf07 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 30 Sep 2003 19:27:54 +0000 Subject: [PATCH] Bugfixes in directory code: Improve debugging output on fingerprint checking. Make sure to add our own fingerprint to the fingerprint list _before_ adding our own descriptor, or else we'll reject ourself. Don't call a directory invalid just because we have a newer descriptor for some router. Use router_get_dir_hash to generate hashes for signed directories. Make sure we add our own descriptor successfully. Don't fall-through on failed base64-endode. svn:r514 --- src/or/dirserv.c | 43 ++++++++++++++++++++++++++++++++++++++++--- src/or/main.c | 12 ++++++++++-- src/or/or.h | 4 ++++ src/or/routers.c | 2 +- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/or/dirserv.c b/src/or/dirserv.c index d0c7fbb371..40e2ff51ef 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -20,6 +20,34 @@ typedef struct fingerprint_entry_t { static fingerprint_entry_t fingerprint_list[MAX_ROUTERS_IN_DIR]; static int n_fingerprints = 0; +static void +add_fingerprint_to_dir(const char *nickname, const char *fp) +{ + int i; + for (i = 0; i < n_fingerprints; ++i) { + if (!strcasecmp(fingerprint_list[i].nickname,nickname)) { + free(fingerprint_list[i].fingerprint); + fingerprint_list[i].fingerprint = strdup(fp); + return; + } + } + fingerprint_list[n_fingerprints].nickname = strdup(nickname); + fingerprint_list[n_fingerprints].fingerprint = strdup(fp); + ++n_fingerprints; +} + +int +dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk) +{ + char fp[FINGERPRINT_LEN+1]; + if (crypto_pk_get_fingerprint(pk, fp)<0) { + log_fn(LOG_ERR, "Error computing fingerprint"); + return -1; + } + add_fingerprint_to_dir(nickname, fp); + return 0; +} + /* return 0 on success, -1 on failure */ int dirserv_parse_fingerprint_file(const char *fname) @@ -83,7 +111,9 @@ dirserv_router_fingerprint_is_known(const routerinfo_t *router) fingerprint_entry_t *ent =NULL; char fp[FINGERPRINT_LEN+1]; + log_fn(LOG_DEBUG, "%d fingerprints known.", n_fingerprints); for (i=0;inickname, fingerprint_list[i].nickname); if (!strcasecmp(router->nickname,fingerprint_list[i].nickname)) { ent = &fingerprint_list[i]; break; @@ -91,6 +121,7 @@ dirserv_router_fingerprint_is_known(const routerinfo_t *router) } if (!ent) { /* No such server known */ + log_fn(LOG_WARNING,"no fingerprint found for %s",router->nickname); return 0; } if (crypto_pk_get_fingerprint(router->identity_pkey, fp)) { @@ -98,8 +129,10 @@ dirserv_router_fingerprint_is_known(const routerinfo_t *router) return 0; } if (0==strcasecmp(ent->fingerprint, fp)) { + log_fn(LOG_DEBUG,"good fingerprint for %s",router->nickname); return 1; /* Right fingerprint. */ } else { + log_fn(LOG_WARNING,"mismatched fingerprint for %s",router->nickname); return 0; /* Wrong fingerprint. */ } } @@ -201,7 +234,11 @@ dirserv_add_descriptor(const char **desc) if ((*desc_ent_ptr)->published > ri->published_on) { /* We already have a newer descriptor */ log_fn(LOG_INFO,"We already have a newer desc for nickname %s. Not adding.",ri->nickname); - goto err; + /* This isn't really an error; return. */ + if (desc_tmp) free(desc_tmp); + if (ri) routerinfo_free(ri); + *desc = end; + return 0; } /* We don't have a newer one; we'll update this one. */ free_descriptor_entry(*desc_ent_ptr); @@ -291,7 +328,7 @@ dirserv_dump_directory_to_string(char *s, int maxlen, i = strlen(s); cp = s + i; - if (crypto_SHA_digest(s, i, digest)) { + if (router_get_dir_hash(s,digest)) { log_fn(LOG_WARNING,"couldn't compute digest"); return -1; } @@ -306,7 +343,7 @@ dirserv_dump_directory_to_string(char *s, int maxlen, i = strlen(s); cp = s+i; if (base64_encode(cp, maxlen-i, signature, 128) < 0) { - log_fn(LOG_WARNING," couldn't base64-encode signature"); + log_fn(LOG_WARNING,"couldn't base64-encode signature"); return -1; } diff --git a/src/or/main.c b/src/or/main.c index 37e506ac07..1d1d42bb16 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -472,8 +472,16 @@ static int init_keys(void) log_fn(LOG_ERR, "Error initializing descriptor."); return -1; } + /* We need to add our own fingerprint so it gets recognized. */ + if (dirserv_add_own_fingerprint(options.Nickname, get_identity_key())) { + log_fn(LOG_ERR, "Error adding own fingerprint to approved set"); + return -1; + } tmp = mydesc = router_get_my_descriptor(); - dirserv_add_descriptor(&tmp); + if (dirserv_add_descriptor(&tmp)) { + log(LOG_ERR, "Unable to add own descriptor to directory."); + return -1; + } sprintf(keydir,"%s/router.desc", options.DataDirectory); log_fn(LOG_INFO,"Dumping descriptor to %s...",keydir); if (write_str_to_file(keydir, mydesc)) { @@ -744,7 +752,7 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router, written += strlen(s+written); if (base64_encode(s+written, maxlen-written, signature, 128) < 0) { log_fn(LOG_WARNING, "Couldn't base64-encode signature"); - /* XXX Nick: do we really mean to fall through here? */ + return -1; } written += strlen(s+written); strcat(s+written, "-----END SIGNATURE-----\n"); diff --git a/src/or/or.h b/src/or/or.h index 1d445dc764..c3eb26512a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -620,6 +620,8 @@ int connection_add(connection_t *conn); int connection_remove(connection_t *conn); void connection_set_poll_socket(connection_t *conn); +void get_connection_array(connection_t ***array, int *n); + void connection_watch_events(connection_t *conn, short events); int connection_is_reading(connection_t *conn); void connection_stop_reading(connection_t *conn); @@ -677,6 +679,7 @@ int router_is_me(uint32_t addr, uint16_t port); void router_forget_router(uint32_t addr, uint16_t port); int router_get_list_from_file(char *routerfile); int router_get_router_hash(char *s, char *digest); +int router_get_dir_hash(char *s, char *digest); /* Reads a list of known routers, unsigned. */ int router_get_list_from_string(char *s); @@ -692,6 +695,7 @@ int router_compare_to_exit_policy(connection_t *conn); void routerinfo_free(routerinfo_t *router); /********************************* dirserv.c ***************************/ +int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_parse_fingerprint_file(const char *fname); int dirserv_router_fingerprint_is_known(const routerinfo_t *router); void dirserv_free_fingerprint_list(); diff --git a/src/or/routers.c b/src/or/routers.c index 3367ae6ba3..beec9b1274 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -570,7 +570,7 @@ static int router_get_hash_impl(char *s, char *digest, const char *start_str, return 0; } -static int router_get_dir_hash(char *s, char *digest) +int router_get_dir_hash(char *s, char *digest) { return router_get_hash_impl(s,digest, "signed-directory","directory-signature");