[or-cvs] Check for named servers when looking them up by nickname;

Nick Mathewson nickm at seul.org
Tue Oct 4 22:23:33 UTC 2005


Update of /home/or/cvsroot/tor/src/or
In directory moria:/tmp/cvs-serv13844/src/or

Modified Files:
	circuitbuild.c circuituse.c connection_edge.c connection_or.c 
	control.c dirserv.c or.h rendclient.c rendservice.c router.c 
	routerlist.c 
Log Message:
Check for named servers when looking them up by nickname;
warn when we'recalling a non-named server by its nickname;
don't warn twice about the same name.

Fix a bug in routers_update_status_from_networkstatus that made nearly
all clients never update routerinfo_t.is_named.

Try to list MyFamily elements by key, not by nickname.

Only warn about names that we generated ourself, or got from the local
user.

On TLS handshake, only check the other router's nickname against its
expected nickname if is_named is set.



Index: circuitbuild.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/circuitbuild.c,v
retrieving revision 1.147
retrieving revision 1.148
diff -u -d -r1.147 -r1.148
--- circuitbuild.c	4 Oct 2005 06:53:59 -0000	1.147
+++ circuitbuild.c	4 Oct 2005 22:23:31 -0000	1.148
@@ -1053,7 +1053,7 @@
   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 @@
          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 @@
          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);

Index: circuituse.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/circuituse.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -d -r1.81 -r1.82
--- circuituse.c	30 Sep 2005 01:09:52 -0000	1.81
+++ circuituse.c	4 Oct 2005 22:23:31 -0000	1.82
@@ -806,7 +806,7 @@
   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 @@
     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 @@
     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);

Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/connection_edge.c,v
retrieving revision 1.351
retrieving revision 1.352
diff -u -d -r1.351 -r1.352
--- connection_edge.c	24 Sep 2005 21:56:04 -0000	1.351
+++ connection_edge.c	4 Oct 2005 22:23:31 -0000	1.352
@@ -996,7 +996,7 @@
       }
     } 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 @@
    * 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);

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/connection_or.c,v
retrieving revision 1.186
retrieving revision 1.187
diff -u -d -r1.186 -r1.187
--- connection_or.c	26 Aug 2005 07:41:19 -0000	1.186
+++ connection_or.c	4 Oct 2005 22:23:31 -0000	1.187
@@ -497,9 +497,9 @@
   }
   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)",

Index: control.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/control.c,v
retrieving revision 1.135
retrieving revision 1.136
diff -u -d -r1.135 -r1.136
--- control.c	4 Oct 2005 06:53:59 -0000	1.135
+++ control.c	4 Oct 2005 22:23:31 -0000	1.136
@@ -1226,7 +1226,7 @@
     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 @@
   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);

Index: dirserv.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/dirserv.c,v
retrieving revision 1.244
retrieving revision 1.245
diff -u -d -r1.244 -r1.245
--- dirserv.c	4 Oct 2005 19:52:58 -0000	1.244
+++ dirserv.c	4 Oct 2005 22:23:31 -0000	1.245
@@ -105,12 +105,14 @@
   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));

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.701
retrieving revision 1.702
diff -u -d -r1.701 -r1.702
--- or.h	4 Oct 2005 21:21:09 -0000	1.701
+++ or.h	4 Oct 2005 22:23:31 -0000	1.702
@@ -775,8 +775,8 @@
   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 @@
   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 @@
      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 @@
                                         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);

Index: rendclient.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/rendclient.c,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -d -r1.92 -r1.93
--- rendclient.c	9 Sep 2005 19:54:28 -0000	1.92
+++ rendclient.c	4 Oct 2005 22:23:31 -0000	1.93
@@ -467,7 +467,7 @@
   } 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);

Index: rendservice.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/rendservice.c,v
retrieving revision 1.139
retrieving revision 1.140
diff -u -d -r1.139 -r1.140
--- rendservice.c	30 Sep 2005 01:09:52 -0000	1.139
+++ rendservice.c	4 Oct 2005 22:23:31 -0000	1.140
@@ -292,7 +292,7 @@
   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 @@
     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 @@
     /* 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 @@
     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;

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/router.c,v
retrieving revision 1.214
retrieving revision 1.215
diff -u -d -r1.214 -r1.215
--- router.c	4 Oct 2005 21:21:09 -0000	1.214
+++ router.c	4 Oct 2005 22:23:31 -0000	1.215
@@ -810,9 +810,33 @@
   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,

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerlist.c,v
retrieving revision 1.324
retrieving revision 1.325
diff -u -d -r1.324 -r1.325
--- routerlist.c	4 Oct 2005 21:21:09 -0000	1.324
+++ routerlist.c	4 Oct 2005 22:23:31 -0000	1.325
@@ -502,7 +502,7 @@
    * 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 @@
   /* 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 @@
  * 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 @@
       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 @@
   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 @@
  * <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 @@
   {
     /* 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 @@
     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 @@
   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 @@
         *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));



More information about the tor-commits mailing list