[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Parsing for DirectoryAuthority
commit bf192cb70a770fe2551add747bbdb6aed2f94d9d
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Thu Oct 4 09:04:53 2012 -0700
Parsing for DirectoryAuthority
Rewriting the parser for the DirectoryAuthority class. Still passes the minimal
descriptor tests so next gonna add the field specific unit tests.
---
stem/descriptor/networkstatus.py | 99 +++++++++++++++++++++++++++-----------
1 files changed, 71 insertions(+), 28 deletions(-)
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 8147a26..c27f587 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -712,8 +712,7 @@ class DirectoryAuthority(stem.descriptor.Descriptor):
self._unrecognized_lines = []
- #self._parse(raw_contents, validate, is_vote)
- self._parse_old(raw_content, validate, is_vote)
+ self._parse(raw_content, validate, is_vote)
def _parse(self, content, validate, is_vote):
"""
@@ -726,22 +725,31 @@ class DirectoryAuthority(stem.descriptor.Descriptor):
:raises: ValueError if a validity check fails
"""
+ # separate the directory authority entry from its key certificate
+ key_cert_content = None
+
+ if is_vote:
+ key_div = content.find('\ndir-key-certificate-version')
+
+ if key_div != -1:
+ key_cert_content = content[key_div + 1:]
+ content = content[:key_div + 1]
+
entries, first_keyword, _, _ = stem.descriptor._get_descriptor_components(content, validate)
if validate and first_keyword != 'dir-source':
raise ValueError("Authority entries are expected to start with a 'dir-source' line:\n%s" % (content))
# check that we have mandatory fields
+
if validate:
required_fields = ["dir-source", "contact"]
- if is_vote:
- pass
- #required_fields += ... god damnit
- else:
+ if is_vote and not key_cert_content:
+ raise ValueError("Authority votes must have a key certificate:\n%s" % content)
+ elif not is_vote:
required_fields += ["vote-digest"]
-
for keyword in required_fields:
if not keyword in entries:
raise ValueError("Authority entries must have a '%s' line:\n%s" % (keyword, content))
@@ -751,27 +759,62 @@ class DirectoryAuthority(stem.descriptor.Descriptor):
line = "%s %s" % (keyword, value)
# all known attributes can only appear at most once
- #if validate and len(values) > 1 and keyword in ('r', 's', 'v', 'w', 'p'):
- # raise ValueError("Router status entries can only have a single '%s' line, got %i:\n%s" % (key, len(values), content))
-
- def _parse_old(self, raw_content, validate, is_vote):
- content = StringIO(raw_content)
- dir_source = _read_keyword_line("dir-source", content, validate)
- self.nickname, self.fingerprint, self.hostname, self.address, self.dir_port, self.or_port = dir_source.split(" ")
- self.dir_port = int(self.dir_port)
- self.or_port = int(self.or_port)
-
- self.contact = _read_keyword_line("contact", content, validate)
- if is_vote:
- self.legacy_dir_key = _read_keyword_line("legacy-dir-key", content, validate, True)
- self.key_certificate = KeyCertificate(content.read(), validate)
- else:
- self.vote_digest = _read_keyword_line("vote-digest", content, True, validate)
-
- remainder = content.read()
+ if validate and len(values) > 1 and keyword in ('dir-source', 'contact', 'legacy-dir-key', 'vote-digest'):
+ raise ValueError("Authority entries can only have a single '%s' line, got %i:\n%s" % (keyword, len(values), content))
+
+ if keyword == 'dir-source':
+ # "dir-source" nickname identity address IP dirport orport
+
+ dir_source_comp = value.split(" ")
+
+ if len(dir_source_comp) < 6:
+ if not validate: continue
+ raise ValueError("Authority entry's 'dir-source' line must have six values: %s" % line)
+
+ if validate:
+ if not stem.util.tor_tools.is_valid_nickname(dir_source_comp[0]):
+ raise ValueError("Authority's nickname is invalid: %s" % dir_source_comp[0])
+ elif not stem.util.tor_tools.is_valid_fingerprint(dir_source_comp[1]):
+ raise ValueError("Authority's fingerprint is invalid: %s" % dir_source_comp[1])
+ elif not stem.util.connection.is_valid_ip_address(dir_source_comp[3]):
+ raise ValueError("Authority's address isn't a valid IPv4 address: %s" % dir_source_comp[3])
+ elif not stem.util.connection.is_valid_port(dir_source_comp[4], allow_zero = True):
+ raise ValueError("Authority's DirPort is invalid: %s" % dir_source_comp[4])
+ elif not stem.util.connection.is_valid_port(dir_source_comp[5]):
+ raise ValueError("Authority's ORPort is invalid: %s" % dir_source_comp[5])
+ elif not (dir_source_comp[4].isdigit() and dir_source_comp[5].isdigit()):
+ continue
+
+ self.nickname = dir_source_comp[0]
+ self.fingerprint = dir_source_comp[1]
+ self.hostname = dir_source_comp[2]
+ self.address = dir_source_comp[3]
+ self.dir_port = None if dir_source_comp[4] == '0' else int(dir_source_comp[4])
+ self.or_port = int(dir_source_comp[5])
+ elif keyword == 'contact':
+ # "contact" string
+
+ self.contact = value
+ elif keyword == 'legacy-dir-key':
+ # "legacy-dir-key" FINGERPRINT
+
+ if validate and not stem.util.tor_tools.is_valid_fingerprint(value):
+ raise ValueError("Authority has a malformed legacy directory key: %s" % line)
+
+ self.legacy_dir_key = value
+ elif keyword == 'vote-digest':
+ # "vote-digest" digest
+
+ # technically not a fingerprint, but has the same characteristics
+ if validate and not stem.util.tor_tools.is_valid_fingerprint(value):
+ raise ValueError("Authority has a malformed vote digest: %s" % line)
+
+ self.vote_digest = value
+ else:
+ self._unrecognized_lines.append(line)
- if remainder:
- self._unrecognized_lines = remainder.split("\n")
+ if key_cert_content:
+ self.key_certificate = KeyCertificate(key_cert_content)
def get_unrecognized_lines(self):
"""
@@ -1081,7 +1124,7 @@ class RouterStatusEntry(stem.descriptor.Descriptor):
if len(r_comp) < 8:
if not validate: continue
- raise ValueError("Router status entry's 'r' line line must have eight values: %s" % line)
+ raise ValueError("Router status entry's 'r' line must have eight values: %s" % line)
if validate:
if not stem.util.tor_tools.is_valid_nickname(r_comp[0]):
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits