diff options
-rw-r--r-- | doc/TODO | 6 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 8 | ||||
-rw-r--r-- | src/or/circuituse.c | 6 | ||||
-rw-r--r-- | src/or/connection_edge.c | 4 | ||||
-rw-r--r-- | src/or/connection_or.c | 4 | ||||
-rw-r--r-- | src/or/control.c | 4 | ||||
-rw-r--r-- | src/or/dirserv.c | 14 | ||||
-rw-r--r-- | src/or/or.h | 12 | ||||
-rw-r--r-- | src/or/rendclient.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 8 | ||||
-rw-r--r-- | src/or/router.c | 26 | ||||
-rw-r--r-- | src/or/routerlist.c | 85 |
12 files changed, 135 insertions, 44 deletions
@@ -186,7 +186,7 @@ N . Routerdesc download changes connections over last N seconds. o Call dirport_is_reachable from somewhere else. o Networkstatus should list who's an authority. - - Add nickname element to dirserver line. Log this along with IP:Port. + o Add nickname element to dirserver line. Log this along with IP:Port. o Warn when using non-default directory servers. - When giving up on a non-finished dir request, log how many bytes dropped, to see whether it's worthwhile to use partial info. @@ -206,8 +206,8 @@ N . Naming and validation: o Not all authdirs name. o Change naming rule: N->K iff any naming authdir says N->K, and none says N->K' or N'->K. - - Clients choose names based on network-status options. - - Names are remembered in client state (?) + o Clients choose names based on network-status options. + o Names are remembered in client state (?) - Okay to have two valid servers with same nickname, but not two named servers with same nickname. Update logic. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index fd84306b72..e88a5a10f3 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1053,7 +1053,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, or_options_t *options = get_options(); preferredentries = smartlist_create(); - add_nickname_list_to_smartlist(preferredentries,options->EntryNodes,1); + add_nickname_list_to_smartlist(preferredentries,options->EntryNodes,1,1); get_connection_array(&carray, &n_connections); @@ -1142,10 +1142,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, n_best_support, best_support, n_pending_connections); preferredexits = smartlist_create(); - add_nickname_list_to_smartlist(preferredexits,options->ExitNodes,1); + add_nickname_list_to_smartlist(preferredexits,options->ExitNodes,1,1); excludedexits = smartlist_create(); - add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0); + add_nickname_list_to_smartlist(excludedexits,options->ExcludeNodes,0,1); sl = smartlist_create(); @@ -1506,7 +1506,7 @@ onion_extend_cpath(uint8_t purpose, crypt_path_t **head_ptr, state->desired_path_len); excludednodes = smartlist_create(); - add_nickname_list_to_smartlist(excludednodes,get_options()->ExcludeNodes,0); + add_nickname_list_to_smartlist(excludednodes,get_options()->ExcludeNodes,0,1); if (cur_len == state->desired_path_len - 1) { /* Picking last node */ info = extend_info_dup(state->chosen_exit); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index d9b2f7a591..d88db4ee01 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -806,7 +806,7 @@ circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname, routerinfo_t *router = NULL; if (exit_nickname) { - router = router_get_by_nickname(exit_nickname); + router = router_get_by_nickname(exit_nickname, 1); if (!router) { log_fn(LOG_WARN, "No such OR as '%s'", exit_nickname); return NULL; @@ -923,7 +923,7 @@ circuit_get_open_circ_or_launch(connection_t *conn, if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { if (conn->chosen_exit_name) { routerinfo_t *r; - if (!(r = router_get_by_nickname(conn->chosen_exit_name))) { + if (!(r = router_get_by_nickname(conn->chosen_exit_name, 1))) { log_fn(LOG_NOTICE,"Requested exit point '%s' is not known. Closing.", conn->chosen_exit_name); return -1; @@ -1097,7 +1097,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn) circuit_t *circ=NULL; if (conn->chosen_exit_name) { - routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name); + routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); if (!router) { log_fn(LOG_WARN,"Requested exit point '%s' is not known. Closing.", conn->chosen_exit_name); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index bf51b126fe..0cefe5d694 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -996,7 +996,7 @@ connection_ap_handshake_process_socks(connection_t *conn) } } else { struct in_addr in; - routerinfo_t *r = router_get_by_nickname(socks->address); + routerinfo_t *r = router_get_by_nickname(socks->address, 1); if (r) { conn->chosen_exit_name = tor_strdup(socks->address); /* XXXX Should this use server->address instead? */ @@ -1703,7 +1703,7 @@ connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) * make sure the exit node of the existing circuit matches exactly. */ if (conn->chosen_exit_name) { - if (router_get_by_nickname(conn->chosen_exit_name) != exit) { + if (router_get_by_nickname(conn->chosen_exit_name, 1) != exit) { /* doesn't match */ log_fn(LOG_DEBUG,"Requested node '%s', considering node '%s'. No.", conn->chosen_exit_name, exit->nickname); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index b69301df9f..6d3fad21d0 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -497,9 +497,9 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd) } crypto_free_pk_env(identity_rcvd); - router = router_get_by_nickname(nickname); + router = router_get_by_nickname(nickname, 0); if (router && /* we know this nickname */ - router->is_verified && /* make sure it's the right guy */ + router->is_named && /* make sure it's the right guy */ memcmp(digest_rcvd, router->identity_digest, DIGEST_LEN) != 0) { log_fn(severity, "Identity key not as expected for router claiming to be '%s' (%s:%d)", diff --git a/src/or/control.c b/src/or/control.c index dccb2d55a5..f522f79acd 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1226,7 +1226,7 @@ handle_getinfo_helper(const char *question, char **answer) if (ri && ri->signed_descriptor) *answer = tor_strdup(ri->signed_descriptor); } else if (!strcmpstart(question, "desc/name/")) { - routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/")); + routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1); if (ri && ri->signed_descriptor) *answer = tor_strdup(ri->signed_descriptor); } else if (!strcmpstart(question, "unregistered-servers-")) { @@ -1513,7 +1513,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, routers = smartlist_create(); SMARTLIST_FOREACH(router_nicknames, const char *, n, { - routerinfo_t *r = router_get_by_nickname(n); + routerinfo_t *r = router_get_by_nickname(n, 1); if (!r) { if (v0) send_control0_error(conn, ERR_NO_ROUTER, n); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index d60560ce41..3a1c6eb079 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -105,12 +105,14 @@ add_fingerprint_to_dir(const char *nickname, const char *fp, smartlist_t *list) fingerprint = tor_strdup(fp); tor_strstrip(fingerprint, " "); - for (i = 0; i < smartlist_len(list); ++i) { - ent = smartlist_get(list, i); - if (!strcasecmp(ent->nickname,nickname)) { - tor_free(ent->fingerprint); - ent->fingerprint = fingerprint; - return 1; + if (nickname[0] != '!') { + for (i = 0; i < smartlist_len(list); ++i) { + ent = smartlist_get(list, i); + if (!strcasecmp(ent->nickname,nickname)) { + tor_free(ent->fingerprint); + ent->fingerprint = fingerprint; + return 1; + } } } ent = tor_malloc(sizeof(fingerprint_entry_t)); diff --git a/src/or/or.h b/src/or/or.h index c1e3203010..b5286178d6 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -775,8 +775,8 @@ typedef struct { unsigned int is_verified:1; /**< Has a trusted dirserver validated this OR? * (For Authdir: Have we validated this OR?) */ - /*XXXX Make this get used once we think we do naming right. NM */ - unsigned int is_named:1; /* Do we believe the nickname that this OR gives us? */ + unsigned int is_named:1; /**< Do we believe the nickname that this OR gives + * us? */ /* The below items are used only by authdirservers for * reachability testing. */ @@ -815,6 +815,9 @@ typedef struct local_routerstatus_t { uint8_t n_download_failures; /**< Number of failures trying to download the * most recent descriptor. */ unsigned int should_download:1; /**< DOCDOC */ + unsigned int name_lookup_warned:1; /*< Have we warned the user for referring + * to this (unnamed) router by nickname? + */ } local_routerstatus_t; /*XXXX011 make this configurable? */ @@ -2091,7 +2094,7 @@ trusted_dir_server_t *router_get_trusteddirserver_by_digest( const char *digest); int all_trusted_directory_servers_down(void); void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); -void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down); +void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down, int warn_if_unnamed); routerinfo_t *routerlist_find_my_routerinfo(void); int exit_policy_implicitly_allows_local_networks(addr_policy_t *policy, int warn); @@ -2110,7 +2113,8 @@ routerinfo_t *router_choose_random_node(const char *preferred, smartlist_t *excludedsmartlist, int need_uptime, int need_bandwidth, int allow_unverified, int strict); -routerinfo_t *router_get_by_nickname(const char *nickname); +routerinfo_t *router_get_by_nickname(const char *nickname, + int warn_if_unnamed); routerinfo_t *router_get_by_hexdigest(const char *hexdigest); routerinfo_t *router_get_by_digest(const char *digest); int router_digest_is_trusted_dir(const char *digest); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 8b191b4187..b4e8f171af 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -467,7 +467,7 @@ rend_client_get_random_intro(const char *query) } else { /* add the intro point nicknames */ char *choice = entry->parsed->intro_points[i]; - routerinfo_t *router = router_get_by_nickname(choice); + routerinfo_t *router = router_get_by_nickname(choice, 0); if (!router) { log_fn(LOG_INFO, "Unknown router with nickname '%s'; trying another.",choice); tor_free(choice); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index e101e9a7b2..b33776bf8c 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -292,7 +292,7 @@ rend_service_update_descriptor(rend_service_t *service) d->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t*)*n); d->protocols = (1<<2) | (1<<0); /* We support protocol 2 and protocol 0. */ for (i=0; i < n; ++i) { - router = router_get_by_nickname(smartlist_get(service->intro_nodes, i)); + router = router_get_by_nickname(smartlist_get(service->intro_nodes, i),1); if (!router) { log_fn(LOG_INFO,"Router '%s' not found. Skipping.", (char*)smartlist_get(service->intro_nodes, i)); @@ -512,7 +512,7 @@ rend_service_introduce(circuit_t *circuit, const char *request, size_t request_l ptr = rp_nickname+nickname_field_len; len -= nickname_field_len; len -= rp_nickname - buf; /* also remove header space used by version, if any */ - router = router_get_by_nickname(rp_nickname); + router = router_get_by_nickname(rp_nickname, 0); if (!router) { log_fn(LOG_INFO, "Couldn't find router '%s' named in rendezvous cell.", rp_nickname); @@ -934,7 +934,7 @@ rend_services_introduce(void) /* Find out which introduction points we have in progress for this service. */ for (j=0; j < smartlist_len(service->intro_nodes); ++j) { intro = smartlist_get(service->intro_nodes, j); - router = router_get_by_nickname(intro); + router = router_get_by_nickname(intro, 1); if (!router || !find_intro_circuit(router,service->pk_digest)) { log_fn(LOG_INFO,"Giving up on %s as intro point for %s.", intro, service->service_id); @@ -1052,7 +1052,7 @@ rend_service_dump_stats(int severity) log(severity, "Service configured in \"%s\":", service->directory); for (j=0; j < smartlist_len(service->intro_nodes); ++j) { nickname = smartlist_get(service->intro_nodes, j); - router = router_get_by_nickname(smartlist_get(service->intro_nodes,j)); + router = router_get_by_nickname(smartlist_get(service->intro_nodes,j),1); if (!router) { log(severity, " Intro point at %s: unrecognized router",nickname); continue; diff --git a/src/or/router.c b/src/or/router.c index 3db797ffd2..5835c38aed 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -810,9 +810,33 @@ router_rebuild_descriptor(int force) if (authdir_mode(options)) ri->is_verified = ri->is_named = 1; /* believe in yourself */ if (options->MyFamily) { + smartlist_t *family = smartlist_create(); ri->declared_family = smartlist_create(); - smartlist_split_string(ri->declared_family, options->MyFamily, ",", + smartlist_split_string(family, options->MyFamily, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH(family, char *, name, + { + routerinfo_t *member; + if (!strcasecmp(name, options->Nickname)) + member = ri; + else + member = router_get_by_nickname(name, 1); + if (!member) { + log_fn(LOG_WARN, "I have no descriptor for the router named \"%s\" " + "in my declared family; I'll use the nickname verbatim, but " + "this may confuse clients.", name); + smartlist_add(ri->declared_family, name); + name = NULL; + } else { + char *fp = tor_malloc(HEX_DIGEST_LEN+2); + fp[0] = '$'; + base16_encode(fp+1,HEX_DIGEST_LEN+1, + member->identity_digest, DIGEST_LEN); + smartlist_add(ri->declared_family, fp); + } + tor_free(name); + }); + smartlist_free(family); } ri->signed_descriptor = tor_malloc(8192); if (router_dump_router_to_string(ri->signed_descriptor, 8192, diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 435d4dfd55..fef8427acf 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -502,7 +502,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) * declares familyhood with router. */ SMARTLIST_FOREACH(router->declared_family, const char *, n, { - if (!(r = router_get_by_nickname(n))) + if (!(r = router_get_by_nickname(n, 0))) continue; if (!r->declared_family) continue; @@ -516,7 +516,7 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) /* If the user declared any families locally, honor those too. */ for (cl = get_options()->NodeFamilies; cl; cl = cl->next) { if (router_nickname_is_in_list(router, cl->value)) { - add_nickname_list_to_smartlist(sl, cl->value, 0); + add_nickname_list_to_smartlist(sl, cl->value, 1, 1); } } } @@ -530,7 +530,7 @@ static smartlist_t *warned_nicknames = NULL; * currently running. Add the routerinfos for those routers to <b>sl</b>. */ void -add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down) +add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_down, int warn_if_unnamed) { routerinfo_t *router; smartlist_t *nickname_list; @@ -552,7 +552,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int warn_if_do log_fn(LOG_WARN,"Nickname %s is misformed; skipping", nick); continue; } - router = router_get_by_nickname(nick); + router = router_get_by_nickname(nick, warn_if_unnamed); warned = smartlist_string_isin(warned_nicknames, nick); if (router) { if (router->is_running) { @@ -770,12 +770,12 @@ router_choose_random_node(const char *preferred, routerinfo_t *choice; excludednodes = smartlist_create(); - add_nickname_list_to_smartlist(excludednodes,excluded,0); + add_nickname_list_to_smartlist(excludednodes,excluded,0,1); /* Try the preferred nodes first. Ignore need_uptime and need_capacity, * since the user explicitly asked for these nodes. */ sl = smartlist_create(); - add_nickname_list_to_smartlist(sl,preferred,1); + add_nickname_list_to_smartlist(sl,preferred,1,1); smartlist_subtract(sl,excludednodes); if (excludedsmartlist) smartlist_subtract(sl,excludedsmartlist); @@ -839,10 +839,12 @@ router_nickname_matches(routerinfo_t *router, const char *nickname) * <b>nickname</b>. Return NULL if no such router is known. */ routerinfo_t * -router_get_by_nickname(const char *nickname) +router_get_by_nickname(const char *nickname, int warn_if_unnamed) { int maybedigest; char digest[DIGEST_LEN]; + routerinfo_t *best_match=NULL; + int n_matches = 0; tor_assert(nickname); if (!routerlist) @@ -860,12 +862,69 @@ router_get_by_nickname(const char *nickname) { /* XXXX011 NM Should this restrict by Named rouers, or warn on * non-named routers, or something? */ - if (0 == strcasecmp(router->nickname, nickname) || - (maybedigest && 0 == memcmp(digest, router->identity_digest, - DIGEST_LEN))) + if (!strcasecmp(router->nickname, nickname)) { + if (router->is_named) + return router; + else { + ++n_matches; + best_match = router; + } + } else if (maybedigest && + !memcmp(digest, router->identity_digest, DIGEST_LEN)) { return router; + } }); + if (best_match) { + if (n_matches>1) { + smartlist_t *fps = smartlist_create(); + int any_unwarned = 0; + SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, + { + local_routerstatus_t *rs; + char *desc; + size_t dlen; + char fp[HEX_DIGEST_LEN+1]; + if (strcasecmp(router->nickname, nickname)) + continue; + rs=router_get_combined_status_by_digest(router->identity_digest); + if (!rs->name_lookup_warned) { + rs->name_lookup_warned = 1; + any_unwarned = 1; + } + base16_encode(fp, sizeof(fp), router->identity_digest, DIGEST_LEN); + dlen = 32 + HEX_DIGEST_LEN + strlen(router->address); + desc = tor_malloc(dlen); + tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d", + fp, router->address, router->or_port); + smartlist_add(fps, desc); + }); + if (any_unwarned) { + char *alternatives = smartlist_join_strings(fps, "; ",0,NULL); + log_fn(LOG_WARN, "There are multiple matches for the nickname \"%s\"," + " but none is listed as named by the directory authories. " + "Choosing one arbitrarily. If you meant one in particular, " + "you should say %s.", nickname, alternatives); + tor_free(alternatives); + } + SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); + smartlist_free(fps); + } else if (warn_if_unnamed) { + local_routerstatus_t *rs = + router_get_combined_status_by_digest(best_match->identity_digest); + if (rs && !rs->name_lookup_warned) { + char fp[HEX_DIGEST_LEN+1]; + base16_encode(fp, sizeof(fp), best_match->identity_digest, DIGEST_LEN); + log_fn(LOG_WARN, "You specified a server \"%s\" by name, but the " + "directory authorities do not have a listing for this name. " + "To make sure you get the same server in the future, refer to " + "it by key, as \"$%s\".", nickname, fp); + rs->name_lookup_warned = 1; + } + } + return best_match; + } + return NULL; } @@ -2313,6 +2372,7 @@ routerstatus_list_update_from_networkstatus(time_t now) if ((rs_old = router_get_combined_status_by_digest(lowest))) { rs_out->n_download_failures = rs_old->n_download_failures; rs_out->next_attempt_at = rs_old->next_attempt_at; + rs_out->name_lookup_warned = rs_old->name_lookup_warned; } smartlist_add(result, rs_out); log_fn(LOG_DEBUG, "Router '%s' is listed by %d/%d directories, " @@ -2356,7 +2416,8 @@ routers_update_status_from_networkstatus(smartlist_t *routers, int reset_failure local_routerstatus_t *rs; or_options_t *options = get_options(); int authdir = options->AuthoritativeDir; - int namingdir = options->NamingAuthoritativeDir; + int namingdir = options->AuthoritativeDir && + options->NamingAuthoritativeDir; if (!routerstatus_list) return; @@ -2600,9 +2661,9 @@ update_router_descriptor_downloads(time_t now) *cp++ = '+'; } memcpy(cp-1, ".z", 3); - last_download_attempted = now; directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,resource,1); } + last_download_attempted = now; tor_free(resource); } SMARTLIST_FOREACH(downloadable, char *, c, tor_free(c)); |