[tor-commits] [stem/master] Stub hidden service descriptor v3

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


commit 26ed95d4b09505fa1320b0e8de0cc271776fe95d
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Aug 22 15:55:46 2019 -0700

    Stub hidden service descriptor v3
    
    Doesn't do anything yet - just getting the class and such wired up.
---
 stem/descriptor/__init__.py                 |  13 +-
 stem/descriptor/hidden_service.py           |  32 +++-
 test/settings.cfg                           |   1 +
 test/unit/descriptor/data/hidden_service_v3 | 223 ++++++++++++++++++++++++++++
 test/unit/descriptor/hidden_service_v2.py   |  26 ++--
 test/unit/descriptor/hidden_service_v3.py   |  19 +++
 6 files changed, 288 insertions(+), 26 deletions(-)

diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
index 9415454c..1b5e53bc 100644
--- a/stem/descriptor/__init__.py
+++ b/stem/descriptor/__init__.py
@@ -532,18 +532,19 @@ def _parse_metrics_file(descriptor_type, major_version, minor_version, descripto
     for desc in stem.descriptor.networkstatus._parse_file(descriptor_file, document_type, validate = validate, document_handler = document_handler, **kwargs):
       yield desc
   elif descriptor_type == stem.descriptor.tordnsel.TorDNSEL.TYPE_ANNOTATION_NAME and major_version == 1:
-    document_type = stem.descriptor.tordnsel.TorDNSEL
-
     for desc in stem.descriptor.tordnsel._parse_file(descriptor_file, validate = validate, **kwargs):
       yield desc
   elif descriptor_type == stem.descriptor.hidden_service.HiddenServiceDescriptorV2.TYPE_ANNOTATION_NAME and major_version == 1:
-    document_type = stem.descriptor.hidden_service.HiddenServiceDescriptorV2
+    desc_type = stem.descriptor.hidden_service.HiddenServiceDescriptorV2
 
-    for desc in stem.descriptor.hidden_service._parse_file(descriptor_file, validate = validate, **kwargs):
+    for desc in stem.descriptor.hidden_service._parse_file(descriptor_file, desc_type, validate = validate, **kwargs):
       yield desc
-  elif descriptor_type == stem.descriptor.bandwidth_file.BandwidthFile.TYPE_ANNOTATION_NAME and major_version == 1:
-    document_type = stem.descriptor.bandwidth_file.BandwidthFile
+  elif descriptor_type == stem.descriptor.hidden_service.HiddenServiceDescriptorV3.TYPE_ANNOTATION_NAME and major_version == 1:
+    desc_type = stem.descriptor.hidden_service.HiddenServiceDescriptorV3
 
+    for desc in stem.descriptor.hidden_service._parse_file(descriptor_file, desc_type, validate = validate, **kwargs):
+      yield desc
+  elif descriptor_type == stem.descriptor.bandwidth_file.BandwidthFile.TYPE_ANNOTATION_NAME and major_version == 1:
     for desc in stem.descriptor.bandwidth_file._parse_file(descriptor_file, validate = validate, **kwargs):
       yield desc
   else:
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index ab5699f6..1ed100ef 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -17,7 +17,8 @@ These are only available through the Controller's
 ::
 
   BaseHiddenServiceDescriptor - Common parent for hidden service descriptors
-    +- HiddenServiceDescriptorV2 - Version 2 hidden service descriptor
+    |- HiddenServiceDescriptorV2 - Version 2 hidden service descriptor
+    +- HiddenServiceDescriptorV3 - Version 3 hidden service descriptor
 
 .. versionadded:: 1.4.0
 """
@@ -103,11 +104,12 @@ class DecryptionFailure(Exception):
   """
 
 
-def _parse_file(descriptor_file, validate = False, **kwargs):
+def _parse_file(descriptor_file, desc_type = None, validate = False, **kwargs):
   """
   Iterates over the hidden service descriptors in a file.
 
   :param file descriptor_file: file with descriptor content
+  :param class desc_type: BaseHiddenServiceDescriptor subclass
   :param bool validate: checks the validity of the descriptor's content if
     **True**, skips these checks otherwise
   :param dict kwargs: additional arguments for the descriptor constructor
@@ -120,18 +122,24 @@ def _parse_file(descriptor_file, validate = False, **kwargs):
     * **IOError** if the file can't be read
   """
 
+  if desc_type is None:
+    desc_type = HiddenServiceDescriptorV2
+
+  # Hidden service v3 ends with a signature line, whereas v2 has a pgp style
+  # block following it.
+
   while True:
     descriptor_content = _read_until_keywords('signature', descriptor_file)
 
-    # we've reached the 'signature', now include the pgp style block
-    block_end_prefix = PGP_BLOCK_END.split(' ', 1)[0]
-    descriptor_content += _read_until_keywords(block_end_prefix, descriptor_file, True)
+    if desc_type == HiddenServiceDescriptorV2:
+      block_end_prefix = PGP_BLOCK_END.split(' ', 1)[0]
+      descriptor_content += _read_until_keywords(block_end_prefix, descriptor_file, True)
 
     if descriptor_content:
       if descriptor_content[0].startswith(b'@type'):
         descriptor_content = descriptor_content[1:]
 
-      yield HiddenServiceDescriptorV2(bytes.join(b'', descriptor_content), validate, **kwargs)
+      yield desc_type(bytes.join(b'', descriptor_content), validate, **kwargs)
     else:
       break  # done parsing file
 
@@ -194,7 +202,7 @@ class BaseHiddenServiceDescriptor(Descriptor):
 
 class HiddenServiceDescriptorV2(BaseHiddenServiceDescriptor):
   """
-  Hidden service descriptor.
+  Version 2 hidden service descriptor.
 
   :var str descriptor_id: **\\*** identifier for this descriptor, this is a base32 hash of several fields
   :var int version: **\\*** hidden service descriptor version
@@ -452,6 +460,16 @@ class HiddenServiceDescriptorV2(BaseHiddenServiceDescriptor):
     return introduction_points
 
 
+class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
+  """
+  Version 3 hidden service descriptor.
+  """
+
+  # TODO: requested this @type on https://trac.torproject.org/projects/tor/ticket/31481
+
+  TYPE_ANNOTATION_NAME = 'hidden-service-descriptor-3'
+
+
 # TODO: drop this alias in stem 2.x
 
 HiddenServiceDescriptor = HiddenServiceDescriptorV2
diff --git a/test/settings.cfg b/test/settings.cfg
index 2e6b29dd..1b971bb4 100644
--- a/test/settings.cfg
+++ b/test/settings.cfg
@@ -259,6 +259,7 @@ test.unit_tests
 |test.unit.descriptor.networkstatus.document_v3.TestNetworkStatusDocument
 |test.unit.descriptor.networkstatus.bridge_document.TestBridgeNetworkStatusDocument
 |test.unit.descriptor.hidden_service_v2.TestHiddenServiceDescriptorV2
+|test.unit.descriptor.hidden_service_v3.TestHiddenServiceDescriptorV3
 |test.unit.descriptor.certificate.TestEd25519Certificate
 |test.unit.descriptor.bandwidth_file.TestBandwidthFile
 |test.unit.exit_policy.rule.TestExitPolicyRule
diff --git a/test/unit/descriptor/data/hidden_service_v3 b/test/unit/descriptor/data/hidden_service_v3
new file mode 100644
index 00000000..c67ae292
--- /dev/null
+++ b/test/unit/descriptor/data/hidden_service_v3
@@ -0,0 +1,223 @@
+hs-descriptor 3
+descriptor-lifetime 180
+descriptor-signing-key-cert
+-----BEGIN ED25519 CERT-----
+AQgABqKwAQVql1QZETyEwJjg+Cv6f2w/cp+c3juj01NPBaJqihboAQAgBACx+FKK
+oDrFE1+ztSxzN8sApKOb5UuDtoe/E03DxZU5+r/K5AV6G0hYn21V7Xbu2pZHvIkT
+2oVY4hypWNJE58eFBRFRzBA0J2h0GyFs1pIuRh5QDJuxB5j92V0aRCNZFgM=
+-----END ED25519 CERT-----
+revision-counter 15
+superencrypted
+-----BEGIN MESSAGE-----
+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
+usMPytqLsZg2WXj4ikmGug==
+-----END MESSAGE-----
+signature wdc7ffr+dPZJ/mIQ1l4WYqNABcmsm6SHW/NL3M3wG7bjjqOJWoPR5TimUXxH52n5Zk0Gc7hl/hz3YYmAx5MvAg
diff --git a/test/unit/descriptor/hidden_service_v2.py b/test/unit/descriptor/hidden_service_v2.py
index 8442376b..ac64fa19 100644
--- a/test/unit/descriptor/hidden_service_v2.py
+++ b/test/unit/descriptor/hidden_service_v2.py
@@ -1,5 +1,5 @@
 """
-Unit tests for stem.descriptor.hidden_service.
+Unit tests for stem.descriptor.hidden_service for version 2.
 """
 
 import datetime
@@ -250,27 +250,27 @@ class TestHiddenServiceDescriptorV2(unittest.TestCase):
     Parse duckduckgo's descriptor.
     """
 
-    descriptor_file = open(get_resource('hidden_service_duckduckgo'), 'rb')
-    desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
-    self._assert_matches_duckduckgo(desc)
+    with open(get_resource('hidden_service_duckduckgo'), 'rb') as descriptor_file:
+      desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
+      self._assert_matches_duckduckgo(desc)
 
   def test_for_duckduckgo_without_validation(self):
     """
     Parse duckduckgo's descriptor
     """
 
-    descriptor_file = open(get_resource('hidden_service_duckduckgo'), 'rb')
-    desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = False))
-    self._assert_matches_duckduckgo(desc)
+    with open(get_resource('hidden_service_duckduckgo'), 'rb') as descriptor_file:
+      desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = False))
+      self._assert_matches_duckduckgo(desc)
 
   def test_for_facebook(self):
     """
     Parse facebook's descriptor.
     """
 
-    descriptor_file = open(get_resource('hidden_service_facebook'), 'rb')
+    with open(get_resource('hidden_service_facebook'), 'rb') as descriptor_file:
+      desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
 
-    desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
     self.assertEqual('utjk4arxqg6s6zzo7n6cjnq6ot34udhr', desc.descriptor_id)
     self.assertEqual(2, desc.version)
     self.assertEqual('6355jaerje3bqozopwq2qmpf4iviizdn', desc.secret_id_part)
@@ -287,9 +287,9 @@ class TestHiddenServiceDescriptorV2(unittest.TestCase):
     Parse a descriptor with introduction-points encrypted with basic auth.
     """
 
-    descriptor_file = open(get_resource('hidden_service_basic_auth'), 'rb')
+    with open(get_resource('hidden_service_basic_auth'), 'rb') as descriptor_file:
+      desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
 
-    desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
     self.assertEqual('yfmvdrkdbyquyqk5vygyeylgj2qmrvrd', desc.descriptor_id)
     self.assertEqual(2, desc.version)
     self.assertEqual('fluw7z3s5cghuuirq3imh5jjj5ljips6', desc.secret_id_part)
@@ -334,9 +334,9 @@ class TestHiddenServiceDescriptorV2(unittest.TestCase):
     Parse a descriptor with introduction-points encrypted with stealth auth.
     """
 
-    descriptor_file = open(get_resource('hidden_service_stealth_auth'), 'rb')
+    with open(get_resource('hidden_service_stealth_auth'), 'rb') as descriptor_file:
+      desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
 
-    desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor 1.0', validate = True))
     self.assertEqual('ubf3xeibzlfil6s4larq6y5peup2z3oj', desc.descriptor_id)
     self.assertEqual(2, desc.version)
     self.assertEqual('jczvydhzetbpdiylj3d5nsnjvaigs7xm', desc.secret_id_part)
diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py
new file mode 100644
index 00000000..757c1944
--- /dev/null
+++ b/test/unit/descriptor/hidden_service_v3.py
@@ -0,0 +1,19 @@
+"""
+Unit tests for stem.descriptor.hidden_service for version 3.
+"""
+
+import unittest
+
+import stem.descriptor
+
+from test.unit.descriptor import get_resource
+
+
+class TestHiddenServiceDescriptorV3(unittest.TestCase):
+  def test_stub(self):
+    # TODO: replace with actual field assertions as the class gets implemented
+
+    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))





More information about the tor-commits mailing list