def _parse_exit_policy(descriptor, entries): if hasattr(descriptor, '_unparsed_exit_policy'): if descriptor._unparsed_exit_policy == [str_type('reject *:*')]: descriptor.exit_policy = REJECT_ALL_POLICY else: descriptor.exit_policy = stem.exit_policy.ExitPolicy( *descriptor._unparsed_exit_policy) del descriptor._unparsed_exit_policy _parse_identity_ed25519_line = _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT') _parse_master_key_ed25519_line = _parse_simple_line('master-key-ed25519', 'ed25519_master_key') _parse_master_key_ed25519_for_hash_line = _parse_simple_line( 'master-key-ed25519', 'ed25519_certificate_hash') _parse_contact_line = _parse_bytes_line('contact', 'contact') _parse_published_line = _parse_timestamp_line('published', 'published') _parse_read_history_line = functools.partial(_parse_history_line, 'read-history', 'read_history_end', 'read_history_interval', 'read_history_values') _parse_write_history_line = functools.partial(_parse_history_line, 'write-history', 'write_history_end', 'write_history_interval', 'write_history_values') _parse_ipv6_policy_line = _parse_simple_line(
raise ValueError( "There can only be one 'id' line per a key type, but '%s' appeared multiple times" % key_type) 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_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY') _parse_ntor_onion_key_line = _parse_simple_line('ntor-onion-key', 'ntor_onion_key') _parse_family_line = _parse_simple_line('family', 'family', func=lambda v: v.split(' ')) _parse_p6_line = _parse_simple_line( 'p6', 'exit_policy_v6', func=lambda v: stem.exit_policy.MicroExitPolicy(v)) _parse_pr_line = _parse_protocol_line('pr', 'protocols') class Microdescriptor(Descriptor): """ Microdescriptor (`descriptor specification <https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt>`_) :var str onion_key: **\\*** key used to encrypt EXTEND cells :var str ntor_onion_key: base64 key used to encrypt EXTEND in the ntor protocol
setattr(descriptor, history_interval_attribute, interval) setattr(descriptor, history_values_attribute, history_values) def _parse_exit_policy(descriptor, entries): if hasattr(descriptor, '_unparsed_exit_policy'): if descriptor._unparsed_exit_policy == [str_type('reject *:*')]: descriptor.exit_policy = REJECT_ALL_POLICY else: descriptor.exit_policy = stem.exit_policy.ExitPolicy(*descriptor._unparsed_exit_policy) del descriptor._unparsed_exit_policy _parse_identity_ed25519_line = _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT') _parse_master_key_ed25519_line = _parse_simple_line('master-key-ed25519', 'ed25519_master_key') _parse_master_key_ed25519_for_hash_line = _parse_simple_line('master-key-ed25519', 'ed25519_certificate_hash') _parse_contact_line = _parse_bytes_line('contact', 'contact') _parse_published_line = _parse_timestamp_line('published', 'published') _parse_read_history_line = functools.partial(_parse_history_line, 'read-history', 'read_history_end', 'read_history_interval', 'read_history_values') _parse_write_history_line = functools.partial(_parse_history_line, 'write-history', 'write_history_end', 'write_history_interval', 'write_history_values') _parse_ipv6_policy_line = _parse_simple_line('ipv6-policy', 'exit_policy_v6', func = lambda v: stem.exit_policy.MicroExitPolicy(v)) _parse_allow_single_hop_exits_line = _parse_if_present('allow-single-hop-exits', 'allow_single_hop_exits') _parse_caches_extra_info_line = _parse_if_present('caches-extra-info', 'extra_info_cache') _parse_family_line = _parse_simple_line('family', 'family', func = lambda v: set(v.split(' '))) _parse_eventdns_line = _parse_simple_line('eventdns', 'eventdns', func = lambda v: v == '1') _parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY') _parse_onion_key_crosscert_line = _parse_key_block('onion-key-crosscert', 'onion_key_crosscert', 'CROSSCERT') _parse_signing_key_line = _parse_key_block('signing-key', 'signing_key', 'RSA PUBLIC KEY') _parse_router_signature_line = _parse_key_block('router-signature', 'signature', 'SIGNATURE') _parse_ntor_onion_key_line = _parse_simple_line('ntor-onion-key', 'ntor_onion_key')
stat = int(stat_value) except ValueError: raise ValueError("'%s' stat was non-numeric (%s): %s %s" % (keyword, stat_value, keyword, value)) for key, val in _mappings_for(keyword, remainder): extra[key] = val setattr(descriptor, stat_attribute, stat) setattr(descriptor, extra_attribute, extra) _parse_identity_ed25519_line = _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT') _parse_master_key_ed25519_line = _parse_simple_line( 'master-key-ed25519', 'ed25519_certificate_hash') _parse_geoip_db_digest_line = _parse_forty_character_hex( 'geoip-db-digest', 'geoip_db_digest') _parse_geoip6_db_digest_line = _parse_forty_character_hex( 'geoip6-db-digest', 'geoip6_db_digest') _parse_dirreq_v2_resp_line = functools.partial(_parse_dirreq_line, 'dirreq-v2-resp', 'dir_v2_responses', 'dir_v2_responses_unknown') _parse_dirreq_v3_resp_line = functools.partial(_parse_dirreq_line, 'dirreq-v3-resp', 'dir_v3_responses', 'dir_v3_responses_unknown') _parse_dirreq_v2_direct_dl_line = functools.partial( _parse_dirreq_line, 'dirreq-v2-direct-dl', 'dir_v2_direct_dl', 'dir_v2_direct_dl_unknown')
descriptor.introduction_points_auth = [ ] # field was never implemented in tor (#15190) try: descriptor.introduction_points_content = _bytes_for_block( block_contents) except TypeError: raise ValueError( "'introduction-points' isn't base64 encoded content:\n%s" % block_contents) _parse_v2_version_line = _parse_int_line('version', 'version', allow_negative=False) _parse_rendezvous_service_descriptor_line = _parse_simple_line( 'rendezvous-service-descriptor', 'descriptor_id') _parse_permanent_key_line = _parse_key_block('permanent-key', 'permanent_key', 'RSA PUBLIC KEY') _parse_secret_id_part_line = _parse_simple_line('secret-id-part', 'secret_id_part') _parse_publication_time_line = _parse_timestamp_line('publication-time', 'published') _parse_v2_signature_line = _parse_key_block('signature', 'signature', 'SIGNATURE') _parse_v3_version_line = _parse_int_line('hs-descriptor', 'version', allow_negative=False) _parse_lifetime_line = _parse_int_line('descriptor-lifetime', 'lifetime', allow_negative=False)
def _parse_id_line(descriptor, entries): value = _value('id', entries) value_comp = value.split() 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) _parse_digest = lambda descriptor, entries: setattr(descriptor, 'digest', hashlib.sha256(descriptor.get_bytes()).hexdigest().upper()) _parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY') _parse_ntor_onion_key_line = _parse_simple_line('ntor-onion-key', 'ntor_onion_key') _parse_family_line = lambda descriptor, entries: setattr(descriptor, 'family', _value('family', entries).split(' ')) _parse_p6_line = lambda descriptor, entries: setattr(descriptor, 'exit_policy_v6', stem.exit_policy.MicroExitPolicy(_value('p6', entries))) class Microdescriptor(Descriptor): """ Microdescriptor (`descriptor specification <https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt>`_) :var str digest: **\*** hex digest for this microdescriptor, this can be used to match against the corresponding digest attribute of a :class:`~stem.descriptor.router_status_entry.RouterStatusEntryMicroV3` :var str onion_key: **\*** key used to encrypt EXTEND cells :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
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) _parse_digest = lambda descriptor, entries: setattr( descriptor, 'digest', hashlib.sha256(descriptor.get_bytes()).hexdigest().upper()) _parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY') _parse_ntor_onion_key_line = _parse_simple_line('ntor-onion-key', 'ntor_onion_key') _parse_family_line = lambda descriptor, entries: setattr( descriptor, 'family', _value('family', entries).split(' ')) _parse_p6_line = lambda descriptor, entries: setattr( descriptor, 'exit_policy_v6', stem.exit_policy.MicroExitPolicy(_value('p6', entries))) class Microdescriptor(Descriptor): """ Microdescriptor (`descriptor specification <https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt>`_) :var str digest: **\*** hex digest for this microdescriptor, this can be used to match against the corresponding digest attribute of a
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 def _parse_digest(descriptor, entries): setattr(descriptor, 'digest', hashlib.sha256(descriptor.get_bytes()).hexdigest().upper()) _parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY') _parse_ntor_onion_key_line = _parse_simple_line('ntor-onion-key', 'ntor_onion_key') _parse_family_line = _parse_simple_line('family', 'family', func = lambda v: v.split(' ')) _parse_p6_line = _parse_simple_line('p6', 'exit_policy_v6', func = lambda v: stem.exit_policy.MicroExitPolicy(v)) _parse_pr_line = _parse_protocol_line('pr', 'protocols') class Microdescriptor(Descriptor): """ Microdescriptor (`descriptor specification <https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt>`_) :var str digest: **\*** hex digest for this microdescriptor, this can be used to match against the corresponding digest attribute of a :class:`~stem.descriptor.router_status_entry.RouterStatusEntryMicroV3` :var str onion_key: **\*** key used to encrypt EXTEND cells :var str ntor_onion_key: base64 key used to encrypt EXTEND in the ntor protocol
except ValueError: raise ValueError("'%s' stat was non-numeric (%s): %s %s" % (keyword, value_comp[0], keyword, value)) for entry in value_comp[1:]: if '=' not in entry: raise ValueError('Entries after the stat in %s lines should only be key=val entries: %s %s' % (keyword, keyword, value)) key, val = entry.split('=', 1) extra[key] = val setattr(descriptor, stat_attribute, stat) setattr(descriptor, extra_attribute, extra) _parse_identity_ed25519_line = _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT') _parse_master_key_ed25519_line = _parse_simple_line('master-key-ed25519', 'ed25519_certificate_hash') _parse_geoip_db_digest_line = _parse_forty_character_hex('geoip-db-digest', 'geoip_db_digest') _parse_geoip6_db_digest_line = _parse_forty_character_hex('geoip6-db-digest', 'geoip6_db_digest') _parse_dirreq_v2_resp_line = functools.partial(_parse_dirreq_line, 'dirreq-v2-resp', 'dir_v2_responses', 'dir_v2_responses_unknown') _parse_dirreq_v3_resp_line = functools.partial(_parse_dirreq_line, 'dirreq-v3-resp', 'dir_v3_responses', 'dir_v3_responses_unknown') _parse_dirreq_v2_direct_dl_line = functools.partial(_parse_dirreq_line, 'dirreq-v2-direct-dl', 'dir_v2_direct_dl', 'dir_v2_direct_dl_unknown') _parse_dirreq_v3_direct_dl_line = functools.partial(_parse_dirreq_line, 'dirreq-v3-direct-dl', 'dir_v3_direct_dl', 'dir_v3_direct_dl_unknown') _parse_dirreq_v2_tunneled_dl_line = functools.partial(_parse_dirreq_line, 'dirreq-v2-tunneled-dl', 'dir_v2_tunneled_dl', 'dir_v2_tunneled_dl_unknown') _parse_dirreq_v3_tunneled_dl_line = functools.partial(_parse_dirreq_line, 'dirreq-v3-tunneled-dl', 'dir_v3_tunneled_dl', 'dir_v3_tunneled_dl_unknown') _parse_dirreq_v2_share_line = functools.partial(_parse_dirreq_share_line, 'dirreq-v2-share', 'dir_v2_share') _parse_dirreq_v3_share_line = functools.partial(_parse_dirreq_share_line, 'dirreq-v3-share', 'dir_v3_share') _parse_cell_processed_cells_line = functools.partial(_parse_cell_line, 'cell-processed-cells', 'cell_processed_cells') _parse_cell_queued_cells_line = functools.partial(_parse_cell_line, 'cell-queued-cells', 'cell_queued_cells') _parse_cell_time_in_queue_line = functools.partial(_parse_cell_line, 'cell-time-in-queue', 'cell_time_in_queue') _parse_published_line = _parse_timestamp_line('published', 'published') _parse_geoip_start_time_line = _parse_timestamp_line('geoip-start-time', 'geoip_start_time')
'descriptor-lifetime line must have a positive integer value: %s' % value) def _parse_revision_counter(descriptor, entries): value = _value('revision-counter', entries) if value.isdigit(): descriptor.revision_counter = int(value) else: raise ValueError( 'revision-counter line must have a positive integer value: %s' % value) _parse_signature = _parse_simple_line('signature', 'signature') class Hsv3Descriptor(Descriptor): """ """ TYPE_ANNOTATION_NAME = 'hsv3-descriptor' ATTRIBUTES = { 'hs_descriptor': (None, _parse_hs_descriptor_line), 'descriptor_lifetime': (None, _parse_hs_descriptor_lifetime), 'descriptor_signing_key_cert': (None, _parse_identity_ed25519_line), 'revision_counter': (None, _parse_revision_counter), 'superencrypted_encoded': (None, _parse_superencrypted_line), 'create2-formats': (None, _parse_create2_formats_line),
def _parse_introduction_points_line(descriptor, entries): _, block_type, block_contents = entries['introduction-points'][0] if not block_contents or block_type != 'MESSAGE': raise ValueError("'introduction-points' should be followed by a MESSAGE block, but was a %s" % block_type) descriptor.introduction_points_encoded = block_contents descriptor.introduction_points_auth = [] # field was never implemented in tor (#15190) try: descriptor.introduction_points_content = _bytes_for_block(block_contents) except TypeError: raise ValueError("'introduction-points' isn't base64 encoded content:\n%s" % block_contents) _parse_rendezvous_service_descriptor_line = _parse_simple_line('rendezvous-service-descriptor', 'descriptor_id') _parse_permanent_key_line = _parse_key_block('permanent-key', 'permanent_key', 'RSA PUBLIC KEY') _parse_secret_id_part_line = _parse_simple_line('secret-id-part', 'secret_id_part') _parse_publication_time_line = _parse_timestamp_line('publication-time', 'published') _parse_signature_line = _parse_key_block('signature', 'signature', 'SIGNATURE') class HiddenServiceDescriptor(Descriptor): """ 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 :var str permanent_key: **\*** long term key of the hidden service :var str secret_id_part: **\*** hash of the time period, cookie, and replica values so our descriptor_id can be validated