commit 4863c2281c26660a249378e65354a00e406fffbc Author: Damian Johnson atagar@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
tor-commits@lists.torproject.org