[tor-commits] [stem/master] Change extension flags to an enum list

atagar at torproject.org atagar at torproject.org
Thu Mar 30 04:18:03 UTC 2017


commit ff1641d5d27deaa735ffd78727922bcfa6f3e1a0
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Mar 26 16:29:42 2017 +0200

    Change extension flags to an enum list
    
    Seems they're going for unix permission style flag encoding in the int so we
    should include a proper splitting of the attributes. We can't know yet what
    future flags will be so gotta keep the int around too.
---
 stem/descriptor/certificate.py      | 28 +++++++++++++++++++++++++---
 test/unit/descriptor/certificate.py | 10 +++++-----
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index 52bb33b..e1d75bb 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -26,6 +26,17 @@ to sign server descriptors.
   **LINK_CERT**   TLS link certificate signed with ed25519 signing key
   **AUTH**        authentication key signed with ed25519 signing key
   ==============  ===========
+
+.. data::ExtensionFlag (enum)
+
+  Flags that can be assigned to Ed25519 certificate extensions.
+
+  ====================  ===========
+  ExtensionFlag         Description
+  ====================  ===========
+  AFFECTS_VALIDATION    extension affects whether the certificate is valid
+  UNKNOWN               extension includes flags not yet recognized by stem
+  ====================  ===========
 """
 
 import base64
@@ -38,6 +49,7 @@ ED25519_HEADER_LENGTH = 40
 ED25519_SIGNATURE_LENGTH = 64
 
 CertType = enum.UppercaseEnum('SIGNING', 'LINK_CERT', 'AUTH')
+ExtensionFlag = enum.UppercaseEnum('AFFECTS_VALIDATION', 'UNKNOWN')
 
 
 class Ed25519Certificate(object):
@@ -138,19 +150,29 @@ class Ed25519CertificateV1(Ed25519Certificate):
       if extension_length != len(extension_data):
         raise ValueError("Ed25519 extension is truncated. It should have %i bytes of data but there's only %i." % (extension_length, len(extension_data)))
 
-      self.extensions.append(Ed25519Extension(extension_type, extension_flags, extension_data))
+      flags, remaining_flags = [], extension_flags
+
+      if remaining_flags % 2 == 1:
+        flags.append(ExtensionFlag.AFFECTS_VALIDATION)
+        remaining_flags -= 1
+
+      if remaining_flags:
+        flags.append(ExtensionFlag.UNKNOWN)
+
+      self.extensions.append(Ed25519Extension(extension_type, flags, extension_flags, extension_data))
       remaining_data = remaining_data[4 + extension_length:]
 
     if remaining_data:
       raise ValueError('Ed25519 certificate had %i bytes of unused extension data' % len(remaining_data))
 
 
-class Ed25519Extension(collections.namedtuple('Ed25519Extension', ['extension_type', 'flags', 'data'])):
+class Ed25519Extension(collections.namedtuple('Ed25519Extension', ['extension_type', 'flags', 'flag_int', 'data'])):
   """
   Extension within an Ed25519 certificate.
 
   :var int extension_type: extension type
-  :var int flags: extension attributes
+  :var list flags: extension attribute flags
+  :var int flag_int: integer encoding of the extension attribute flags
   :var bytes data: data the extension concerns
   """
 
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
index fde7fa3..5728711 100644
--- a/test/unit/descriptor/certificate.py
+++ b/test/unit/descriptor/certificate.py
@@ -11,7 +11,7 @@ import stem.descriptor.certificate
 import stem.prereq
 import test.runner
 
-from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, CertType, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
+from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, CertType, ExtensionFlag, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
 
 ED25519_CERT = """
 AQQABhtZAaW2GoBED1IjY3A6f6GNqBEl5A83fD2Za9upGke51JGqAQAgBABnprVR
@@ -41,7 +41,7 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertRaisesRegexp(ValueError, re.escape(exc_msg), Ed25519Certificate.parse, parse_arg)
 
   def test_basic_parsing(self):
-    cert_bytes = certificate(extension_data = [b'\x00\x02\x04\x07\x15\x12', b'\x00\x00\x05\x03'])
+    cert_bytes = certificate(extension_data = [b'\x00\x02\x04\x07\x15\x12', b'\x00\x00\x05\x04'])
     cert = Ed25519Certificate.parse(cert_bytes)
 
     self.assertEqual(Ed25519CertificateV1, type(cert))
@@ -54,8 +54,8 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertEqual(b'\x01' * ED25519_SIGNATURE_LENGTH, cert.signature)
 
     self.assertEqual([
-      Ed25519Extension(extension_type = 4, flags = 7, data = b'\x15\x12'),
-      Ed25519Extension(extension_type = 5, flags = 3, data = b''),
+      Ed25519Extension(extension_type = 4, flags = [ExtensionFlag.AFFECTS_VALIDATION, ExtensionFlag.UNKNOWN], flag_int = 7, data = b'\x15\x12'),
+      Ed25519Extension(extension_type = 5, flags = [ExtensionFlag.UNKNOWN], flag_int = 4, data = b''),
     ], cert.extensions)
 
   def test_with_real_cert(self):
@@ -68,7 +68,7 @@ class TestEd25519Certificate(unittest.TestCase):
     self.assertEqual(datetime.datetime(2015, 8, 28, 19, 0), cert.expiration)
     self.assertEqual(1, cert.key_type)
     self.assertEqual(EXPECTED_CERT_KEY, cert.key)
-    self.assertEqual([Ed25519Extension(extension_type = 4, flags = 0, data = EXPECTED_EXTENSION_DATA)], cert.extensions)
+    self.assertEqual([Ed25519Extension(extension_type = 4, flags = [], flag_int = 0, data = EXPECTED_EXTENSION_DATA)], cert.extensions)
     self.assertEqual(EXPECTED_SIGNATURE, cert.signature)
 
   def test_non_base64(self):





More information about the tor-commits mailing list