Beispiel #1
0
  def test_annotations(self):
    """
    Checks that content before a descriptor are parsed as annotations.
    """

    desc_text = b'@pepperjack very tasty\n@mushrooms not so much\n'
    desc_text += RelayDescriptor.content()
    desc_text += b'\ntrailing text that should be invalid, ho hum'

    # running _parse_file should provide an iterator with a single descriptor
    desc_iter = stem.descriptor.server_descriptor._parse_file(io.BytesIO(desc_text), validate = True)
    self.assertRaises(ValueError, list, desc_iter)

    desc_text = b'@pepperjack very tasty\n@mushrooms not so much\n'
    desc_text += RelayDescriptor.content({'router': 'caerSidi 71.35.133.197 9001 0 0'})
    desc_iter = stem.descriptor.server_descriptor._parse_file(io.BytesIO(desc_text))

    desc_entries = list(desc_iter)
    self.assertEqual(1, len(desc_entries))
    desc = desc_entries[0]

    self.assertEqual('caerSidi', desc.nickname)
    self.assertEqual(b'@pepperjack very tasty', desc.get_annotation_lines()[0])
    self.assertEqual(b'@mushrooms not so much', desc.get_annotation_lines()[1])
    self.assertEqual({b'@pepperjack': b'very tasty', b'@mushrooms': b'not so much'}, desc.get_annotations())
    self.assertEqual([], desc.get_unrecognized_lines())
 def test_unrecognized_line(self):
   """
   Includes unrecognized content in the descriptor.
   """
   
   desc_text = _make_descriptor({"pepperjack": "is oh so tasty!"})
   desc = RelayDescriptor(desc_text)
   self.assertEquals(["pepperjack is oh so tasty!"], desc.get_unrecognized_lines())
Beispiel #3
0
  def test_unrecognized_line(self):
    """
    Includes unrecognized content in the descriptor.
    """

    desc = RelayDescriptor.create({'pepperjack': 'is oh so tasty!'})
    self.assertEqual(['pepperjack is oh so tasty!'], desc.get_unrecognized_lines())
Beispiel #4
0
  def test_invalid_attributes(self):
    """
    Attempts to make a csv with attributes that don't exist.
    """

    desc = RelayDescriptor.create()
    self.assertRaises(ValueError, export_csv, desc, ('nickname', 'blarg!'))
Beispiel #5
0
  def test_protocols(self):
    """
    Checks a 'proto' line.
    """

    desc = RelayDescriptor.create({'proto': 'Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2'})
    self.assertEqual({'Cons': [1], 'Desc': [1], 'DirCache': [1], 'HSDir': [1], 'HSIntro': [3], 'HSRend': [1], 'Link': [1, 2, 3, 4], 'LinkAuth': [1], 'Microdesc': [1], 'Relay': [1, 2]}, desc.protocols)
Beispiel #6
0
  def test_proceeding_line(self):
    """
    Includes a line prior to the 'router' entry.
    """

    desc_text = b'hibernate 1\n' + RelayDescriptor.content()
    expect_invalid_attr_for_text(self, desc_text)
Beispiel #7
0
  def test_trailing_line(self):
    """
    Includes a line after the 'router-signature' entry.
    """

    desc_text = RelayDescriptor.content() + b'\nhibernate 1'
    expect_invalid_attr_for_text(self, desc_text)
Beispiel #8
0
  def test_with_opt(self):
    """
    Includes an 'opt <keyword> <value>' entry.
    """

    desc = RelayDescriptor.create({'opt': 'contact www.atagar.com/contact/'})
    self.assertEqual(b'www.atagar.com/contact/', desc.contact)
Beispiel #9
0
  def test_ipv6_policy(self):
    """
    Checks a 'ipv6-policy' line.
    """

    desc = RelayDescriptor.create({'ipv6-policy': 'accept 22-23,53,80,110'})
    self.assertEqual(stem.exit_policy.MicroExitPolicy('accept 22-23,53,80,110'), desc.exit_policy_v6)
Beispiel #10
0
  def test_ntor_onion_key(self):
    """
    Checks a 'ntor-onion-key' line.
    """

    desc = RelayDescriptor.create({'ntor-onion-key': 'Od2Sj3UXFyDjwESLXk6fhatqW9z/oBL/vAKJ+tbDqUU='})
    self.assertEqual('Od2Sj3UXFyDjwESLXk6fhatqW9z/oBL/vAKJ+tbDqUU=', desc.ntor_onion_key)
Beispiel #11
0
  def test_duplicate_field(self):
    """
    Constructs with a field appearing twice.
    """

    desc_text = RelayDescriptor.content({'<replace>': ''})
    desc_text = desc_text.replace(b'<replace>', b'contact foo\ncontact bar')
    expect_invalid_attr_for_text(self, desc_text, 'contact', b'foo')
Beispiel #12
0
  def test_extrainfo_sha256_digest(self):
    """
    Extrainfo descriptor line with both a hex and base64 encoded sha256 digest.
    """

    desc = RelayDescriptor.create({'extra-info-digest': '03272BF7C68484AFBDA508DAE3734D809E4A5BC4 DWMz1AEdqPlcroubwx3lPEoGbT+oX7S2BH653sPIqfI'})
    self.assertEqual('03272BF7C68484AFBDA508DAE3734D809E4A5BC4', desc.extra_info_digest)
    self.assertEqual('DWMz1AEdqPlcroubwx3lPEoGbT+oX7S2BH653sPIqfI', desc.extra_info_sha256_digest)
Beispiel #13
0
  def test_mirror_mirror_on_the_wall_5(self, downloader_mock, stdout_mock):
    def tutorial_example():
      from stem.descriptor.remote import DescriptorDownloader
      from stem.util import str_tools

      # provides a mapping of observed bandwidth to the relay nicknames
      def get_bw_to_relay():
        bw_to_relay = {}

        downloader = DescriptorDownloader()

        try:
          for desc in downloader.get_server_descriptors().run():
            if desc.exit_policy.is_exiting_allowed():
              bw_to_relay.setdefault(desc.observed_bandwidth, []).append(desc.nickname)
        except Exception as exc:
          print('Unable to retrieve the server descriptors: %s' % exc)

        return bw_to_relay

      # prints the top fifteen relays

      bw_to_relay = get_bw_to_relay()
      count = 1

      for bw_value in sorted(bw_to_relay.keys(), reverse = True):
        for nickname in bw_to_relay[bw_value]:
          print('%i. %s (%s/s)' % (count, nickname, str_tools.size_label(bw_value, 2)))
          count += 1

          if count > 15:
            return

    exit_descriptor = RelayDescriptor.content({'router': 'speedyexit 149.255.97.109 9001 0 0'}).replace(b'reject *:*', b'accept *:*')
    exit_descriptor = RelayDescriptor(exit_descriptor)

    downloader_mock().get_server_descriptors().run.return_value = [
      exit_descriptor,
      RelayDescriptor.create(),  # non-exit
      exit_descriptor,
      exit_descriptor,
    ]

    tutorial_example()
    self.assertEqual(MIRROR_MIRROR_OUTPUT, stdout_mock.getvalue())
Beispiel #14
0
  def test_read_history_empty(self):
    """
    Parses a read-history with an empty value.
    """

    desc = RelayDescriptor.create({'opt read-history': '2005-12-17 01:23:11 (900 s) '})
    self.assertEqual(datetime.datetime(2005, 12, 17, 1, 23, 11), desc.read_history_end)
    self.assertEqual(900, desc.read_history_interval)
    self.assertEqual([], desc.read_history_values)
Beispiel #15
0
  def test_platform_for_node_tor(self):
    """
    Parse a platform line belonging to a node-Tor relay.
    """

    desc = RelayDescriptor.create({'platform': 'node-Tor 0.1.0 on Linux x86_64'})
    self.assertEqual(b'node-Tor 0.1.0 on Linux x86_64', desc.platform)
    self.assertEqual(stem.version.Version('0.1.0'), desc.tor_version)
    self.assertEqual('Linux x86_64', desc.operating_system)
Beispiel #16
0
  def test_bridge_unsanitized_relay(self):
    """
    Checks that parsing a normal relay descriptor as a bridge will fail due to
    its unsanatized content.
    """

    desc_text = RelayDescriptor.content({'router-digest': '006FD96BA35E7785A6A3B8B75FE2E2435A13BDB4'})
    desc = BridgeDescriptor(desc_text)
    self.assertFalse(desc.is_scrubbed())
Beispiel #17
0
  def test_published_leap_year(self):
    """
    Constructs with a published entry for a leap year, and when the date is
    invalid.
    """

    expect_invalid_attr(self, {'published': '2011-02-29 04:03:19'}, 'published')

    desc = RelayDescriptor.create({'published': '2012-02-29 04:03:19'})
    self.assertEqual(datetime.datetime(2012, 2, 29, 4, 3, 19), desc.published)
Beispiel #18
0
  def test_minimal_relay_descriptor(self):
    """
    Basic sanity check that we can parse a relay server descriptor with minimal
    attributes.
    """

    desc = RelayDescriptor.create({'router': 'caerSidi 71.35.133.197 9001 0 0'})
    self.assertEqual('caerSidi', desc.nickname)
    self.assertEqual('71.35.133.197', desc.address)
    self.assertEqual(None, desc.fingerprint)
Beispiel #19
0
    def test_minimal_relay_descriptor(self):
        """
    Basic sanity check that we can parse a relay server descriptor with minimal
    attributes.
    """

        desc = RelayDescriptor.create(
            {'router': 'caerSidi 71.35.133.197 9001 0 0'})
        self.assertEqual('caerSidi', desc.nickname)
        self.assertEqual('71.35.133.197', desc.address)
        self.assertEqual(None, desc.fingerprint)
Beispiel #20
0
    def test_read_history_empty(self):
        """
    Parses a read-history with an empty value.
    """

        desc = RelayDescriptor.create(
            {'opt read-history': '2005-12-17 01:23:11 (900 s) '})
        self.assertEqual(datetime.datetime(2005, 12, 17, 1, 23, 11),
                         desc.read_history_end)
        self.assertEqual(900, desc.read_history_interval)
        self.assertEqual([], desc.read_history_values)
Beispiel #21
0
  def test_published_leap_year(self):
    """
    Constructs with a published entry for a leap year, and when the date is
    invalid.
    """

    desc_text = get_relay_server_descriptor({"published": "2011-02-29 04:03:19"}, content = True)
    self._expect_invalid_attr(desc_text, "published")

    desc_text = get_relay_server_descriptor({"published": "2012-02-29 04:03:19"}, content = True)
    expected_published = datetime.datetime(2012, 2, 29, 4, 3, 19)
    self.assertEquals(expected_published, RelayDescriptor(desc_text).published)
Beispiel #22
0
    def test_read_with_parse_file(self, stdout_mock, parse_file_mock):
        parse_file_mock.return_value = [
            RelayDescriptor.create({
                'fingerprint':
                '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE44'
            })
        ]

        import read_with_parse_file

        self.assertEqual('4F0C867DF0EF68160568C826838F482CEA7CFE44\n',
                         stdout_mock.getvalue())
Beispiel #23
0
    def test_outdated_relays(self, stdout_mock, downloader_mock):
        downloader_mock().get_server_descriptors.return_value = [
            RelayDescriptor.create(
                {'platform': 'node-Tor 0.2.3.0 on Linux x86_64'}),
            RelayDescriptor.create(
                {'platform': 'node-Tor 0.1.0 on Linux x86_64'}),
            RelayDescriptor.create({
                'opt':
                'contact Random Person [email protected]',
                'platform':
                'node-Tor 0.2.3.0 on Linux x86_64'
            }),
            RelayDescriptor.create({
                'opt': 'contact Sambuddha Basu',
                'platform': 'node-Tor 0.1.0 on Linux x86_64'
            }),
        ]

        import outdated_relays

        self.assertEqual(EXPECTED_OUTDATED_RELAYS, stdout_mock.getvalue())
Beispiel #24
0
    def test_published_leap_year(self):
        """
    Constructs with a published entry for a leap year, and when the date is
    invalid.
    """

        expect_invalid_attr(self, {'published': '2011-02-29 04:03:19'},
                            'published')

        desc = RelayDescriptor.create({'published': '2012-02-29 04:03:19'})
        self.assertEqual(datetime.datetime(2012, 2, 29, 4, 3, 19),
                         desc.published)
Beispiel #25
0
    def test_mirror_mirror_on_the_wall_5(self, downloader_mock, stdout_mock):
        def tutorial_example():
            from stem.descriptor.remote import DescriptorDownloader
            from stem.util import str_tools

            # provides a mapping of observed bandwidth to the relay nicknames
            def get_bw_to_relay():
                bw_to_relay = {}

                downloader = DescriptorDownloader()

                try:
                    for desc in downloader.get_server_descriptors().run():
                        if desc.exit_policy.is_exiting_allowed():
                            bw_to_relay.setdefault(desc.observed_bandwidth,
                                                   []).append(desc.nickname)
                except Exception as exc:
                    print('Unable to retrieve the server descriptors: %s' %
                          exc)

                return bw_to_relay

            # prints the top fifteen relays

            bw_to_relay = get_bw_to_relay()
            count = 1

            for bw_value in sorted(bw_to_relay.keys(), reverse=True):
                for nickname in bw_to_relay[bw_value]:
                    print('%i. %s (%s/s)' %
                          (count, nickname, str_tools.size_label(bw_value, 2)))
                    count += 1

                    if count > 15:
                        return

        exit_descriptor = mocking.get_relay_server_descriptor(
            {
                'router': 'speedyexit 149.255.97.109 9001 0 0'
            }, content=True).replace(b'reject *:*', b'accept *:*')

        exit_descriptor = mocking.sign_descriptor_content(exit_descriptor)
        exit_descriptor = RelayDescriptor(exit_descriptor)

        downloader_mock().get_server_descriptors().run.return_value = [
            exit_descriptor,
            mocking.get_relay_server_descriptor(),  # non-exit
            exit_descriptor,
            exit_descriptor,
        ]

        tutorial_example()
        self.assertEqual(MIRROR_MIRROR_OUTPUT, stdout_mock.getvalue())
Beispiel #26
0
    def test_file_output(self):
        """
    Basic test for the export_csv_file() function, checking that it provides
    the same output as export_csv().
    """

        desc = RelayDescriptor.create()
        desc_csv = export_csv(desc)

        csv_buffer = StringIO()
        export_csv_file(csv_buffer, desc)

        self.assertEqual(desc_csv, csv_buffer.getvalue())
Beispiel #27
0
  def test_router_status_entry(self):
    """
    Tests creation of router status entries.
    """

    desc_without_fingerprint = RelayDescriptor.create()
    exc_msg = 'Server descriptor lacks a fingerprint. This is an optional field, but required to make a router status entry.'
    self.assertRaisesRegexp(ValueError, exc_msg, desc_without_fingerprint.make_router_status_entry)

    desc = RelayDescriptor.create({
      'router': 'caerSidi 71.35.133.197 9001 0 0',
      'published': '2012-02-29 04:03:19',
      'fingerprint': '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE44',
      'or-address': ['71.35.133.197:9001', '[12ab:2e19:3bcf::02:9970]:9001'],
      'onion-key': '\n-----BEGIN RSA PUBLIC KEY-----%s-----END RSA PUBLIC KEY-----' % stem.descriptor.CRYPTO_BLOB,
      'signing-key': '\n-----BEGIN RSA PUBLIC KEY-----%s-----END RSA PUBLIC KEY-----' % stem.descriptor.CRYPTO_BLOB,
    }).make_router_status_entry()

    self.assertEqual(stem.descriptor.router_status_entry.RouterStatusEntryV3, type(desc))
    self.assertEqual('caerSidi', desc.nickname)
    self.assertEqual('4F0C867DF0EF68160568C826838F482CEA7CFE44', desc.fingerprint)
    self.assertEqual(datetime.datetime(2012, 2, 29, 4, 3, 19), desc.published)
    self.assertEqual('71.35.133.197', desc.address)
    self.assertEqual(9001, desc.or_port)
    self.assertEqual(None, desc.dir_port)
    self.assertEqual(['Fast', 'Named', 'Running', 'Stable', 'Valid'], desc.flags)
    self.assertEqual(None, desc.version)
    self.assertEqual(None, desc.version_line)

    self.assertEqual([('71.35.133.197', 9001, False), ('12ab:2e19:3bcf::02:9970', 9001, True)], desc.or_addresses)
    self.assertEqual(None, desc.identifier_type)
    self.assertEqual(None, desc.identifier)
    self.assertEqual('4F0069BF91C04581B7C3CA9272E2D3228D4EA571', desc.digest)
    self.assertEqual(153600, desc.bandwidth)
    self.assertEqual(None, desc.measured)
    self.assertEqual(False, desc.is_unmeasured)
    self.assertEqual([], desc.unrecognized_bandwidth_entries)
    self.assertEqual(stem.exit_policy.MicroExitPolicy('reject 1-65535'), desc.exit_policy)
    self.assertEqual([], desc.microdescriptor_hashes)
Beispiel #28
0
  def test_platform_empty(self):
    """
    Constructs with an empty platform entry.
    """

    desc_text = RelayDescriptor.content({'platform': ''})
    desc = RelayDescriptor(desc_text, validate = False)
    self.assertEqual(b'', desc.platform)

    # does the same but with 'platform ' replaced with 'platform'
    desc_text = desc_text.replace(b'platform ', b'platform')
    desc = RelayDescriptor(desc_text, validate = False)
    self.assertEqual(b'', desc.platform)
Beispiel #29
0
    def test_outdated_relays(self, downloader_mock, stdout_mock):
        downloader_mock().get_server_descriptors.return_value = [
            RelayDescriptor.create(
                {'platform': 'node-Tor 0.2.3.0 on Linux x86_64'}),
            RelayDescriptor.create(
                {'platform': 'node-Tor 0.1.0 on Linux x86_64'}),
            RelayDescriptor.create({
                'opt':
                'contact Random Person [email protected]',
                'platform':
                'node-Tor 0.2.3.0 on Linux x86_64'
            }),
            RelayDescriptor.create({
                'opt': 'contact Sambuddha Basu',
                'platform': 'node-Tor 0.1.0 on Linux x86_64'
            }),
        ]

        exec_documentation_example('outdated_relays.py')

        self.assertCountEqual(OUTDATED_RELAYS_OUTPUT.splitlines(),
                              stdout_mock.getvalue().splitlines())
Beispiel #30
0
  def test_file_output(self):
    """
    Basic test for the export_csv_file() function, checking that it provides
    the same output as export_csv().
    """

    desc = RelayDescriptor.create()
    desc_csv = export_csv(desc)

    csv_buffer = StringIO()
    export_csv_file(csv_buffer, desc)

    self.assertEqual(desc_csv, csv_buffer.getvalue())
Beispiel #31
0
    def test_extrainfo_sha256_digest(self):
        """
    Extrainfo descriptor line with both a hex and base64 encoded sha256 digest.
    """

        desc = RelayDescriptor.create({
            'extra-info-digest':
            '03272BF7C68484AFBDA508DAE3734D809E4A5BC4 DWMz1AEdqPlcroubwx3lPEoGbT+oX7S2BH653sPIqfI'
        })
        self.assertEqual('03272BF7C68484AFBDA508DAE3734D809E4A5BC4',
                         desc.extra_info_digest)
        self.assertEqual('DWMz1AEdqPlcroubwx3lPEoGbT+oX7S2BH653sPIqfI',
                         desc.extra_info_sha256_digest)
Beispiel #32
0
  def test_router_status_entry(self):
    """
    Tests creation of router status entries.
    """

    desc_without_fingerprint = RelayDescriptor.create()
    exc_msg = 'Server descriptor lacks a fingerprint. This is an optional field, but required to make a router status entry.'
    self.assertRaisesRegexp(ValueError, exc_msg, desc_without_fingerprint.make_router_status_entry)

    desc = RelayDescriptor.create(OrderedDict((
      ('router', 'caerSidi 71.35.133.197 9001 0 0'),
      ('published', '2012-02-29 04:03:19'),
      ('fingerprint', '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE44'),
      ('or-address', ['71.35.133.197:9001', '[12ab:2e19:3bcf::02:9970]:9001']),
      ('onion-key', '\n-----BEGIN RSA PUBLIC KEY-----%s-----END RSA PUBLIC KEY-----' % stem.descriptor.CRYPTO_BLOB),
      ('signing-key', '\n-----BEGIN RSA PUBLIC KEY-----%s-----END RSA PUBLIC KEY-----' % stem.descriptor.CRYPTO_BLOB),
    ))).make_router_status_entry()

    self.assertEqual(stem.descriptor.router_status_entry.RouterStatusEntryV3, type(desc))
    self.assertEqual('caerSidi', desc.nickname)
    self.assertEqual('4F0C867DF0EF68160568C826838F482CEA7CFE44', desc.fingerprint)
    self.assertEqual(datetime.datetime(2012, 2, 29, 4, 3, 19), desc.published)
    self.assertEqual('71.35.133.197', desc.address)
    self.assertEqual(9001, desc.or_port)
    self.assertEqual(None, desc.dir_port)
    self.assertEqual(['Fast', 'Named', 'Running', 'Stable', 'Valid'], desc.flags)
    self.assertEqual(None, desc.version)
    self.assertEqual(None, desc.version_line)

    self.assertEqual([('71.35.133.197', 9001, False), ('12ab:2e19:3bcf::02:9970', 9001, True)], desc.or_addresses)
    self.assertEqual(None, desc.identifier_type)
    self.assertEqual(None, desc.identifier)
    self.assertEqual('A863EFE8395C41C880782B89B850D20EDD242BDA', desc.digest)
    self.assertEqual(153600, desc.bandwidth)
    self.assertEqual(None, desc.measured)
    self.assertEqual(False, desc.is_unmeasured)
    self.assertEqual([], desc.unrecognized_bandwidth_entries)
    self.assertEqual(stem.exit_policy.MicroExitPolicy('reject 1-65535'), desc.exit_policy)
    self.assertEqual([], desc.microdescriptor_hashes)
Beispiel #33
0
    def test_mirror_mirror_on_the_wall_4(self, from_port_mock, stdout_mock):
        def tutorial_example():
            from stem.control import Controller
            from stem.util import str_tools

            # provides a mapping of observed bandwidth to the relay nicknames
            def get_bw_to_relay():
                bw_to_relay = {}

                with Controller.from_port(control_port=9051) as controller:
                    controller.authenticate()

                    for desc in controller.get_server_descriptors():
                        if desc.exit_policy.is_exiting_allowed():
                            bw_to_relay.setdefault(desc.observed_bandwidth,
                                                   []).append(desc.nickname)

                return bw_to_relay

            # prints the top fifteen relays

            bw_to_relay = get_bw_to_relay()
            count = 1

            for bw_value in sorted(bw_to_relay.keys(), reverse=True):
                for nickname in bw_to_relay[bw_value]:
                    print "%i. %s (%s/s)" % (
                        count, nickname, str_tools.get_size_label(bw_value, 2))
                    count += 1

                    if count > 15:
                        return

        exit_descriptor = mocking.get_relay_server_descriptor(
            {
                'router': 'speedyexit 149.255.97.109 9001 0 0'
            }, content=True).replace(b'reject *:*', b'accept *:*')

        exit_descriptor = mocking.sign_descriptor_content(exit_descriptor)
        exit_descriptor = RelayDescriptor(exit_descriptor)

        controller = from_port_mock().__enter__()
        controller.get_server_descriptors.return_value = [
            exit_descriptor,
            mocking.get_relay_server_descriptor(),  # non-exit
            exit_descriptor,
            exit_descriptor,
        ]

        tutorial_example()
        self.assertEqual(MIRROR_MIRROR_OUTPUT, stdout_mock.getvalue())
Beispiel #34
0
  def test_mirror_mirror_on_the_wall(self):
    from stem.descriptor.server_descriptor import RelayDescriptor
    from stem.descriptor.reader import DescriptorReader
    from stem.util import str_tools

    exit_descriptor = mocking.get_relay_server_descriptor({
     'router': 'speedyexit 149.255.97.109 9001 0 0'
    }, content = True).replace('reject *:*', 'accept *:*')
    exit_descriptor = mocking.sign_descriptor_content(exit_descriptor)
    exit_descriptor = RelayDescriptor(exit_descriptor)

    reader_wrapper = mocking.get_object(DescriptorReader, {
      '__enter__': lambda x: x,
      '__exit__': mocking.no_op(),
      '__iter__': mocking.return_value(iter((
        exit_descriptor,
        mocking.get_relay_server_descriptor(),  # non-exit
        exit_descriptor,
        exit_descriptor,
      )))
    })

    # provides a mapping of observed bandwidth to the relay nicknames
    def get_bw_to_relay():
      bw_to_relay = {}

      with reader_wrapper as reader:
        for desc in reader:
          if desc.exit_policy.is_exiting_allowed():
            bw_to_relay.setdefault(desc.observed_bandwidth, []).append(desc.nickname)

      return bw_to_relay

    # prints the top fifteen relays

    bw_to_relay = get_bw_to_relay()
    count = 1

    for bw_value in sorted(bw_to_relay.keys(), reverse = True):
      for nickname in bw_to_relay[bw_value]:
        expected_line = "%i. speedyexit (102.13 KB/s)" % count
        printed_line = "%i. %s (%s/s)" % (count, nickname, str_tools.get_size_label(bw_value, 2))
        self.assertEqual(expected_line, printed_line)

        count += 1

        if count > 15:
          return

    self.assertEqual(4, count)
Beispiel #35
0
  def test_multiple_descriptors(self):
    """
    Exports multiple descriptors, making sure that we get them back in the same
    order.
    """

    nicknames = ('relay1', 'relay3', 'relay2', 'caerSidi', 'zeus')
    descriptors = []

    for nickname in nicknames:
      router_line = '%s 71.35.133.197 9001 0 0' % nickname
      descriptors.append(RelayDescriptor.create({'router': router_line}))

    expected = '\n'.join(nicknames) + '\n'
    self.assertEqual(expected, export_csv(descriptors, included_fields = ('nickname',), header = False))
Beispiel #36
0
    def test_collector_reading(self, stdout_mock, server_desc_mock):
        server_desc_mock.return_value = [
            RelayDescriptor.create(
                {
                    'router':
                    'caerSidi 71.35.133.197 9001 0 0',
                    'fingerprint':
                    '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE44',
                },
                exit_policy=ExitPolicy('accept *:*')),
        ]

        import collector_reading

        self.assertEqual(EXPECTED_COLLECTOR_READING, stdout_mock.getvalue())
Beispiel #37
0
  def test_excludes_private_attr(self):
    """
    Checks that the default attributes for our csv output doesn't include private fields.
    """

    if stem.prereq._is_python_26():
      self.skipTest('(header added in python 2.7)')
      return

    desc = RelayDescriptor.create()
    desc_csv = export_csv(desc)

    self.assertTrue(',signature' in desc_csv)
    self.assertFalse(',_digest' in desc_csv)
    self.assertFalse(',_annotation_lines' in desc_csv)
Beispiel #38
0
    def test_excludes_private_attr(self):
        """
    Checks that the default attributes for our csv output doesn't include private fields.
    """

        if stem.prereq._is_python_26():
            self.skipTest('(header added in python 2.7)')
            return

        desc = RelayDescriptor.create()
        desc_csv = export_csv(desc)

        self.assertTrue(',signature' in desc_csv)
        self.assertFalse(',_digest' in desc_csv)
        self.assertFalse(',_annotation_lines' in desc_csv)
Beispiel #39
0
    def test_saving_and_loading_descriptors(self):
        server_desc = RelayDescriptor.create(
            {'router': 'caerSidi 71.35.133.197 9001 0 0'})

        with patch('stem.descriptor.remote.get_server_descriptors',
                   _download_of(server_desc)):
            try:
                import saving_and_loading_descriptors

                with open('/tmp/descriptor_dump') as descriptor_file:
                    self.assertTrue(descriptor_file.read().startswith(
                        'router caerSidi 71.35.133.197'))
            finally:
                if os.path.exists('/tmp/descriptor_dump'):
                    os.remove('/tmp/descriptor_dump')
Beispiel #40
0
    def test_check_digests(self):
        import check_digests as module
        fingerprint = 'A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB'

        extrainfo_desc = RelayExtraInfoDescriptor.create()
        server_desc = RelayDescriptor.create(
            {'extra-info-digest': extrainfo_desc.digest()}, sign=True)

        encoded_digest = base64.b64encode(
            binascii.unhexlify(server_desc.digest())).rstrip(b'=')

        consensus_desc = RouterStatusEntryV3.create({
            'r':
            'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s %s 2012-08-06 11:19:31 71.35.150.29 9001 0'
            % encoded_digest.decode('utf-8'),
        })

        bad_consensus_desc = RouterStatusEntryV3.create({
            'r':
            'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0',
        })

        with patch('stem.descriptor.remote.get_server_descriptors',
                   _download_of(server_desc)):
            with patch('stem.descriptor.remote.get_extrainfo_descriptors',
                       _download_of(extrainfo_desc)):
                # correctly signed descriptors

                with patch('stem.descriptor.remote.get_consensus',
                           _download_of(consensus_desc)):
                    with patch('sys.stdout',
                               new_callable=io.StringIO) as stdout_mock:
                        module.validate_relay(fingerprint)
                        self.assertEqual(EXPECTED_CHECK_DIGESTS_OK,
                                         stdout_mock.getvalue())

                # incorrect server descriptor digest

                with patch('stem.descriptor.remote.get_consensus',
                           _download_of(bad_consensus_desc)):
                    with patch('sys.stdout',
                               new_callable=io.StringIO) as stdout_mock:
                        module.validate_relay(fingerprint)
                        self.assertEqual(
                            EXPECTED_CHECK_DIGESTS_BAD % server_desc.digest(),
                            stdout_mock.getvalue())
Beispiel #41
0
    def test_mirror_mirror_on_the_wall_4(self, get_desc_mock, stdout_mock):
        get_desc_mock.return_value = iter([
            RelayDescriptor.create(
                {
                    'router':
                    'caerSidi 71.35.133.197 9001 0 0',
                    'fingerprint':
                    '2C3C 4662 5698 B6D6 7DF3 2BC1 918A D3EE 1F99 06B1',
                },
                exit_policy=ExitPolicy('accept *:*'),
                validate=False)
        ])

        exec_documentation_example('collector_reading.py')
        self.assertEqual(
            '1 relays published an exiting policy today...\n\n  caerSidi (2C3C46625698B6D67DF32BC1918AD3EE1F9906B1)\n',
            stdout_mock.getvalue())
Beispiel #42
0
    def _expect_invalid_attr(self, desc_text, attr=None, expected_value=None):
        """
    Asserts that construction will fail due to desc_text having a malformed
    attribute. If an attr is provided then we check that it matches an expected
    value when we're constructed without validation.
    """

        self.assertRaises(ValueError, RelayDescriptor, desc_text, True)
        desc = RelayDescriptor(desc_text, validate=False)

        if attr:
            # check that the invalid attribute matches the expected value when
            # constructed without validation

            self.assertEqual(expected_value, getattr(desc, attr))
        else:
            # check a default attribute
            self.assertEqual('caerSidi', desc.nickname)
def main(reactor):
    proto = yield txtorcon.build_local_tor_connection(reactor,
                                                      build_state=False)

    or_nickname = "moria1"
    print "Trying to get decriptor information about", or_nickname
    # If the fingerprint is used in place of nickname then, desc/id/<OR identity>
    # should be used.
    descriptor_info = yield proto.get_info('desc/name/' + or_nickname)

    descriptor_info = descriptor_info['desc/name/' + or_nickname]
    try:
        from stem.descriptor.server_descriptor import RelayDescriptor
        relay_info = RelayDescriptor(descriptor_info)
        print "The relay's fingerprint is:", relay_info.fingerprint
        print "Time in UTC when the descriptor was made:", relay_info.published
    except ImportError as e:
        print "Error:", e
Beispiel #44
0
    def test_multiple_descriptors(self):
        """
    Exports multiple descriptors, making sure that we get them back in the same
    order.
    """

        nicknames = ('relay1', 'relay3', 'relay2', 'caerSidi', 'zeus')
        descriptors = []

        for nickname in nicknames:
            router_line = '%s 71.35.133.197 9001 0 0' % nickname
            descriptors.append(RelayDescriptor.create({'router': router_line}))

        expected = '\n'.join(nicknames) + '\n'
        self.assertEqual(
            expected,
            export_csv(descriptors,
                       included_fields=('nickname', ),
                       header=False))
Beispiel #45
0
  def test_missing_required_attr(self):
    """
    Test making a descriptor with a missing required attribute.
    """

    for attr in stem.descriptor.server_descriptor.REQUIRED_FIELDS:
      desc_text = get_relay_server_descriptor(exclude = [attr], content = True)
      self.assertRaises(ValueError, RelayDescriptor, desc_text)

      # check that we can still construct it without validation
      desc = RelayDescriptor(desc_text, validate = False)

      # for one of them checks that the corresponding values are None
      if attr == "router":
        self.assertEquals(None, desc.nickname)
        self.assertEquals(None, desc.address)
        self.assertEquals(None, desc.or_port)
        self.assertEquals(None, desc.socks_port)
        self.assertEquals(None, desc.dir_port)
Beispiel #46
0
  def test_missing_required_attr(self):
    """
    Test making a descriptor with a missing required attribute.
    """

    for attr in stem.descriptor.server_descriptor.REQUIRED_FIELDS:
      desc_text = RelayDescriptor.content(exclude = [attr])
      self.assertRaises(ValueError, RelayDescriptor, desc_text, True)

      # check that we can still construct it without validation
      desc = RelayDescriptor(desc_text, validate = False)

      # for one of them checks that the corresponding values are None
      if attr == 'router':
        self.assertEqual(None, desc.nickname)
        self.assertEqual(None, desc.address)
        self.assertEqual(None, desc.or_port)
        self.assertEqual(None, desc.socks_port)
        self.assertEqual(None, desc.dir_port)
Beispiel #47
0
def generateDescriptors(count=None, rundir=None):
    """Run a script which creates fake bridge descriptors for testing purposes.

    :param integer count: Number of mocked bridges to generate descriptor
        for. (default: 3)
    :type rundir: string or None
    :param rundir: If given, use this directory as the current working
        directory for the bridge descriptor generator script to run in. The
        directory MUST already exist, and the descriptor files will be created
        in it. If None, use the whatever directory we are currently in.
    """
    from stem.descriptor.server_descriptor import RelayDescriptor

    count = count if count else 3
    rundir = rundir if rundir else os.getcwd()

    for i in range(count):
        with open(os.path.join(rundir, 'descriptor_%i' % i),
                  'w') as descriptor_file:
            descriptor_file.write(RelayDescriptor.content(sign=True))
Beispiel #48
0
  def test_minimal_descriptor(self):
    """
    Exports a single minimal tor server descriptor.
    """

    if stem.prereq._is_python_26():
      self.skipTest('(header added in python 2.7)')
      return

    desc = RelayDescriptor.create({
      'router': 'caerSidi 71.35.133.197 9001 0 0',
      'published': '2012-03-01 17:15:27',
    })

    desc_csv = export_csv(desc, included_fields = ('nickname', 'address', 'published'), header = False)
    expected = 'caerSidi,71.35.133.197,2012-03-01 17:15:27\n'
    self.assertEqual(expected, desc_csv)

    desc_csv = export_csv(desc, included_fields = ('nickname', 'address', 'published'), header = True)
    expected = 'nickname,address,published\n' + expected
    self.assertEqual(expected, desc_csv)
Beispiel #49
0
  def test_read_and_write_history(self):
    """
    Parses a read-history and write-history entry. This is now a deprecated
    field for relay server descriptors but is still found in archives and
    extra-info descriptors.
    """

    for field in ('read-history', 'write-history'):
      value = '2005-12-16 18:00:48 (900 s) 81,8848,8927,8927,83,8848'
      desc = RelayDescriptor.create({'opt %s' % field: value})

      if field == 'read-history':
        attr = (desc.read_history_end, desc.read_history_interval, desc.read_history_values)
      else:
        attr = (desc.write_history_end, desc.write_history_interval, desc.write_history_values)

      expected_end = datetime.datetime(2005, 12, 16, 18, 0, 48)
      expected_values = [81, 8848, 8927, 8927, 83, 8848]

      self.assertEqual(expected_end, attr[0])
      self.assertEqual(900, attr[1])
      self.assertEqual(expected_values, attr[2])
Beispiel #50
0
def main(reactor):
    tor = yield txtorcon.connect(reactor)

    or_nickname = "moria1"
    print("Trying to get decriptor information about '{}'".format(or_nickname))
    # If the fingerprint is used in place of nickname then, desc/id/<OR identity>
    # should be used.
    try:
        descriptor_info = yield tor.protocol.get_info('desc/name/' +
                                                      or_nickname)
    except txtorcon.TorProtocolError:
        print(
            "No information found. Enable descriptor downloading by setting:")
        print("  UseMicrodescritors 0")
        print("In your torrc")
        raise SystemExit(1)

    descriptor_info = descriptor_info.values()[0]
    relay_info = RelayDescriptor(descriptor_info)
    print("The relay's fingerprint is: {}".format(relay_info.fingerprint))
    print("Time in UTC when the descriptor was made: {}".format(
        relay_info.published))
Beispiel #51
0
  def test_read_and_write_history(self):
    """
    Parses a read-history and write-history entry. This is now a deprecated
    field for relay server descriptors but is still found in archives and
    extra-info descriptors.
    """

    for field in ('read-history', 'write-history'):
      value = '2005-12-16 18:00:48 (900 s) 81,8848,8927,8927,83,8848'
      desc = RelayDescriptor.create({'opt %s' % field: value})

      if field == 'read-history':
        attr = (desc.read_history_end, desc.read_history_interval, desc.read_history_values)
      else:
        attr = (desc.write_history_end, desc.write_history_interval, desc.write_history_values)

      expected_end = datetime.datetime(2005, 12, 16, 18, 0, 48)
      expected_values = [81, 8848, 8927, 8927, 83, 8848]

      self.assertEqual(expected_end, attr[0])
      self.assertEqual(900, attr[1])
      self.assertEqual(expected_values, attr[2])
Beispiel #52
0
    def test_protocols(self):
        """
    Checks a 'proto' line.
    """

        desc = RelayDescriptor.create({
            'proto':
            'Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=1-4 LinkAuth=1 Microdesc=1 Relay=1-2'
        })
        self.assertEqual(
            {
                'Cons': [1],
                'Desc': [1],
                'DirCache': [1],
                'HSDir': [1],
                'HSIntro': [3],
                'HSRend': [1],
                'Link': [1, 2, 3, 4],
                'LinkAuth': [1],
                'Microdesc': [1],
                'Relay': [1, 2]
            }, desc.protocols)
Beispiel #53
0
    def test_download_descriptor(self):
        import download_descriptor

        with patch('sys.stdout', new_callable=io.StringIO) as stdout_mock:
            with patch('stem.descriptor.remote.get_server_descriptors',
                       _download_of([])):
                download_descriptor.main(['--help'])
                self.assertTrue(stdout_mock.getvalue().startswith(
                    "Downloads a descriptor through Tor's ORPort"))

        with patch('sys.stdout', new_callable=io.StringIO) as stdout_mock:
            download_descriptor.main(['--type', 'kaboom'])
            self.assertEqual(EXPECTED_DOWNLOAD_DESCRIPTOR_UNKNOWN_TYPE,
                             stdout_mock.getvalue())

        server_desc = RelayDescriptor.create(
            {'router': 'caerSidi 71.35.133.197 9001 0 0'})

        with patch('sys.stdout', new_callable=io.StringIO) as stdout_mock:
            with patch('stem.descriptor.remote.get_server_descriptors',
                       _download_of(server_desc)):
                download_descriptor.main(['--dirport', '1.2.3.4:443'])
                self.assertTrue(stdout_mock.getvalue().startswith(
                    EXPECTED_DOWNLOAD_DESCRIPTOR_PREFIX))
Beispiel #54
0
 def test_descriptor_signing(self):
   RelayDescriptor.create(sign = True)
   self.assertRaisesRegexp(NotImplementedError, 'Signing of BridgeDescriptor not implemented', BridgeDescriptor.create, sign = True)
Beispiel #55
0
  def test_multiple_descriptor_types(self):
    """
    Attempts to make a csv with multiple descriptor types.
    """

    self.assertRaises(ValueError, export_csv, (RelayDescriptor.create(), BridgeDescriptor.create()))
Beispiel #56
0
from stem.descriptor.server_descriptor import RelayDescriptor

# prints 'caerSidi (71.35.133.197:9001)'
desc = RelayDescriptor.create()
print("%s (%s:%s)" % (desc.nickname, desc.address, desc.or_port))

# prints 'demo (127.0.0.1:80)'
desc = RelayDescriptor.create({'router': 'demo 127.0.0.1 80 0 0'})
print("%s (%s:%s)" % (desc.nickname, desc.address, desc.or_port))
Beispiel #57
0
  def test_mirror_mirror_on_the_wall_4(self, reader_mock, stdout_mock):
    reader = reader_mock().__enter__()
    reader.__iter__.return_value = iter([RelayDescriptor.create({'router': 'caerSidi 71.35.133.197 9001 0 0'})])

    exec_documentation_example('past_descriptors.py')
    self.assertEqual('found relay caerSidi (None)\n', stdout_mock.getvalue())
Beispiel #58
0
 def test_from_str(self):
     sig = RelayDescriptor.create()
     self.assertEqual(sig, RelayDescriptor.from_str(str(sig)))
Beispiel #59
0
 def test_descriptor_signing(self):
     RelayDescriptor.create(sign=True)
     self.assertRaisesRegexp(NotImplementedError,
                             'Signing of BridgeDescriptor not implemented',
                             BridgeDescriptor.create,
                             sign=True)