[tor-commits] [stem/master] Parse version field

atagar at torproject.org atagar at torproject.org
Sun Aug 25 00:20:44 UTC 2019


commit e47abb9f6ed81f39bcb09cd4e8bfb202488f695f
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Aug 22 16:48:04 2019 -0700

    Parse version field
    
    Trivial parsing for the first field. Mostly still just wiring things up.
---
 stem/descriptor/hidden_service.py         | 49 ++++++++++++++++++++++++++++++-
 test/unit/descriptor/hidden_service_v3.py | 34 ++++++++++++++++++---
 2 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index 1ed100ef..4baad548 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -145,7 +145,14 @@ def _parse_file(descriptor_file, desc_type = None, validate = False, **kwargs):
 
 
 def _parse_version_line(descriptor, entries):
-  value = _value('version', entries)
+  if isinstance(descriptor, HiddenServiceDescriptorV2):
+    keyword = 'version'
+  elif isinstance(descriptor, HiddenServiceDescriptorV3):
+    keyword = 'hs-descriptor'
+  else:
+    raise ValueError('BUG: unexpected descriptor type (%s)' % type(descriptor).__name__)
+
+  value = _value(keyword, entries)
 
   if value.isdigit():
     descriptor.version = int(value)
@@ -463,12 +470,52 @@ class HiddenServiceDescriptorV2(BaseHiddenServiceDescriptor):
 class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
   """
   Version 3 hidden service descriptor.
+
+  :var int version: **\\*** hidden service descriptor version
+
+  **\\*** attribute is either required when we're parsed with validation or has
+  a default value, others are left as **None** if undefined
   """
 
   # TODO: requested this @type on https://trac.torproject.org/projects/tor/ticket/31481
 
   TYPE_ANNOTATION_NAME = 'hidden-service-descriptor-3'
 
+  ATTRIBUTES = {
+    'version': (None, _parse_version_line),
+  }
+
+  PARSER_FOR_LINE = {
+    'hs-descriptor': _parse_version_line,
+  }
+
+  @classmethod
+  def content(cls, attr = None, exclude = (), sign = False):
+    if sign:
+      raise NotImplementedError('Signing of %s not implemented' % cls.__name__)
+
+    return _descriptor_content(attr, exclude, (
+      ('hs-descriptor', '3'),
+      ('descriptor-lifetime', '180'),
+      ('descriptor-signing-key-cert', _random_crypto_blob('ED25519 CERT')),
+      ('revision-counter', '15'),
+      ('superencrypted', _random_crypto_blob('MESSAGE')),
+      ('signature', 'wdc7ffr+dPZJ/mIQ1l4WYqNABcmsm6SHW/NL3M3wG7bjjqOJWoPR5TimUXxH52n5Zk0Gc7hl/hz3YYmAx5MvAg'),
+    ), ())
+
+  @classmethod
+  def create(cls, attr = None, exclude = (), validate = True, sign = False):
+    return cls(cls.content(attr, exclude, sign), validate = validate, skip_crypto_validation = not sign)
+
+  def __init__(self, raw_contents, validate = False, skip_crypto_validation = False):
+    super(HiddenServiceDescriptorV3, self).__init__(raw_contents, lazy_load = not validate)
+    entries = _descriptor_components(raw_contents, validate)
+
+    if validate:
+      self._parse(entries, validate)
+    else:
+      self._entries = entries
+
 
 # TODO: drop this alias in stem 2.x
 
diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py
index 757c1944..04a95a6d 100644
--- a/test/unit/descriptor/hidden_service_v3.py
+++ b/test/unit/descriptor/hidden_service_v3.py
@@ -2,18 +2,44 @@
 Unit tests for stem.descriptor.hidden_service for version 3.
 """
 
+import functools
 import unittest
 
 import stem.descriptor
 
-from test.unit.descriptor import get_resource
+from stem.descriptor.hidden_service import HiddenServiceDescriptorV3
+
+from test.unit.descriptor import (
+  get_resource,
+  base_expect_invalid_attr,
+)
+
+expect_invalid_attr = functools.partial(base_expect_invalid_attr, HiddenServiceDescriptorV3, 'version', 3)
 
 
 class TestHiddenServiceDescriptorV3(unittest.TestCase):
-  def test_stub(self):
-    # TODO: replace with actual field assertions as the class gets implemented
+  def test_for_riseup(self):
+    """
+    Parse riseup's descriptor...
+
+      vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion
+    """
 
     with open(get_resource('hidden_service_v3'), 'rb') as descriptor_file:
       desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor-3 1.0', validate = True))
 
-    self.assertTrue('hs-descriptor 3' in str(desc))
+    self.assertEqual(3, desc.version)
+
+  def test_invalid_version(self):
+    """
+    Checks that our version field expects a numeric value.
+    """
+
+    test_values = (
+      '',
+      '-10',
+      'hello',
+    )
+
+    for test_value in test_values:
+      expect_invalid_attr(self, {'hs-descriptor': test_value}, 'version')





More information about the tor-commits mailing list