[tor-commits] [stem/master] Support multiple 'id' lines in microdescriptors
atagar at torproject.org
atagar at torproject.org
Wed Aug 26 16:37:01 UTC 2015
commit 373d56f8fae1521a05f4983060ef50dd43417bd5
Author: Damian Johnson <atagar at torproject.org>
Date: Wed Aug 26 09:38:10 2015 -0700
Support multiple 'id' lines in microdescriptors
With the ed25519 additions the 'id' lines of microdescriptors can now appear
multiple times...
https://gitweb.torproject.org/torspec.git/commit/?id=09ff9e2
---
docs/change_log.rst | 1 +
stem/descriptor/microdescriptor.py | 44 +++++++++++++++++++++++--------
stem/descriptor/server_descriptor.py | 6 ++---
test/unit/descriptor/microdescriptor.py | 28 ++++++++++++++++++++
4 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index 1f542ad..6de73f4 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -56,6 +56,7 @@ The following are only available within Stem's `git repository
* Support for ed25519 descriptor fields (:spec:`5a79d67`)
* Server descriptor validation fails with 'extra-info-digest line had an invalid value' from additions in proposal 228 (:trac:`16227`)
* :class:`~stem.descriptor.server_descriptor.BridgeDescriptor` now has 'ntor_onion_key' like its unsanitized counterparts
+ * Replaced the :class:`~stem.descriptor.microdescriptor.Microdescriptor` identifier and identifier_type attributes with an identifiers hash since it can now appear multiple times (:spec:`09ff9e2`)
* **Website**
diff --git a/stem/descriptor/microdescriptor.py b/stem/descriptor/microdescriptor.py
index 1362147..d626101 100644
--- a/stem/descriptor/microdescriptor.py
+++ b/stem/descriptor/microdescriptor.py
@@ -73,6 +73,7 @@ from stem.descriptor import (
_get_descriptor_components,
_read_until_keywords,
_value,
+ _values,
_parse_simple_line,
_parse_key_block,
)
@@ -159,14 +160,24 @@ def _parse_file(descriptor_file, validate = False, **kwargs):
def _parse_id_line(descriptor, entries):
- value = _value('id', entries)
- value_comp = value.split()
+ identities = {}
- if len(value_comp) >= 2:
- descriptor.identifier_type = value_comp[0]
- descriptor.identifier = value_comp[1]
- else:
- raise ValueError("'id' lines should contain both the key type and digest: id %s" % value)
+ for entry in _values('id', entries):
+ entry_comp = entry.split()
+
+ if len(entry_comp) >= 2:
+ key_type, key_value = entry_comp[0], entry_comp[1]
+
+ if key_type in identities:
+ raise ValueError("There can only be one 'id' line per a key type, but '%s' appeared multiple times" % key_type)
+
+ descriptor.identifier_type = key_type
+ descriptor.identifier = key_value
+ identities[key_type] = key_value
+ else:
+ raise ValueError("'id' lines should contain both the key type and digest: id %s" % entry)
+
+ descriptor.identifiers = identities
_parse_digest = lambda descriptor, entries: setattr(descriptor, 'digest', hashlib.sha256(descriptor.get_bytes()).hexdigest().upper())
@@ -192,13 +203,23 @@ class Microdescriptor(Descriptor):
:var list family: **\*** nicknames or fingerprints of declared family
:var stem.exit_policy.MicroExitPolicy exit_policy: **\*** relay's exit policy
:var stem.exit_policy.MicroExitPolicy exit_policy_v6: **\*** exit policy for IPv6
- :var str identifier_type: identity digest key type
- :var str identifier: base64 encoded identity digest, this is only used for collision prevention (:trac:`11743`)
+ :var hash identifiers: mapping of key types (like rsa1024 or ed25519) to
+ their base64 encoded identity, this is only used for collision prevention
+ (:trac:`11743`)
+
+ :var str identifier: base64 encoded identity digest (**deprecated**, use
+ identifiers instead)
+ :var str identifier_type: identity digest key type (**deprecated**, use
+ identifiers instead)
**\*** attribute is required when we're parsed with validation
.. versionchanged:: 1.1.0
Added the identifier and identifier_type attributes.
+
+ .. versionchanged:: 1.5.0
+ Added the identifiers attribute, and deprecated identifier and
+ identifier_type since the field can now appear multiple times.
"""
ATTRIBUTES = {
@@ -208,8 +229,9 @@ class Microdescriptor(Descriptor):
'family': ([], _parse_family_line),
'exit_policy': (stem.exit_policy.MicroExitPolicy('reject 1-65535'), _parse_p_line),
'exit_policy_v6': (None, _parse_p6_line),
- 'identifier_type': (None, _parse_id_line),
- 'identifier': (None, _parse_id_line),
+ 'identifier_type': (None, _parse_id_line), # deprecated in favor of identifiers
+ 'identifier': (None, _parse_id_line), # deprecated in favor of identifiers
+ 'identifiers': ({}, _parse_id_line),
'digest': (None, _parse_digest),
}
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index be40f62..07b224a 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -420,7 +420,7 @@ class ServerDescriptor(Descriptor):
:var str address: **\*** IPv4 address of the relay
:var int or_port: **\*** port used for relaying
- :var int socks_port: **\*** port used as client (deprecated, always **None**)
+ :var int socks_port: **\*** port used as client (**deprecated**, always **None**)
:var int dir_port: **\*** port used for descriptor mirroring
:var bytes platform: line with operating system and tor version
@@ -442,13 +442,13 @@ class ServerDescriptor(Descriptor):
:var bool allow_single_hop_exits: **\*** flag if single hop exiting is allowed
:var bool extra_info_cache: **\*** flag if a mirror for extra-info documents
:var str extra_info_digest: upper-case hex encoded digest of our extra-info document
- :var bool eventdns: flag for evdns backend (deprecated, always unset)
+ :var bool eventdns: flag for evdns backend (**deprecated**, always unset)
:var str ntor_onion_key: base64 key used to encrypt EXTEND in the ntor protocol
:var list or_addresses: **\*** alternative for our address/or_port
attributes, each entry is a tuple of the form (address (**str**), port
(**int**), is_ipv6 (**bool**))
- Deprecated, moved to extra-info descriptor...
+ **Deprecated**, moved to extra-info descriptor...
:var datetime read_history_end: end of the sampling interval
:var int read_history_interval: seconds per interval
diff --git a/test/unit/descriptor/microdescriptor.py b/test/unit/descriptor/microdescriptor.py
index 598f58e..f21e518 100644
--- a/test/unit/descriptor/microdescriptor.py
+++ b/test/unit/descriptor/microdescriptor.py
@@ -95,6 +95,7 @@ class TestMicrodescriptor(unittest.TestCase):
self.assertEqual([], desc.family)
self.assertEqual(stem.exit_policy.MicroExitPolicy('reject 1-65535'), desc.exit_policy)
self.assertEqual(None, desc.exit_policy_v6)
+ self.assertEqual({}, desc.identifiers)
self.assertEqual(None, desc.identifier_type)
self.assertEqual(None, desc.identifier)
self.assertEqual([], desc.get_unrecognized_lines())
@@ -170,5 +171,32 @@ class TestMicrodescriptor(unittest.TestCase):
"""
desc = get_microdescriptor({'id': 'rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4'})
+ self.assertEqual({'rsa1024': 'Cd47okjCHD83YGzThGBDptXs9Z4'}, desc.identifiers)
self.assertEqual('rsa1024', desc.identifier_type)
self.assertEqual('Cd47okjCHD83YGzThGBDptXs9Z4', desc.identifier)
+
+ # check when there's multiple key types
+
+ desc_text = b'\n'.join((get_microdescriptor(content = True),
+ b'id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4',
+ b'id ed25519 50f6ddbecdc848dcc6b818b14d1'))
+
+ desc = Microdescriptor(desc_text, validate = True)
+ self.assertEqual({'rsa1024': 'Cd47okjCHD83YGzThGBDptXs9Z4', 'ed25519': '50f6ddbecdc848dcc6b818b14d1'}, desc.identifiers)
+ self.assertEqual('ed25519', desc.identifier_type)
+ self.assertEqual('50f6ddbecdc848dcc6b818b14d1', desc.identifier)
+
+ # check when there's conflicting keys
+
+ desc_text = b'\n'.join((get_microdescriptor(content = True),
+ b'id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4',
+ b'id rsa1024 50f6ddbecdc848dcc6b818b14d1'))
+
+ desc = Microdescriptor(desc_text)
+ self.assertEqual({}, desc.identifiers)
+
+ try:
+ Microdescriptor(desc_text, validate = True)
+ self.fail('constructor validation should fail')
+ except ValueError as exc:
+ self.assertEqual("There can only be one 'id' line per a key type, but 'rsa1024' appeared multiple times", str(exc))
More information about the tor-commits
mailing list