Selaa lähdekoodia

Check recommended-software string *early*, before actually parsing the directory.

svn:r1930
Nick Mathewson 21 vuotta sitten
vanhempi
commit
94782444f8
5 muutettua tiedostoa jossa 90 lisäystä ja 38 poistoa
  1. 1 1
      doc/TODO
  2. 3 0
      src/or/or.h
  3. 1 35
      src/or/routerlist.c
  4. 83 0
      src/or/routerparse.c
  5. 2 2
      src/or/test.c

+ 1 - 1
doc/TODO

@@ -23,7 +23,7 @@ For 0.0.7:
         D try to break apart the main clump of functions better.
         o rend_services_introduce should check if it's failed a lot
           recently, and not try for a while if so
-        - check tor version as soon as you get the recommended-versions
+        o check tor version as soon as you get the recommended-versions
           string, regardless of whether parsing the directory succeeded.
         - make all ORs serve the directory too.
 

+ 3 - 0
src/or/or.h

@@ -1334,6 +1334,9 @@ int router_parse_routerlist_from_directory(const char *s,
 routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
 int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
 struct exit_policy_t *router_parse_exit_policy_from_string(const char *s);
+int check_software_version_against_directory(const char *directory,
+                                             int ignoreversion);
+
 
 #endif
 

+ 1 - 35
src/or/routerlist.c

@@ -445,34 +445,13 @@ int router_load_routerlist_from_string(const char *s, int trusted)
   return 0;
 }
 
-/** Return 1 if myversion is in versionlist. Else return 0.
- * (versionlist is a comma-separated list of versions.) */
-int is_recommended_version(const char *myversion,
-                           const char *versionlist) {
-  int len_myversion = strlen(myversion);
-  char *comma;
-  const char *end = versionlist + strlen(versionlist);
-
-  log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, versionlist);
-
-  for(;;) {
-    comma = strchr(versionlist, ',');
-    if( ((comma ? comma : end) - versionlist == len_myversion) &&
-       !strncmp(versionlist, myversion, len_myversion))
-      /* only do strncmp if the length matches */
-      return 1; /* success, it's there */
-    if(!comma)
-      return 0; /* nope */
-    versionlist = comma+1;
-  }
-}
-
 /** Add to the current routerlist each router stored in the
  * signed directory <b>s</b>.  If pkey is provided, make sure that <b>s</b> is
  * signed with pkey. */
 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);
   if (router_parse_routerlist_from_directory(s, &new_list, pkey)) {
     log_fn(LOG_WARN, "Couldn't parse directory.");
     return -1;
@@ -493,19 +472,6 @@ int router_load_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey)
     log_fn(LOG_WARN, "Error resolving routerlist");
     return -1;
   }
-  if (!is_recommended_version(VERSION, routerlist->software_versions)) {
-    log(options.IgnoreVersion ? LOG_WARN : LOG_ERR,
-     "You are running Tor version %s, which will not work with this network.\n"
-     "Please use %s%s.",
-        VERSION, strchr(routerlist->software_versions,',') ? "one of " : "",
-        routerlist->software_versions);
-    if(options.IgnoreVersion) {
-      log(LOG_WARN, "IgnoreVersion is set. If it breaks, we told you so.");
-    } else {
-      fflush(0);
-      exit(0);
-    }
-  }
   return 0;
 }
 

+ 83 - 0
src/or/routerparse.c

@@ -176,6 +176,89 @@ static int parse_time(const char *cp, time_t *t)
   return 0;
 }
 
+/**
+ * Find the first instance of "recommended-software ...\n" at the start of
+ * a line; return a newly allocated string containing the "..." portion.
+ * Return NULL if no such instance was found.
+ */
+static char *
+get_recommended_software_from_directory(const char *str)
+{
+#define REC "recommended-software "
+  const char *cp = str, *eol;
+  int len = strlen(REC);
+  cp = str;
+  if (strncmp(str, REC, len)==0) {
+    cp += len;
+  } else {
+    cp = strstr(str, "\n"REC);
+    if (!cp)
+      return NULL;
+    cp += len+1;
+  }
+  eol = strchr(cp, '\n');
+  if (!eol)
+    return NULL;
+  return tor_strndup(cp, eol-cp);
+#undef REC
+}
+
+/** Return 1 if myversion is in versionlist. Else return 0.
+ * (versionlist is a comma-separated list of versions.) */
+/* static */ int is_recommended_version(const char *myversion,
+                           const char *versionlist) {
+  int len_myversion = strlen(myversion);
+  char *comma;
+  const char *end = versionlist + strlen(versionlist);
+
+  log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, versionlist);
+
+  for(;;) {
+    comma = strchr(versionlist, ',');
+    if( ((comma ? comma : end) - versionlist == len_myversion) &&
+       !strncmp(versionlist, myversion, len_myversion))
+      /* only do strncmp if the length matches */
+      return 1; /* success, it's there */
+    if(!comma)
+      return 0; /* nope */
+    versionlist = comma+1;
+  }
+}
+
+/* Return 0 if myversion is supported; else log a message and return
+ * -1 (or exit if ignoreversions is false) */
+int check_software_version_against_directory(const char *directory,
+                                             int ignoreversion)
+{
+  char *v;
+  v = get_recommended_software_from_directory(directory);
+  if (!v) {
+    log_fn(LOG_WARN, "No recommended-versions string found in directory");
+    return -1;
+  }
+  /* Look for versions of the form "0.1.0" and of the form "Tor 0.1.0".
+   * Eventually, we should deprecate the first form.
+   */
+  if (is_recommended_version(VERSION, v) ||
+      is_recommended_version("Tor "VERSION, v)) {
+    tor_free(v);
+    return 0;
+  }
+  log(ignoreversion ? LOG_WARN : LOG_ERR,
+     "You are running Tor version %s, which will not work with this network.\n"
+     "Please use %s%s.",
+      VERSION, strchr(v,',') ? "one of " : "", v);
+  tor_free(v);
+
+  if(ignoreversion) {
+    log(LOG_WARN, "IgnoreVersion is set. If it breaks, we told you so.");
+    return -1;
+  } else {
+    fflush(0);
+    exit(0);
+    return -1; /* never reached */
+  }
+}
 
 /** Parse a directory from <b>s</b> and, when done, store the
  * resulting routerlist in *<b>dest</b>, freeing the old value if necessary.

+ 2 - 2
src/or/test.c

@@ -635,8 +635,8 @@ test_onion_handshake() {
   crypto_free_pk_env(pk);
 }
 
-/* from routers.c */
-int is_recommended_version(char *myversion, char *start);
+/* from routerparse.c */
+int is_recommended_version(const char *myversion, const char *start);
 
 void
 test_dir_format()