Browse Source

Don't use Tor version 0.0.5 for intro/rendezvous points. (We don't need
to worry about 0.0.4 or earlier, because nobody is running them any more.)


svn:r1533

Nick Mathewson 21 years ago
parent
commit
8169da5c30
8 changed files with 89 additions and 23 deletions
  1. 1 1
      doc/TODO
  2. 20 8
      src/common/util.c
  3. 9 7
      src/common/util.h
  4. 10 1
      src/or/onion.c
  5. 4 0
      src/or/or.h
  6. 13 2
      src/or/rendservice.c
  7. 6 4
      src/or/router.c
  8. 26 0
      src/or/routerlist.c

+ 1 - 1
doc/TODO

@@ -148,7 +148,7 @@ Rendezvous service:
           protocol, how do we deal? have nodes parse the tor version field?
           protocol, how do we deal? have nodes parse the tor version field?
           force an upgrade? simply be more robust against useless nodes?
           force an upgrade? simply be more robust against useless nodes?
         o should expire rend streams when too much time has passed
         o should expire rend streams when too much time has passed
-        - should make failed rend/intro circs count toward alice's
+        o should make failed rend/intro circs count toward alice's
           num_failed circs, to prevent madness when we're offline (But
           num_failed circs, to prevent madness when we're offline (But
           don't count failed rend circs toward Bob's total, or Alice
           don't count failed rend circs toward Bob's total, or Alice
           can bork him.)
           can bork him.)

+ 20 - 8
src/common/util.c

@@ -213,7 +213,13 @@ void smartlist_clear(smartlist_t *sl) {
   sl->num_used = 0;
   sl->num_used = 0;
 }
 }
 
 
-/* add element to the list, but only if there's room */
+void smartlist_truncate(smartlist_t *sl, int len)
+{
+  assert(len <= sl->num_used);
+  sl->num_used = len;
+}
+
+/* add element to the list */
 void smartlist_add(smartlist_t *sl, void *element) {
 void smartlist_add(smartlist_t *sl, void *element) {
   if (sl->num_used >= sl->capacity) {
   if (sl->num_used >= sl->capacity) {
     sl->capacity *= 2;
     sl->capacity *= 2;
@@ -222,6 +228,12 @@ void smartlist_add(smartlist_t *sl, void *element) {
   sl->list[sl->num_used++] = element;
   sl->list[sl->num_used++] = element;
 }
 }
 
 
+/* Add all elements from S2 to S1. */
+void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2)
+{
+  SMARTLIST_FOREACH(s2, void *, element, smartlist_add(sl, element));
+}
+
 void smartlist_remove(smartlist_t *sl, void *element) {
 void smartlist_remove(smartlist_t *sl, void *element) {
   int i;
   int i;
   if(element == NULL)
   if(element == NULL)
@@ -233,7 +245,7 @@ void smartlist_remove(smartlist_t *sl, void *element) {
     }
     }
 }
 }
 
 
-int smartlist_isin(smartlist_t *sl, void *element) {
+int smartlist_isin(const smartlist_t *sl, void *element) {
   int i;
   int i;
   for(i=0; i < sl->num_used; i++)
   for(i=0; i < sl->num_used; i++)
     if(sl->list[i] == element)
     if(sl->list[i] == element)
@@ -241,7 +253,7 @@ int smartlist_isin(smartlist_t *sl, void *element) {
   return 0;
   return 0;
 }
 }
 
 
-int smartlist_overlap(smartlist_t *sl1, smartlist_t *sl2) {
+int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) {
   int i;
   int i;
   for(i=0; i < sl2->num_used; i++)
   for(i=0; i < sl2->num_used; i++)
     if(smartlist_isin(sl1, sl2->list[i]))
     if(smartlist_isin(sl1, sl2->list[i]))
@@ -250,7 +262,7 @@ int smartlist_overlap(smartlist_t *sl1, smartlist_t *sl2) {
 }
 }
 
 
 /* remove elements of sl1 that aren't in sl2 */
 /* remove elements of sl1 that aren't in sl2 */
-void smartlist_intersect(smartlist_t *sl1, smartlist_t *sl2) {
+void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2) {
   int i;
   int i;
   for(i=0; i < sl1->num_used; i++)
   for(i=0; i < sl1->num_used; i++)
     if(!smartlist_isin(sl2, sl1->list[i])) {
     if(!smartlist_isin(sl2, sl1->list[i])) {
@@ -260,19 +272,19 @@ void smartlist_intersect(smartlist_t *sl1, smartlist_t *sl2) {
 }
 }
 
 
 /* remove all elements of sl2 from sl1 */
 /* remove all elements of sl2 from sl1 */
-void smartlist_subtract(smartlist_t *sl1, smartlist_t *sl2) {
+void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) {
   int i;
   int i;
   for(i=0; i < sl2->num_used; i++)
   for(i=0; i < sl2->num_used; i++)
     smartlist_remove(sl1, sl2->list[i]);
     smartlist_remove(sl1, sl2->list[i]);
 }
 }
 
 
-void *smartlist_choose(smartlist_t *sl) {
+void *smartlist_choose(const smartlist_t *sl) {
   if(sl->num_used)
   if(sl->num_used)
     return sl->list[crypto_pseudo_rand_int(sl->num_used)];
     return sl->list[crypto_pseudo_rand_int(sl->num_used)];
   return NULL; /* no elements to choose from */
   return NULL; /* no elements to choose from */
 }
 }
 
 
-void *smartlist_get(smartlist_t *sl, int idx)
+void *smartlist_get(const smartlist_t *sl, int idx)
 {
 {
   assert(sl && idx>=0 && idx < sl->num_used);
   assert(sl && idx>=0 && idx < sl->num_used);
   return sl->list[idx];
   return sl->list[idx];
@@ -303,7 +315,7 @@ void *smartlist_del_keeporder(smartlist_t *sl, int idx)
     memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
     memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
   return old;
   return old;
 }
 }
-int smartlist_len(smartlist_t *sl)
+int smartlist_len(const smartlist_t *sl)
 {
 {
   return sl->num_used;
   return sl->num_used;
 }
 }

+ 9 - 7
src/common/util.h

@@ -103,19 +103,21 @@ smartlist_t *smartlist_create();
 void smartlist_free(smartlist_t *sl);
 void smartlist_free(smartlist_t *sl);
 void smartlist_set_capacity(smartlist_t *sl, int n);
 void smartlist_set_capacity(smartlist_t *sl, int n);
 void smartlist_clear(smartlist_t *sl);
 void smartlist_clear(smartlist_t *sl);
+void smartlist_truncate(smartlist_t *sl, int n);
 void smartlist_add(smartlist_t *sl, void *element);
 void smartlist_add(smartlist_t *sl, void *element);
+void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
 void smartlist_remove(smartlist_t *sl, void *element);
 void smartlist_remove(smartlist_t *sl, void *element);
-int smartlist_isin(smartlist_t *sl, void *element);
-int smartlist_overlap(smartlist_t *sl1, smartlist_t *sl2);
-void smartlist_intersect(smartlist_t *sl1, smartlist_t *sl2);
-void smartlist_subtract(smartlist_t *sl1, smartlist_t *sl2);
-void *smartlist_choose(smartlist_t *sl);
-void *smartlist_get(smartlist_t *sl, int idx);
+int smartlist_isin(const smartlist_t *sl, void *element);
+int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
+void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
+void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
+void *smartlist_choose(const smartlist_t *sl);
+void *smartlist_get(const smartlist_t *sl, int idx);
 void *smartlist_set(smartlist_t *sl, int idx, void *val);
 void *smartlist_set(smartlist_t *sl, int idx, void *val);
 void *smartlist_del(smartlist_t *sl, int idx);
 void *smartlist_del(smartlist_t *sl, int idx);
 void *smartlist_del_keeporder(smartlist_t *sl, int idx);
 void *smartlist_del_keeporder(smartlist_t *sl, int idx);
 void smartlist_insert(smartlist_t *sl, int idx, void *val);
 void smartlist_insert(smartlist_t *sl, int idx, void *val);
-int smartlist_len(smartlist_t *sl);
+int smartlist_len(const smartlist_t *sl);
 #define SMARTLIST_FOREACH(sl, type, var, cmd)                   \
 #define SMARTLIST_FOREACH(sl, type, var, cmd)                   \
   do {                                                          \
   do {                                                          \
     int sl_idx, sl_len=smartlist_len(sl);                       \
     int sl_idx, sl_len=smartlist_len(sl);                       \

+ 10 - 1
src/or/onion.c

@@ -337,7 +337,16 @@ static routerinfo_t *choose_good_exit_server(uint8_t purpose, routerlist_t *dir)
 {
 {
   if(purpose == CIRCUIT_PURPOSE_C_GENERAL)
   if(purpose == CIRCUIT_PURPOSE_C_GENERAL)
     return choose_good_exit_server_general(dir);
     return choose_good_exit_server_general(dir);
-  else
+  else if (purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND ||
+           purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
+    smartlist_t *obsolete_routers;
+    routerinfo_t *r;
+    obsolete_routers = smartlist_create();
+    router_add_nonrendezvous_to_list(obsolete_routers);
+    r = router_choose_random_node(dir, options.RendNodes, options.RendExcludeNodes, NULL);
+    smartlist_free(obsolete_routers);
+    return r;
+  } else
     return router_choose_random_node(dir, options.RendNodes, options.RendExcludeNodes, NULL);
     return router_choose_random_node(dir, options.RendNodes, options.RendExcludeNodes, NULL);
 }
 }
 
 

+ 4 - 0
src/or/or.h

@@ -461,6 +461,8 @@ typedef struct {
 
 
   int is_running;
   int is_running;
 
 
+  char *platform;
+
   /* link info */
   /* link info */
   uint32_t bandwidthrate;
   uint32_t bandwidthrate;
   uint32_t bandwidthburst;
   uint32_t bandwidthburst;
@@ -996,6 +998,8 @@ routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
 routerinfo_t *router_get_by_nickname(char *nickname);
 routerinfo_t *router_get_by_nickname(char *nickname);
 void router_get_routerlist(routerlist_t **prouterlist);
 void router_get_routerlist(routerlist_t **prouterlist);
 void routerinfo_free(routerinfo_t *router);
 void routerinfo_free(routerinfo_t *router);
+int router_version_supports_rendezvous(routerinfo_t *router);
+void router_add_nonrendezvous_to_list(smartlist_t *sl);
 void router_mark_as_down(char *nickname);
 void router_mark_as_down(char *nickname);
 int router_set_routerlist_from_file(char *routerfile);
 int router_set_routerlist_from_file(char *routerfile);
 int router_set_routerlist_from_string(const char *s);
 int router_set_routerlist_from_string(const char *s);

+ 13 - 2
src/or/rendservice.c

@@ -657,10 +657,14 @@ int rend_services_init(void) {
   rend_service_t *service;
   rend_service_t *service;
   char *desc, *intro;
   char *desc, *intro;
   int changed, prev_intro_nodes, desc_len;
   int changed, prev_intro_nodes, desc_len;
-  smartlist_t *intro_routers;
+  smartlist_t *intro_routers, *exclude_routers;
+  int n_old_routers;
 
 
   router_get_routerlist(&rl);
   router_get_routerlist(&rl);
   intro_routers = smartlist_create();
   intro_routers = smartlist_create();
+  exclude_routers = smartlist_create();
+  router_add_nonrendezvous_to_list(exclude_routers);
+  n_old_routers = smartlist_len(exclude_routers);
 
 
   for (i=0; i< smartlist_len(rend_service_list); ++i) {
   for (i=0; i< smartlist_len(rend_service_list); ++i) {
     smartlist_clear(intro_routers);
     smartlist_clear(intro_routers);
@@ -688,12 +692,13 @@ int rend_services_init(void) {
     /* Remember how many introduction circuits we started with. */
     /* Remember how many introduction circuits we started with. */
     prev_intro_nodes = smartlist_len(service->intro_nodes);
     prev_intro_nodes = smartlist_len(service->intro_nodes);
 
 
+    smartlist_add_all(exclude_routers, intro_routers);
     /* The directory is now here. Pick three ORs as intro points. */
     /* The directory is now here. Pick three ORs as intro points. */
     for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
     for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
       router = router_choose_random_node(rl,
       router = router_choose_random_node(rl,
                                          service->intro_prefer_nodes,
                                          service->intro_prefer_nodes,
                                          service->intro_exclude_nodes,
                                          service->intro_exclude_nodes,
-                                         intro_routers);
+                                         exclude_routers);
       if (!router) {
       if (!router) {
         log_fn(LOG_WARN, "Can't establish more than %d introduction points",
         log_fn(LOG_WARN, "Can't establish more than %d introduction points",
                smartlist_len(service->intro_nodes));
                smartlist_len(service->intro_nodes));
@@ -701,9 +706,14 @@ int rend_services_init(void) {
       }
       }
       changed = 1;
       changed = 1;
       smartlist_add(intro_routers, router);
       smartlist_add(intro_routers, router);
+      smartlist_add(exclude_routers, router);
       smartlist_add(service->intro_nodes, tor_strdup(router->nickname));
       smartlist_add(service->intro_nodes, tor_strdup(router->nickname));
     }
     }
 
 
+    /* Reset exclude_routers to include obsolete routers only for the next
+     * time around the loop. */
+    smartlist_truncate(exclude_routers, n_old_routers);
+
     /* If there's no need to republish, stop here. */
     /* If there's no need to republish, stop here. */
     if (!changed)
     if (!changed)
       continue;
       continue;
@@ -731,6 +741,7 @@ int rend_services_init(void) {
     }
     }
   }
   }
   smartlist_free(intro_routers);
   smartlist_free(intro_routers);
+  smartlist_free(exclude_routers);
 
 
   return 0;
   return 0;
 }
 }

+ 6 - 4
src/or/router.c

@@ -6,6 +6,8 @@
 
 
 extern or_options_t options; /* command-line and config-file options */
 extern or_options_t options; /* command-line and config-file options */
 
 
+static void get_platform_str(char *platform, int len);
+
 /************************************************************/
 /************************************************************/
 
 
 /* private keys */
 /* private keys */
@@ -353,6 +355,7 @@ const char *router_get_my_descriptor(void) {
 int router_rebuild_descriptor(void) {
 int router_rebuild_descriptor(void) {
   routerinfo_t *ri;
   routerinfo_t *ri;
   struct in_addr addr;
   struct in_addr addr;
+  char platform[256];
   if (!tor_inet_aton(options.Address, &addr)) {
   if (!tor_inet_aton(options.Address, &addr)) {
     log_fn(LOG_ERR, "options.Address didn't hold an IP.");
     log_fn(LOG_ERR, "options.Address didn't hold an IP.");
     return -1;
     return -1;
@@ -369,6 +372,8 @@ int router_rebuild_descriptor(void) {
   ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
   ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
   ri->link_pkey = crypto_pk_dup_key(get_link_key());
   ri->link_pkey = crypto_pk_dup_key(get_link_key());
   ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
   ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
+  get_platform_str(platform, sizeof(platform));
+  ri->platform = tor_strdup(platform);
   ri->bandwidthrate = options.BandwidthRate;
   ri->bandwidthrate = options.BandwidthRate;
   ri->bandwidthburst = options.BandwidthBurst;
   ri->bandwidthburst = options.BandwidthBurst;
   ri->exit_policy = NULL; /* zero it out first */
   ri->exit_policy = NULL; /* zero it out first */
@@ -401,7 +406,6 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
   char *link_pkey;
   char *link_pkey;
   char *identity_pkey;
   char *identity_pkey;
   struct in_addr in;
   struct in_addr in;
-  char platform[256];
   char digest[20];
   char digest[20];
   char signature[128];
   char signature[128];
   char published[32];
   char published[32];
@@ -415,8 +419,6 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
   routerinfo_t *ri_tmp;
   routerinfo_t *ri_tmp;
 #endif
 #endif
 
 
-  get_platform_str(platform, sizeof(platform));
-
   if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
   if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
     log_fn(LOG_WARN,"Tried to sign a router with a private key that didn't match router's public key!");
     log_fn(LOG_WARN,"Tried to sign a router with a private key that didn't match router's public key!");
     return -1;
     return -1;
@@ -455,7 +457,7 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
     router->dir_port,
     router->dir_port,
     (int) router->bandwidthrate,
     (int) router->bandwidthrate,
 /* XXXBC also write bandwidthburst */
 /* XXXBC also write bandwidthburst */
-    platform,
+    router->platform,
     published,
     published,
     onion_pkey, link_pkey, identity_pkey);
     onion_pkey, link_pkey, identity_pkey);
 
 

+ 26 - 0
src/or/routerlist.c

@@ -236,6 +236,24 @@ void router_add_running_routers_to_smartlist(smartlist_t *sl) {
   }
   }
 }
 }
 
 
+/* Return 0 if router is running a version of Tor too old to be a
+ * rendezvous/introduction point.  Return 1 otherwise.
+ */
+int router_version_supports_rendezvous(routerinfo_t *router)
+{
+  return (router->platform && 0==strncasecmp(router->platform,"Tor 0.0.5",9));
+}
+
+/* Add every router running a version of Tor too old for rend/intro
+   points to sl.
+ */
+void router_add_nonrendezvous_to_list(smartlist_t *sl)
+{
+  SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
+                    if (!router_version_supports_rendezvous(r))
+                      smartlist_add(sl,r));
+}
+
 /* Pick a random node from preferred if possible, else from all of dir.
 /* Pick a random node from preferred if possible, else from all of dir.
  * Never pick a node in excluded.
  * Never pick a node in excluded.
  * If excludedsmartlist is defined, never pick a node in it either.
  * If excludedsmartlist is defined, never pick a node in it either.
@@ -333,6 +351,7 @@ void routerinfo_free(routerinfo_t *router)
 
 
   tor_free(router->address);
   tor_free(router->address);
   tor_free(router->nickname);
   tor_free(router->nickname);
+  tor_free(router->platform);
   if (router->onion_pkey)
   if (router->onion_pkey)
     crypto_free_pk_env(router->onion_pkey);
     crypto_free_pk_env(router->onion_pkey);
   if (router->link_pkey)
   if (router->link_pkey)
@@ -988,6 +1007,10 @@ routerinfo_t *router_get_entry_from_string(const char *s,
   router->identity_pkey = tok->key;
   router->identity_pkey = tok->key;
   tok->key = NULL; /* Prevent free */
   tok->key = NULL; /* Prevent free */
 
 
+  if ((tok = find_first_by_keyword(tokens, K_PLATFORM))) {
+    router->platform = tor_strdup(tok->args[0]);
+  }
+
   exit_policy_tokens = find_all_exitpolicy(tokens);
   exit_policy_tokens = find_all_exitpolicy(tokens);
   SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
   SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
                     if (router_add_exit_policy(router,t)<0) {
                     if (router_add_exit_policy(router,t)<0) {
@@ -1023,6 +1046,9 @@ routerinfo_t *router_get_entry_from_string(const char *s,
     log_fn(LOG_WARN,"bandwidthrate unreadable or 0. Failing.");
     log_fn(LOG_WARN,"bandwidthrate unreadable or 0. Failing.");
     goto err;
     goto err;
   }
   }
+  if (!router->platform) {
+    router->platform = tor_strdup("<unknown>");
+  }
 
 
 #if XXXBC
 #if XXXBC
   router->bandwidthburst = atoi(ARGS[6]);
   router->bandwidthburst = atoi(ARGS[6]);