[tor-commits] [stem/master] Validating that votes only have a single authority entry

atagar at torproject.org atagar at torproject.org
Tue Aug 20 01:15:15 UTC 2013


commit 4863c2281c26660a249378e65354a00e406fffbc
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon Aug 19 18:15:47 2013 -0700

    Validating that votes only have a single authority entry
    
    Vote documents should only contain an entry from the authority that issued it.
    I was checking this in my consensus-checker monitor but Karsten made the good
    point that the check belongs in stem.
---
 stem/descriptor/networkstatus.py                  |    3 +++
 test/mocking.py                                   |    5 +++++
 test/unit/descriptor/networkstatus/document_v3.py |   21 ++++++++++++++++-----
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 6258fdc..9142e63 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -518,6 +518,9 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
       extra_args = (self._header.is_vote,),
     ))
 
+    if validate and self._header.is_vote and len(self.directory_authorities) != 1:
+      raise ValueError("Votes should only have an authority entry for the one that issued it, got %i: %s" % (len(self.directory_authorities), self.directory_authorities))
+
     if not self._header.is_microdescriptor:
       router_type = stem.descriptor.router_status_entry.RouterStatusEntryV3
     else:
diff --git a/test/mocking.py b/test/mocking.py
index aebbaac..0d0c2e6 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -589,6 +589,11 @@ def get_network_status_document_v3(attr = None, exclude = (), authorities = None
       "consensus-methods": "1 9",
       "published": "2012-09-02 22:00:00",
     }
+
+    # votes need an authority to be valid
+
+    if authorities is None:
+      authorities = [get_directory_authority(is_vote = True)]
   else:
     extra_defaults = {
       "consensus-method": "9",
diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py
index ece95de..71ef8b6 100644
--- a/test/unit/descriptor/networkstatus/document_v3.py
+++ b/test/unit/descriptor/networkstatus/document_v3.py
@@ -105,7 +105,6 @@ class TestNetworkStatusDocument(unittest.TestCase):
     self.assertEqual(expected_known_flags, document.known_flags)
     self.assertEqual({}, document.flag_thresholds)
     self.assertEqual(DEFAULT_PARAMS, document.params)
-    self.assertEqual((), document.directory_authorities)
     self.assertEqual({}, document.bandwidth_weights)
     self.assertEqual([DOC_SIG], document.signatures)
     self.assertEqual([], document.get_unrecognized_lines())
@@ -218,10 +217,12 @@ class TestNetworkStatusDocument(unittest.TestCase):
       lines = get_network_status_document_v3(attr, content = True).split(b"\n")
 
       for index in xrange(len(lines) - 1):
-        # once we reach the crypto blob we're done since swapping those won't
-        # be detected
+        # once we reach the authority entry or later we're done since swapping
+        # those won't be detected
 
-        if lines[index].startswith(stem.util.str_tools._to_bytes(CRYPTO_BLOB[1:10])):
+        if is_consensus and lines[index].startswith(stem.util.str_tools._to_bytes(CRYPTO_BLOB[1:10])):
+          break
+        elif not is_consensus and lines[index].startswith('dir-source'):
           break
 
         # swaps this line with the one after it
@@ -243,6 +244,9 @@ class TestNetworkStatusDocument(unittest.TestCase):
       lines = get_network_status_document_v3(attr, content = True).split(b"\n")
 
       for index, line in enumerate(lines):
+        if not is_consensus and lines[index].startswith('dir-source'):
+          break
+
         # Stop when we hit the 'directory-signature' for a couple reasons...
         # - that is the one field that can validly appear multiple times
         # - after it is a crypto blob, which won't trigger this kind of
@@ -856,7 +860,14 @@ class TestNetworkStatusDocument(unittest.TestCase):
         content = get_network_status_document_v3({"vote-status": vote_status}, authorities = (authority1, authority2), content = True)
 
         if is_document_vote == is_authorities_vote:
-          document = NetworkStatusDocumentV3(content)
+          if is_document_vote:
+            # votes can only have a single authority
+
+            self.assertRaises(ValueError, NetworkStatusDocumentV3, content)
+            document = NetworkStatusDocumentV3(content, validate = False)
+          else:
+            document = NetworkStatusDocumentV3(content)
+
           self.assertEquals((authority1, authority2), document.directory_authorities)
         else:
           # authority votes in a consensus or consensus authorities in a vote



More information about the tor-commits mailing list