Пример #1
0
def _parse_identity_ed25519_line(descriptor, entries):
  # TODO: replace this with Ed25519Certificate._from_descriptor() in stem 2.x

  _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT')(descriptor, entries)

  if descriptor.ed25519_certificate:
    descriptor.certificate = stem.descriptor.certificate.Ed25519Certificate.from_base64(descriptor.ed25519_certificate)
Пример #2
0
def _parse_identity_ed25519_line(descriptor, entries):
  _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT')(descriptor, entries)

  if descriptor.ed25519_certificate:
    cert_lines = descriptor.ed25519_certificate.split('\n')

    if cert_lines[0] == '-----BEGIN ED25519 CERT-----' and cert_lines[-1] == '-----END ED25519 CERT-----':
      descriptor.certificate = stem.descriptor.certificate.Ed25519Certificate.parse(''.join(cert_lines[1:-1]))
Пример #3
0
def _parse_identity_ed25519_line(descriptor, entries):
  _parse_key_block('identity-ed25519', 'ed25519_certificate', 'ED25519 CERT')(descriptor, entries)

  if descriptor.ed25519_certificate:
    cert_lines = descriptor.ed25519_certificate.split('\n')

    if cert_lines[0] == '-----BEGIN ED25519 CERT-----' and cert_lines[-1] == '-----END ED25519 CERT-----':
      descriptor.certificate = stem.descriptor.certificate.Ed25519Certificate.parse(''.join(cert_lines[1:-1]))
Пример #4
0
            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)

            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>`_)
Пример #5
0
    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',
Пример #6
0
        try:
            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')
Пример #7
0
  setattr(descriptor, history_end_attribute, timestamp)
  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')
Пример #8
0
      break  # done parsing descriptors


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
    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)
_parse_signing_key_line = _parse_key_block('descriptor-signing-key-cert',
                                           'signing_cert', 'ED25519 CERT')
Пример #10
0
    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
Пример #11
0
                                              'write_history_end',
                                              'write_history_interval',
                                              'write_history_values')
_parse_ipv6_policy_line = lambda descriptor, entries: setattr(
    descriptor, 'exit_policy_v6',
    stem.exit_policy.MicroExitPolicy(_value('ipv6-policy', entries)))
_parse_allow_single_hop_exits_line = lambda descriptor, entries: setattr(
    descriptor, 'allow_single_hop_exits', 'allow_single_hop_exits' in entries)
_parse_caches_extra_info_line = lambda descriptor, entries: setattr(
    descriptor, 'extra_info_cache', 'extra_info_cache' in entries)
_parse_family_line = lambda descriptor, entries: setattr(
    descriptor, 'family', set(_value('family', entries).split(' ')))
_parse_eventdns_line = lambda descriptor, entries: setattr(
    descriptor, 'eventdns',
    _value('eventdns', entries) == '1')
_parse_onion_key_line = _parse_key_block('onion-key', 'onion_key',
                                         'RSA PUBLIC KEY')
_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')
_parse_router_digest_line = _parse_forty_character_hex('router-digest',
                                                       '_digest')


class ServerDescriptor(Descriptor):
    """
  Common parent for server descriptors.

  :var str nickname: **\*** relay's nickname
Пример #12
0
      descriptor.exit_policy = stem.exit_policy.ExitPolicy(*descriptor._unparsed_exit_policy)

    del descriptor._unparsed_exit_policy


_parse_contact_line = _parse_bytes_line('contact', 'contact')
_parse_published_line = _parse_timestamp_line('published', 'published')
_parse_extrainfo_digest_line = _parse_forty_character_hex('extra-info-digest', 'extra_info_digest')
_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 = lambda descriptor, entries: setattr(descriptor, 'exit_policy_v6', stem.exit_policy.MicroExitPolicy(_value('ipv6-policy', entries)))
_parse_allow_single_hop_exits_line = lambda descriptor, entries: setattr(descriptor, 'allow_single_hop_exits', 'allow_single_hop_exits' in entries)
_parse_caches_extra_info_line = lambda descriptor, entries: setattr(descriptor, 'extra_info_cache', 'extra_info_cache' in entries)
_parse_family_line = lambda descriptor, entries: setattr(descriptor, 'family', set(_value('family', entries).split(' ')))
_parse_eventdns_line = lambda descriptor, entries: setattr(descriptor, 'eventdns', _value('eventdns', entries) == '1')
_parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY')
_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')
_parse_router_digest_line = _parse_forty_character_hex('router-digest', '_digest')


class ServerDescriptor(Descriptor):
  """
  Common parent for server descriptors.

  :var str nickname: **\*** relay's nickname
  :var str fingerprint: identity key fingerprint
  :var datetime published: **\*** time in UTC when this descriptor was made

  :var str address: **\*** IPv4 address of the relay
Пример #13
0
_parse_dirreq_write_history_line = functools.partial(_parse_history_line, 'dirreq-write-history', 'dir_write_history_end', 'dir_write_history_interval', 'dir_write_history_values')
_parse_exit_kibibytes_written_line = functools.partial(_parse_port_count_line, 'exit-kibibytes-written', 'exit_kibibytes_written')
_parse_exit_kibibytes_read_line = functools.partial(_parse_port_count_line, 'exit-kibibytes-read', 'exit_kibibytes_read')
_parse_exit_streams_opened_line = functools.partial(_parse_port_count_line, 'exit-streams-opened', 'exit_streams_opened')
_parse_hidden_service_stats_end_line = _parse_timestamp_line('hidserv-stats-end', 'hs_stats_end')
_parse_hidden_service_rend_relayed_cells_line = functools.partial(_parse_hs_stats, 'hidserv-rend-relayed-cells', 'hs_rend_cells', 'hs_rend_cells_attr')
_parse_hidden_service_dir_onions_seen_line = functools.partial(_parse_hs_stats, 'hidserv-dir-onions-seen', 'hs_dir_onions_seen', 'hs_dir_onions_seen_attr')
_parse_dirreq_v2_ips_line = functools.partial(_parse_geoip_to_count_line, 'dirreq-v2-ips', 'dir_v2_ips')
_parse_dirreq_v3_ips_line = functools.partial(_parse_geoip_to_count_line, 'dirreq-v3-ips', 'dir_v3_ips')
_parse_dirreq_v2_reqs_line = functools.partial(_parse_geoip_to_count_line, 'dirreq-v2-reqs', 'dir_v2_requests')
_parse_dirreq_v3_reqs_line = functools.partial(_parse_geoip_to_count_line, 'dirreq-v3-reqs', 'dir_v3_requests')
_parse_geoip_client_origins_line = functools.partial(_parse_geoip_to_count_line, 'geoip-client-origins', 'geoip_client_origins')
_parse_entry_ips_line = functools.partial(_parse_geoip_to_count_line, 'entry-ips', 'entry_ips')
_parse_bridge_ips_line = functools.partial(_parse_geoip_to_count_line, 'bridge-ips', 'bridge_ips')
_parse_router_digest_line = _parse_forty_character_hex('router-digest', '_digest')
_parse_router_signature_line = _parse_key_block('router-signature', 'signature', 'SIGNATURE')


class ExtraInfoDescriptor(Descriptor):
  """
  Extra-info descriptor document.

  :var str nickname: **\*** relay's nickname
  :var str fingerprint: **\*** identity key fingerprint
  :var datetime published: **\*** time in UTC when this descriptor was made
  :var str geoip_db_digest: sha1 of the geoIP database file for IPv4 addresses
  :var str geoip6_db_digest: sha1 of the geoIP database file for IPv6 addresses
  :var dict transport: **\*** mapping of transport methods to their (address,
    port, args) tuple, these usually appear on bridges in which case all of
    those are **None**
Пример #14
0
      stat = int(value_comp[0])
    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')
Пример #15
0
                                              'dirreq-v3-ips', 'dir_v3_ips')
_parse_dirreq_v2_reqs_line = functools.partial(_parse_geoip_to_count_line,
                                               'dirreq-v2-reqs',
                                               'dir_v2_requests')
_parse_dirreq_v3_reqs_line = functools.partial(_parse_geoip_to_count_line,
                                               'dirreq-v3-reqs',
                                               'dir_v3_requests')
_parse_geoip_client_origins_line = functools.partial(
    _parse_geoip_to_count_line, 'geoip-client-origins', 'geoip_client_origins')
_parse_entry_ips_line = functools.partial(_parse_geoip_to_count_line,
                                          'entry-ips', 'entry_ips')
_parse_bridge_ips_line = functools.partial(_parse_geoip_to_count_line,
                                           'bridge-ips', 'bridge_ips')
_parse_router_digest_line = _parse_forty_character_hex('router-digest',
                                                       '_digest')
_parse_router_signature_line = _parse_key_block('router-signature',
                                                'signature', 'SIGNATURE')


class ExtraInfoDescriptor(Descriptor):
    """
  Extra-info descriptor document.

  :var str nickname: **\*** relay's nickname
  :var str fingerprint: **\*** identity key fingerprint
  :var datetime published: **\*** time in UTC when this descriptor was made
  :var str geoip_db_digest: sha1 of the geoIP database file for IPv4 addresses
  :var str geoip6_db_digest: sha1 of the geoIP database file for IPv6 addresses
  :var dict transport: **\*** mapping of transport methods to their (address,
    port, args) tuple, these usually appear on bridges in which case all of
    those are **None**
Пример #16
0
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
  :var datetime published: **\*** time in UTC when this descriptor was made