diff --git a/doc/TODO b/doc/TODO index 9e7aa2a314..6372d50529 100644 --- a/doc/TODO +++ b/doc/TODO @@ -65,7 +65,7 @@ NICK - Possible to get autoconf to easily install things into ~/.tor? o nickname defaults to first piece of hostname o running-routers list refers to nickname if verified, else hash-base64'ed. - - Mark routers as verified or unverified based on whether + o Mark routers as verified or unverified based on whether running-routers list includes nickname or id hash. o put OR uptime in descriptor o name the secret-key directory something to discourage people @@ -95,6 +95,7 @@ NICK - Reputation info needs to give better weight to recent events than - he can connect to you - he has successfully extended to you - he has sufficient mean-time-between-failures + - Don't accept ORs with nicknames same as verified ORs' nicknames. - add new "Middleman 1" config variable? o if torrc not found, exitpolicy reject *:* NICK - change if(options.ORPort) to what we really mean. diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 3da343285f..98eeef55a9 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -469,8 +469,9 @@ list_running_servers(char **nicknames_out) if (router_nickname_is_approved(conn->nickname, conn->identity_digest)) { name = tor_strdup(conn->nickname); } else { - name = tor_malloc(HEX_DIGEST_LEN+1); - base16_encode(name, HEX_DIGEST_LEN, conn->identity_digest, DIGEST_LEN); + name = tor_malloc(HEX_DIGEST_LEN+2); + *name = '$'; + base16_encode(name+1, HEX_DIGEST_LEN, conn->identity_digest, DIGEST_LEN); } if(conn->state == OR_CONN_STATE_OPEN) diff --git a/src/or/or.h b/src/or/or.h index 8fb3b45dd1..d7d0fab49a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -584,6 +584,8 @@ typedef struct { * to exit? */ /* local info */ int is_running; /**< As far as we know, is this OR currently running? */ + time_t status_set_at; /**< When did we last update is_running? */ + int is_verified; /**< Has a trusted dirserver validated this OR? */ int is_trusted_dir; /**< Do we trust this OR as a directory server? */ } routerinfo_t; @@ -1381,6 +1383,9 @@ int router_exit_policy_rejects_all(routerinfo_t *router); void running_routers_free(running_routers_t *rr); void routerlist_update_from_runningrouters(routerlist_t *list, running_routers_t *rr); +void router_update_status_from_smartlist(routerinfo_t *r, + time_t list_time, + smartlist_t *running_list); /********************************* routerparse.c ************************/ @@ -1397,9 +1402,8 @@ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_get_runningrouters_hash(const char *s, char *digest); int router_parse_list_from_string(const char **s, - routerlist_t **dest, - int n_good_nicknames, - const char **good_nickname_lst); + routerlist_t **dest, + smartlist_t *good_nickname_list); int router_parse_routerlist_from_directory(const char *s, routerlist_t **dest, crypto_pk_env_t *pkey); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b1455879da..3d648ae8a3 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -93,6 +93,7 @@ static routerinfo_t *router_pick_directory_server_impl(void) { if(router->is_trusted_dir) { tor_assert(router->dir_port > 0); router->is_running = 1; + router->status_set_at = time(NULL); smartlist_add(sl, router); } } @@ -391,6 +392,7 @@ void router_mark_as_down(const char *digest) { return; log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname); router->is_running = 0; + router->status_set_at = time(NULL); } /** Add router to the routerlist, if we don't already have it. Replace @@ -523,7 +525,7 @@ int router_load_routerlist_from_string(const char *s, int trusted) { routerlist_t *new_list=NULL; - if (router_parse_list_from_string(&s, &new_list, -1, NULL)) { + if (router_parse_list_from_string(&s, &new_list, NULL)) { log(LOG_WARN, "Error parsing router file"); return -1; } @@ -743,9 +745,8 @@ void running_routers_free(running_routers_t *rr) void routerlist_update_from_runningrouters(routerlist_t *list, running_routers_t *rr) { - int n_routers, n_names, i, j, running; + int n_routers, i; routerinfo_t *router; - const char *name; if (!list) return; if (list->published_on >= rr->published_on) @@ -754,26 +755,55 @@ void routerlist_update_from_runningrouters(routerlist_t *list, return; n_routers = smartlist_len(list->routers); - n_names = smartlist_len(rr->running_routers); for (i=0; irouters, i); - for (j=0; jrunning_routers, j); - if (*name != '!') { - if (router_nickname_matches(router, name)) { + router_update_status_from_smartlist(router, + rr->published_on, + rr->running_routers); + } + list->running_routers_updated_on = rr->published_on; +} + +/** Update the is_running and is_verified fields of the router router, + * based in its status in the list of strings stored in running_list. + * All entries in running_list follow one of these formats: + *
  1. nickname -- router is running and verified. + *
  2. !nickname -- router is not-running and verified. + *
  3. $hexdigest -- router is running and unverified. + *
  4. !$hexdigest -- router is not-running and unverified. + *
+ */ +void router_update_status_from_smartlist(routerinfo_t *router, + time_t list_time, + smartlist_t *running_list) +{ + int n_names, i, running, approved; + const char *name; + running = approved = 0; + + n_names = smartlist_len(running_list); + for (i=0; istatus_set_at < list_time) { + router->status_set_at = list_time; router->is_running = 1; - break; } - } else { /* *name == '!' */ - if (router_nickname_matches(router, name)) { + router->is_verified = (name[1] != '$'); + return; + } + } else { /* *name == '!' */ + if (router_nickname_matches(router, name)) { + if (router->status_set_at < list_time) { + router->status_set_at = list_time; router->is_running = 0; - break; } + router->is_verified = (name[1] != '$'); + return; } } } - list->running_routers_updated_on = rr->published_on; } /* diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 368de3c025..137db14b42 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -291,8 +291,7 @@ router_parse_routerlist_from_directory(const char *str, char digest[DIGEST_LEN]; routerlist_t *new_dir = NULL; char *versions = NULL; - int n_good_nicknames = 0; - char *good_nickname_lst[1024]; /* XXXX008 correct this limit. */ + smartlist_t *good_nickname_list = NULL; time_t published_on; int i, r; const char *end; @@ -355,22 +354,21 @@ router_parse_routerlist_from_directory(const char *str, goto err; } - n_good_nicknames = tok->n_args; - memcpy(good_nickname_lst, tok->args, n_good_nicknames*sizeof(char *)); + good_nickname_list = smartlist_create(); + for (i=0; in_args; ++i) { + smartlist_add(good_nickname_list, tok->args[i]); + } tok->n_args = 0; /* Don't free the strings in good_nickname_lst yet. */ /* Read the router list from s, advancing s up past the end of the last * router. */ str = end; if (router_parse_list_from_string(&str, &new_dir, - n_good_nicknames, - (const char**)good_nickname_lst)) { + good_nickname_list)) { log_fn(LOG_WARN, "Error reading routers from directory"); goto err; } - for (i = 0; i < n_good_nicknames; ++i) { - tor_free(good_nickname_lst[i]); /* now free them */ - } + new_dir->software_versions = versions; versions = NULL; new_dir->published_on = published_on; @@ -402,14 +400,15 @@ router_parse_routerlist_from_directory(const char *str, if (new_dir) routerlist_free(new_dir); tor_free(versions); - for (i = 0; i < n_good_nicknames; ++i) { - tor_free(good_nickname_lst[i]); - } done: if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok)); smartlist_free(tokens); } + if (good_nickname_list) { + SMARTLIST_FOREACH(good_nickname_list, char *, n, tor_free(n)); + smartlist_free(good_nickname_list); + } return r; } @@ -531,22 +530,21 @@ static int check_directory_signature(const char *digest, } -/** Given a string *s containing a concatenated - * sequence of router descriptors, parses them and stores the result - * in *dest. If good_nickname_lst is provided, then routers whose - * nicknames are not listed are marked as nonrunning. Advances *s to - * a point immediately following the last router entry. Returns 0 on +/** Given a string *s containing a concatenated sequence of router + * descriptors, parses them and stores the result in *dest. If + * good_nickname_list is provided, then routers are mared as + * running/nonrunning and verified/unverified based on their status in the + * list. Otherwise, all routers are marked running and verified. Advances + * *s to a point immediately following the last router entry. Returns 0 on * success and -1 on failure. */ int router_parse_list_from_string(const char **s, routerlist_t **dest, - int n_good_nicknames, - const char **good_nickname_list) + smartlist_t *good_nickname_list) { routerinfo_t *router; smartlist_t *routers; int rarray_len = 0; - int i; const char *end; tor_assert(s && *s); @@ -573,16 +571,13 @@ router_parse_list_from_string(const char **s, routerlist_t **dest, continue; } - if (n_good_nicknames>=0) { - router->is_running = 0; - for (i = 0; i < n_good_nicknames; ++i) { - if (router_nickname_matches(router, good_nickname_list[i])) { - router->is_running = 1; - break; - } - } + if (good_nickname_list) { + router_update_status_from_smartlist(router, time(NULL), + good_nickname_list); } else { router->is_running = 1; /* start out assuming all dirservers are up */ + router->is_verified = 1; + router->status_set_at = time(NULL); } smartlist_add(routers, router); log_fn(LOG_DEBUG,"just added router #%d.",rarray_len);