From 65e26bae3d8cbee189135ed09918e1560f3cf3e6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 2 Jun 2004 20:00:57 +0000 Subject: [PATCH] Check directory signatures based on name of signer, not on whom we got the directory from. svn:r1940 --- src/or/directory.c | 2 +- src/or/or.h | 2 ++ src/or/routerlist.c | 10 ++++++---- src/or/routerparse.c | 21 +++++++++++++++++++-- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/or/directory.c b/src/or/directory.c index 2890736f1f..3119a3fb7b 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -336,7 +336,7 @@ int connection_dir_process_inbuf(connection_t *conn) { connection_mark_for_close(conn); return -1; } - if(router_load_routerlist_from_directory(body, conn->identity_pkey) < 0){ + if(router_load_routerlist_from_directory(body, NULL) < 0){ log_fn(LOG_INFO,"...but parsing failed. Ignoring."); } else { log_fn(LOG_INFO,"updated routers."); diff --git a/src/or/or.h b/src/or/or.h index 7548bf4e2c..7eee5a789b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -578,6 +578,8 @@ typedef struct { * published? */ time_t published_on; + /** Which router is claimed to have signed it? */ + char *signing_router; } routerlist_t; /** Holds accounting information for a single step in the layered encryption diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b2cc910fc1..e221ec4a43 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -212,7 +212,8 @@ routerinfo_t *router_get_by_nickname(char *nickname) routerinfo_t *router; tor_assert(nickname); - tor_assert(routerlist); + if (!routerlist) + return NULL; for(i=0;irouters);i++) { router = smartlist_get(routerlist->routers, i); @@ -446,9 +447,10 @@ int router_load_routerlist_from_string(const char *s, int trusted) } /** Add to the current routerlist each router stored in the - * signed directory s. If pkey is provided, make sure that s is - * signed with pkey. */ -int router_load_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey) + * signed directory s. If pkey is provided, check the signature against + * pkey; else check against the pkey of the signing directory server. */ +int router_load_routerlist_from_directory(const char *s, + crypto_pk_env_t *pkey) { routerlist_t *new_list = NULL; check_software_version_against_directory(s, options.IgnoreVersion); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index c239a613e2..1304975015 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -366,10 +366,27 @@ router_parse_routerlist_from_directory(const char *str, } if (smartlist_len(tokens) != 1 || - ((directory_token_t*)smartlist_get(tokens,0))->tp != K_DIRECTORY_SIGNATURE){ + (!(tok=smartlist_get(tokens,0))) || /* always succeeds */ + (tok->tp != K_DIRECTORY_SIGNATURE)) { log_fn(LOG_WARN,"Expected a single directory signature"); goto err; } - tok = smartlist_get(tokens,0); + if (tok->n_args == 1) { + routerinfo_t *r = router_get_by_nickname(tok->args[0]); + log_fn(LOG_DEBUG, "Got directory signed by %s", tok->args[0]); + if (r && r->is_trusted_dir) { + pkey = r->identity_pkey; + } else if (!r && pkey) { + /* pkey provided for debugging purposes. */ + } else if (!r) { + log_fn(LOG_WARN, "Directory was signed by unrecognized server %s", + tok->args[0]); + goto err; + } else if (r && !r->is_trusted_dir) { + log_fn(LOG_WARN, "Directory was signed by non-trusted server %s", + tok->args[0]); + goto err; + } + } if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) { log_fn(LOG_WARN, "Bad object type or length on directory signature"); goto err;