[tor-commits] [stem/master] Supporting footers in pre-version 9 method documents
atagar at torproject.org
atagar at torproject.org
Sat Jan 12 18:50:02 UTC 2013
commit 98a8842c9ab800f9891a01caf35d02f2dfc60809
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Jan 12 10:46:39 2013 -0800
Supporting footers in pre-version 9 method documents
All version 3 network status documents can have a footer. The caveat is that
prior to consensus method 9 they just contained signatures, and after that they
were a properly marked 'directory-footer' section.
Reproed the issue that Karsten discovered in 'https://trac.torproject.org/7932'
via our unit tests then fixed.
---
stem/descriptor/networkstatus.py | 22 +++++++++++++++-----
test/mocking.py | 22 +++++++++++++++++++-
test/unit/descriptor/networkstatus/document_v3.py | 17 ++++++++++++++++
3 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index e3d5779..cef668a 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -115,7 +115,7 @@ HEADER_STATUS_DOCUMENT_FIELDS = (
)
FOOTER_STATUS_DOCUMENT_FIELDS = (
- ("directory-footer", True, True, True),
+ ("directory-footer", True, True, False),
("bandwidth-weights", False, True, False),
("directory-signature", True, True, True),
)
@@ -482,7 +482,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
validate,
entry_class = DirectoryAuthority,
entry_keyword = AUTH_START,
- section_end_keywords = (ROUTERS_START, FOOTER_START),
+ section_end_keywords = (ROUTERS_START, FOOTER_START, V2_FOOTER_START),
extra_args = (self._header.is_vote,),
))
@@ -496,7 +496,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
validate,
entry_class = router_type,
entry_keyword = ROUTERS_START,
- section_end_keywords = (FOOTER_START,),
+ section_end_keywords = (FOOTER_START, V2_FOOTER_START),
extra_args = (self,),
))
@@ -746,15 +746,25 @@ class _DocumentFooter(object):
self._unrecognized_lines = []
content = document_file.read()
- if validate and content and not header.meets_consensus_method(9):
- raise ValueError("Network status document's footer should only appear in consensus-method 9 or later")
- elif not content and not header.meets_consensus_method(9):
+
+ if not content:
return # footer is optional and there's nothing to parse
entries = stem.descriptor._get_descriptor_components(content, validate)
self._parse(entries, validate, header)
if validate:
+ # Check that the footer has the right initial line. Prior to consensus
+ # method 9 it's a 'directory-signature' and after that footers start with
+ # 'directory-footer'.
+
+ if header.meets_consensus_method(9):
+ if entries.keys()[0] != 'directory-footer':
+ raise ValueError("Network status document's footer should start with a 'directory-footer' line in consensus-method 9 or later")
+ else:
+ if entries.keys()[0] != 'directory-signature':
+ raise ValueError("Network status document's footer should start with a 'directory-signature' line prior to consensus-method 9")
+
_check_for_missing_and_disallowed_fields(header, entries, FOOTER_STATUS_DOCUMENT_FIELDS)
_check_for_misordered_fields(entries, FOOTER_FIELDS)
diff --git a/test/mocking.py b/test/mocking.py
index e92bacd..82b9790 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -864,12 +864,30 @@ def get_network_status_document_v3(attr = None, exclude = (), authorities = None
# inject the authorities and/or routers between the header and footer
if authorities:
- footer_div = desc_content.find("\ndirectory-footer") + 1
+ if "directory-footer" in desc_content:
+ footer_div = desc_content.find("\ndirectory-footer") + 1
+ elif "directory-signature" in desc_content:
+ footer_div = desc_content.find("\ndirectory-signature") + 1
+ else:
+ if routers:
+ desc_content += "\n"
+
+ footer_div = len(desc_content) + 1
+
authority_content = "\n".join([str(a) for a in authorities]) + "\n"
desc_content = desc_content[:footer_div] + authority_content + desc_content[footer_div:]
if routers:
- footer_div = desc_content.find("\ndirectory-footer") + 1
+ if "directory-footer" in desc_content:
+ footer_div = desc_content.find("\ndirectory-footer") + 1
+ elif "directory-signature" in desc_content:
+ footer_div = desc_content.find("\ndirectory-signature") + 1
+ else:
+ if routers:
+ desc_content += "\n"
+
+ footer_div = len(desc_content) + 1
+
router_content = "\n".join([str(r) for r in routers]) + "\n"
desc_content = desc_content[:footer_div] + router_content + desc_content[footer_div:]
diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py
index 42603b1..4ea6347 100644
--- a/test/unit/descriptor/networkstatus/document_v3.py
+++ b/test/unit/descriptor/networkstatus/document_v3.py
@@ -549,6 +549,23 @@ class TestNetworkStatusDocument(unittest.TestCase):
self.assertEqual([], document.signatures)
self.assertEqual([], document.get_unrecognized_lines())
+ # Prior to conensus method 9 votes can still have a signature in their
+ # footer...
+ #
+ # https://trac.torproject.org/7932
+
+ document = get_network_status_document_v3(
+ {
+ "vote-status": "vote",
+ "consensus-methods": "1 8",
+ },
+ exclude = ("directory-footer",),
+ authorities = (get_directory_authority(is_vote = True),)
+ )
+
+ self.assertEqual([DOC_SIG], document.signatures)
+ self.assertEqual([], document.get_unrecognized_lines())
+
def test_footer_with_value(self):
"""
Tries to parse a descriptor with content on the 'directory-footer' line.
More information about the tor-commits
mailing list