Explorar o código

Merge branch 'fix_routerparse_bug'

Nick Mathewson %!s(int64=14) %!d(string=hai) anos
pai
achega
9caecc1e48
Modificáronse 2 ficheiros con 31 adicións e 23 borrados
  1. 3 1
      ChangeLog
  2. 28 22
      src/or/routerparse.c

+ 3 - 1
ChangeLog

@@ -5,7 +5,9 @@ Changes in version 0.2.2.10-alpha - 2010-??-??
       and Guard+Exit flagged nodes for entry, middle, and exit positions.
       and Guard+Exit flagged nodes for entry, middle, and exit positions.
       This should more evenly distribute the network load across these
       This should more evenly distribute the network load across these
       different types of nodes, and give us the flexibility to globally
       different types of nodes, and give us the flexibility to globally
-      alter our node selection algorithms in the future.
+      alter our node selection algorithms in the future.  Extra thanks
+      to "outofwords" for finding some nasty security bugs in the
+      first implementation of this.
 
 
   o Minor features (performance):
   o Minor features (performance):
     - Always perform router selections using weighted node bandwidth,
     - Always perform router selections using weighted node bandwidth,

+ 28 - 22
src/or/routerparse.c

@@ -114,6 +114,7 @@ typedef enum {
   K_CONSENSUS_METHODS,
   K_CONSENSUS_METHODS,
   K_CONSENSUS_METHOD,
   K_CONSENSUS_METHOD,
   K_LEGACY_DIR_KEY,
   K_LEGACY_DIR_KEY,
+  K_DIRECTORY_FOOTER,
 
 
   A_PURPOSE,
   A_PURPOSE,
   A_LAST_LISTED,
   A_LAST_LISTED,
@@ -488,8 +489,9 @@ static token_rule_t networkstatus_consensus_token_table[] = {
 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
  * footers. */
  * footers. */
 static token_rule_t networkstatus_vote_footer_token_table[] = {
 static token_rule_t networkstatus_vote_footer_token_table[] = {
-  T01("bandwidth-weights",   K_BW_WEIGHTS,          ARGS,        NO_OBJ ),
-  T(  "directory-signature", K_DIRECTORY_SIGNATURE, GE(2),   NEED_OBJ ),
+  T01("directory-footer",    K_DIRECTORY_FOOTER,    NO_ARGS,   NO_OBJ ),
+  T01("bandwidth-weights",   K_BW_WEIGHTS,          ARGS,      NO_OBJ ),
+  T(  "directory-signature", K_DIRECTORY_SIGNATURE, GE(2),     NEED_OBJ ),
   END_OF_TABLE
   END_OF_TABLE
 };
 };
 
 
@@ -1878,26 +1880,23 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
 static INLINE const char *
 static INLINE const char *
 find_start_of_next_routerstatus(const char *s)
 find_start_of_next_routerstatus(const char *s)
 {
 {
-  const char *eos = strstr(s, "\nr ");
-  if (eos) {
-    const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-footer\n");
-    if (eos2) eos2 += strlen("\ndirectory-footer");
-    else eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
-    /* Technically we are returning either the start of the next
-     * routerstatus AFTER the \n, or the start of the next consensus
-     * line AT the \n. This seems asymmetric, but leaving it that way
-     * for now for stability. */
-    if (eos2 && eos2 < eos)
-      return eos2;
-    else
-      return eos+1;
-  } else {
-    if ((eos = strstr(s, "\ndirectory-footer\n")))
-      return eos+strlen("\ndirectory-footer\n");
-    if ((eos = strstr(s, "\ndirectory-signature")))
-      return eos+1;
-     return s + strlen(s);
-  }
+  const char *eos, *footer, *sig;
+  if ((eos = strstr(s, "\nr ")))
+    ++eos;
+  else
+    eos = s + strlen(s);
+
+  footer = tor_memstr(s, eos-s, "\ndirectory-footer");
+  sig = tor_memstr(s, eos-s, "\ndirectory-signature");
+
+  if (footer && sig)
+    return MIN(footer, sig) + 1;
+  else if (footer)
+    return footer+1;
+  else if (sig)
+    return sig+1;
+  else
+    return eos;
 }
 }
 
 
 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
@@ -3092,6 +3091,13 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
     } SMARTLIST_FOREACH_END(_tok);
     } SMARTLIST_FOREACH_END(_tok);
   }
   }
 
 
+  if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
+    if (tok != smartlist_get(footer_tokens, 0)) {
+      log_warn(LD_DIR, "Misplaced directory-footer token");
+      goto err;
+    }
+  }
+
   tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
   tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
   if (tok) {
   if (tok) {
     ns->weight_params = smartlist_create();
     ns->weight_params = smartlist_create();