ソースを参照

Merge branch 'bug21278_redux_029_squashed' into maint-0.2.9

Nick Mathewson 7 年 前
コミット
ec6b5a098d
4 ファイル変更72 行追加17 行削除
  1. 4 0
      changes/bug21278_prevention
  2. 10 0
      src/or/dirserv.c
  3. 55 17
      src/or/routerparse.c
  4. 3 0
      src/or/routerparse.h

+ 4 - 0
changes/bug21278_prevention

@@ -0,0 +1,4 @@
+  o Minor features (directory authority):
+    - Directory authorities now reject descriptors that claim to be
+      malformed versions of Tor. Helps prevent exploitation of bug 21278.
+      

+ 10 - 0
src/or/dirserv.c

@@ -365,6 +365,16 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
             strmap_size(fingerprint_list->fp_by_name),
             digestmap_size(fingerprint_list->status_by_digest));
 
+  if (platform) {
+    tor_version_t ver_tmp;
+    if (tor_version_parse_platform(platform, &ver_tmp, 1) < 0) {
+      if (msg) {
+        *msg = "Malformed platform string.";
+      }
+      return FP_REJECT;
+    }
+  }
+
   /* Versions before Tor 0.2.4.18-rc are too old to support, and are
    * missing some important security fixes too. Disable them. */
   if (platform && !tor_version_as_new_as(platform,"0.2.4.18-rc")) {

+ 55 - 17
src/or/routerparse.c

@@ -5512,40 +5512,78 @@ microdescs_parse_from_string(const char *s, const char *eos,
   return result;
 }
 
-/** Parse the Tor version of the platform string <b>platform</b>,
- * and compare it to the version in <b>cutoff</b>. Return 1 if
- * the router is at least as new as the cutoff, else return 0.
+/** Extract a Tor version from a <b>platform</b> line from a router
+ * descriptor, and place the result in <b>router_version</b>.
+ *
+ * Return 1 on success, -1 on parsing failure, and 0 if the
+ * platform line does not indicate some version of Tor.
+ *
+ * If <b>strict</b> is non-zero, finding any weird version components
+ * (like negative numbers) counts as a parsing failure.
  */
 int
-tor_version_as_new_as(const char *platform, const char *cutoff)
+tor_version_parse_platform(const char *platform,
+                           tor_version_t *router_version,
+                           int strict)
 {
-  tor_version_t cutoff_version, router_version;
-  char *s, *s2, *start;
   char tmp[128];
+  char *s, *s2, *start;
 
-  tor_assert(platform);
-
-  if (tor_version_parse(cutoff, &cutoff_version)<0) {
-    log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
+  if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; say 0. */
     return 0;
-  }
-  if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
-    return 1;
 
   start = (char *)eat_whitespace(platform+3);
-  if (!*start) return 0;
+  if (!*start) return -1;
   s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
   s2 = (char*)eat_whitespace(s);
   if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
     s = (char*)find_whitespace(s2);
 
   if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
-    return 0;
+    return -1;
   strlcpy(tmp, start, s-start+1);
 
-  if (tor_version_parse(tmp, &router_version)<0) {
+  if (tor_version_parse(tmp, router_version)<0) {
     log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
-    return 1; /* be safe and say yes */
+    return -1;
+  }
+
+  if (strict) {
+    if (router_version->major < 0 ||
+        router_version->minor < 0 ||
+        router_version->minor < 0 ||
+        router_version->patchlevel < 0 ||
+        router_version->svn_revision < 0) {
+      return -1;
+    }
+  }
+
+  return 1;
+}
+
+/** Parse the Tor version of the platform string <b>platform</b>,
+ * and compare it to the version in <b>cutoff</b>. Return 1 if
+ * the router is at least as new as the cutoff, else return 0.
+ */
+int
+tor_version_as_new_as(const char *platform, const char *cutoff)
+{
+  tor_version_t cutoff_version, router_version;
+  int r;
+  tor_assert(platform);
+
+  if (tor_version_parse(cutoff, &cutoff_version)<0) {
+    log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
+    return 0;
+  }
+
+  r = tor_version_parse_platform(platform, &router_version, 0);
+  if (r == 0) {
+    /* nonstandard Tor; be safe and say yes */
+    return 1;
+  } else if (r < 0) {
+    /* unparseable version; be safe and say yes. */
+    return 1;
   }
 
   /* Here's why we don't need to do any special handling for svn revisions:

+ 3 - 0
src/or/routerparse.h

@@ -45,6 +45,9 @@ MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
          (const char *s, int assume_action, int *malformed_list));
 version_status_t tor_version_is_obsolete(const char *myversion,
                                          const char *versionlist);
+int tor_version_parse_platform(const char *platform,
+                               tor_version_t *version_out,
+                               int strict);
 int tor_version_as_new_as(const char *platform, const char *cutoff);
 int tor_version_parse(const char *s, tor_version_t *out);
 int tor_version_compare(tor_version_t *a, tor_version_t *b);