Example #1
0
File: cell.py Project: dmr-x/stem
  def test_unpack_for_new_link(self):
    expected_certs = (
      (CertType.LINK, 1, b'0\x82\x02F0\x82\x01\xaf'),
      (CertType.IDENTITY, 2, b'0\x82\x01\xc90\x82\x012'),
      (CertType.UNKNOWN, 4, b'\x01\x04\x00\x06m\x1f'),
      (CertType.UNKNOWN, 5, b'\x01\x05\x00\x06m\n\x01'),
      (CertType.UNKNOWN, 7, b'\x1a\xa5\xb3\xbd\x88\xb1C'),
    )

    content = test_data('new_link_cells')

    version_cell, content = Cell.pop(content, 2)
    self.assertEqual(VersionsCell([3, 4, 5]), version_cell)

    certs_cell, content = Cell.pop(content, 2)
    self.assertEqual(CertsCell, type(certs_cell))
    self.assertEqual(len(expected_certs), len(certs_cell.certificates))

    for i, (cert_type, cert_type_int, cert_prefix) in enumerate(expected_certs):
      self.assertEqual(cert_type, certs_cell.certificates[i].type)
      self.assertEqual(cert_type_int, certs_cell.certificates[i].type_int)
      self.assertTrue(certs_cell.certificates[i].value.startswith(cert_prefix))

    auth_challenge_cell, content = Cell.pop(content, 2)
    self.assertEqual(AuthChallengeCell([1, 3], b'\x89Y\t\x99\xb2\x1e\xd9*V\xb6\x1bn\n\x05\xd8/\xe3QH\x85\x13Z\x17\xfc\x1c\x00{\xa9\xae\x83^K'), auth_challenge_cell)

    netinfo_cell, content = Cell.pop(content, 2)
    self.assertEqual(NetinfoCell, type(netinfo_cell))
    self.assertEqual(datetime.datetime(2018, 1, 14, 1, 46, 56), netinfo_cell.timestamp)
    self.assertEqual(Address('127.0.0.1'), netinfo_cell.receiver_address)
    self.assertEqual([Address('97.113.15.2')], netinfo_cell.sender_addresses)
    self.assertEqual(ZERO * 492, netinfo_cell.unused)

    self.assertEqual(b'', content)  # check that we've consumed all of the bytes
Example #2
0
File: cell.py Project: zmchu/stem
    def test_auth_challenge_cell(self):
        for cell_bytes, (challenge, methods, unused,
                         link_protocol) in AUTH_CHALLENGE_CELLS.items():
            if not unused.strip(ZERO):
                self.assertEqual(
                    cell_bytes,
                    AuthChallengeCell(methods, challenge).pack(link_protocol))
            else:
                self.assertEqual(
                    cell_bytes,
                    AuthChallengeCell(methods, challenge,
                                      unused=unused).pack(link_protocol))

            cell = Cell.pop(cell_bytes, link_protocol)[0]
            self.assertEqual(challenge, cell.challenge)
            self.assertEqual(methods, cell.methods)
            self.assertEqual(unused, cell.unused)
            self.assertEqual(cell_bytes, cell.pack(link_protocol))

        self.assertRaisesWith(
            ValueError,
            'AUTH_CHALLENGE cell should have a payload of 38 bytes, but only had 16',
            Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE[:10] +
            b'\x00\x02\x00\x01\x00\x03', 2)
        self.assertRaisesWith(
            ValueError,
            'AUTH_CHALLENGE should have 3 methods, but only had 4 bytes for it',
            Cell.pop,
            b'\x00\x00\x82\x00&' + CHALLENGE + b'\x00\x03\x00\x01\x00\x03', 2)
Example #3
0
File: cell.py Project: zmchu/stem
    def test_vpadding_cell(self):
        for cell_bytes, (payload, link_protocol) in VPADDING_CELLS.items():
            self.assertEqual(cell_bytes,
                             VPaddingCell(payload=payload).pack(link_protocol))

            cell = Cell.pop(cell_bytes, link_protocol)[0]
            self.assertEqual(payload, cell.payload)
            self.assertEqual(b'', cell.unused)  # always empty
            self.assertEqual(cell_bytes, cell.pack(link_protocol))

        empty_constructed_cell = VPaddingCell(size=0)
        self.assertEqual(VPADDING_CELL_EMPTY_PACKED,
                         empty_constructed_cell.pack(2))
        self.assertEqual(b'', empty_constructed_cell.payload)

        self.assertRaisesWith(
            ValueError,
            'VPaddingCell constructor specified both a size of 5 bytes and payload of 1 bytes',
            VPaddingCell, 5, '\x02')
        self.assertRaisesWith(ValueError,
                              'VPaddingCell size (-15) cannot be negative',
                              VPaddingCell, -15)
        self.assertRaisesWith(
            ValueError,
            'VPaddingCell constructor must specify payload or size',
            VPaddingCell)
Example #4
0
File: cell.py Project: zmchu/stem
    def test_created_fast_cell(self):
        for cell_bytes, (circ_id, key_material, derivative_key, unused,
                         link_protocol) in CREATED_FAST_CELLS.items():
            if not unused.strip(ZERO):
                self.assertEqual(
                    cell_bytes,
                    CreatedFastCell(circ_id, derivative_key,
                                    key_material).pack(link_protocol))
            else:
                self.assertEqual(
                    cell_bytes,
                    CreatedFastCell(circ_id,
                                    derivative_key,
                                    key_material,
                                    unused=unused).pack(link_protocol))

            cell = Cell.pop(cell_bytes, link_protocol)[0]
            self.assertEqual(circ_id, cell.circ_id)
            self.assertEqual(key_material, cell.key_material)
            self.assertEqual(derivative_key, cell.derivative_key)
            self.assertEqual(unused, cell.unused)
            self.assertEqual(cell_bytes, cell.pack(link_protocol))

        self.assertRaisesWith(ValueError,
                              'Key material should be 20 bytes, but was 3',
                              CreateFastCell, 5, 'boo')
Example #5
0
File: cell.py Project: zmchu/stem
    def test_certs_cell(self):
        for cell_bytes, (certs, unused, link_protocol) in CERTS_CELLS.items():
            if not unused.strip(ZERO):
                self.assertEqual(cell_bytes,
                                 CertsCell(certs).pack(link_protocol))
            else:
                self.assertEqual(
                    cell_bytes,
                    CertsCell(certs, unused=unused).pack(link_protocol))

            cell = Cell.pop(cell_bytes, link_protocol)[0]
            self.assertEqual(certs, cell.certificates)
            self.assertEqual(unused, cell.unused)
            self.assertEqual(cell_bytes, cell.pack(link_protocol))

        # truncated or missing certificates should error

        self.assertRaisesWith(
            ValueError,
            'CERTS cell should have a certificate with 3 bytes, but only had 1 remaining',
            Cell.pop, b'\x00\x00\x81\x00\x05\x01\x01\x00\x03\x08', 2)
        self.assertRaisesWith(
            ValueError,
            'CERTS cell indicates it should have 2 certificates, but only contained 1',
            Cell.pop, b'\x00\x00\x81\x00\x05\x02\x01\x00\x01\x08', 2)
Example #6
0
File: cell.py Project: zmchu/stem
    def test_destroy_cell(self):
        for cell_bytes, (circ_id, reason, reason_int, unused,
                         link_protocol) in DESTROY_CELLS.items():
            if not unused.strip(ZERO):
                self.assertEqual(
                    cell_bytes,
                    DestroyCell(circ_id, reason).pack(link_protocol))
                self.assertEqual(
                    cell_bytes,
                    DestroyCell(circ_id, reason_int).pack(link_protocol))
            else:
                self.assertEqual(
                    cell_bytes,
                    DestroyCell(circ_id, reason,
                                unused=unused).pack(link_protocol))
                self.assertEqual(
                    cell_bytes,
                    DestroyCell(circ_id, reason_int,
                                unused=unused).pack(link_protocol))

            cell = Cell.pop(cell_bytes, link_protocol)[0]
            self.assertEqual(circ_id, cell.circ_id)
            self.assertEqual(reason, cell.reason)
            self.assertEqual(reason_int, cell.reason_int)
            self.assertEqual(unused, cell.unused)
            self.assertEqual(cell_bytes, cell.pack(link_protocol))
Example #7
0
File: cell.py Project: dmr-x/stem
  def test_versions_cell(self):
    for cell_bytes, (versions, link_protocol) in VERSIONS_CELLS.items():
      self.assertEqual(cell_bytes, VersionsCell(versions).pack(link_protocol))

      cell = Cell.pop(cell_bytes, link_protocol)[0]
      self.assertEqual(versions, cell.versions)
      self.assertEqual(b'', cell.unused)  # always empty
      self.assertEqual(cell_bytes, cell.pack(link_protocol))
Example #8
0
File: cell.py Project: dmr-x/stem
  def test_padding_cell(self):
    for cell_bytes, (payload, link_protocol) in PADDING_CELLS.items():
      self.assertEqual(cell_bytes, PaddingCell(payload).pack(link_protocol))

      cell = Cell.pop(cell_bytes, link_protocol)[0]
      self.assertEqual(payload, cell.payload)
      self.assertEqual(b'', cell.unused)  # always empty
      self.assertEqual(cell_bytes, cell.pack(link_protocol))
Example #9
0
    def test_relay_cell(self):
        for cell_bytes, (command, command_int, circ_id, stream_id, data,
                         digest) in RELAY_CELLS.items():
            self.assertEqual(
                cell_bytes,
                RelayCell(circ_id, command, data, digest, stream_id).pack(2))
            self.assertEqual(
                cell_bytes,
                RelayCell(circ_id, command_int, data, digest,
                          stream_id).pack(2))

            cell = Cell.pop(cell_bytes, 2)[0]
            self.assertEqual(circ_id, cell.circ_id)
            self.assertEqual(command, cell.command)
            self.assertEqual(command_int, cell.command_int)
            self.assertEqual(data, cell.data)
            self.assertEqual(digest, cell.digest)
            self.assertEqual(stream_id, cell.stream_id)
            self.assertEqual(ZERO * (498 - len(cell.data)), cell.unused)

        digest = hashlib.sha1(b'hi')
        self.assertEqual(
            3257622417,
            RelayCell(5, 'RELAY_BEGIN_DIR', '', digest, 564346860).digest)
        self.assertEqual(
            3257622417,
            RelayCell(5, 'RELAY_BEGIN_DIR', '', digest.digest(),
                      564346860).digest)
        self.assertEqual(
            3257622417,
            RelayCell(5, 'RELAY_BEGIN_DIR', '', 3257622417, 564346860).digest)
        self.assertRaisesRegexp(
            ValueError,
            'RELAY cell digest must be a hash, string, or int but was a list',
            RelayCell, 5, 'RELAY_BEGIN_DIR', '', [], 564346860)
        self.assertRaisesRegexp(
            ValueError,
            "Invalid enumeration 'NO_SUCH_COMMAND', options are RELAY_BEGIN, RELAY_DATA",
            RelayCell, 5, 'NO_SUCH_COMMAND', '', 5, 564346860)

        mismatched_data_length_bytes = b''.join((
            b'\x00\x01',  # circ ID
            b'\x03',  # command
            b'\x02',  # relay command
            b'\x00\x00',  # 'recognized'
            b'\x00\x01',  # stream ID
            b'\x15:m\xe0',  # digest
            b'\xFF\xFF',  # data len (65535, clearly invalid)
            ZERO * 498,  # data
        ))
        expected_message = 'RELAY cell said it had 65535 bytes of data, but only had 498'
        self.assertRaisesRegexp(ValueError,
                                '^%s$' % re.escape(expected_message), Cell.pop,
                                mismatched_data_length_bytes, 2)
Example #10
0
File: cell.py Project: dmr-x/stem
  def test_netinfo_cell(self):
    for cell_bytes, (timestamp, receiver_address, sender_addresses, unused, link_protocol) in NETINFO_CELLS.items():
      if not unused.strip(ZERO):
        self.assertEqual(cell_bytes, NetinfoCell(receiver_address, sender_addresses, timestamp).pack(link_protocol))
      else:
        self.assertEqual(cell_bytes, NetinfoCell(receiver_address, sender_addresses, timestamp, unused = unused).pack(link_protocol))

      cell = Cell.pop(cell_bytes, link_protocol)[0]
      self.assertEqual(timestamp, cell.timestamp)
      self.assertEqual(receiver_address, cell.receiver_address)
      self.assertEqual(sender_addresses, cell.sender_addresses)
      self.assertEqual(unused, cell.unused)
      self.assertEqual(cell_bytes, cell.pack(link_protocol))
Example #11
0
    def test_create_fast_cell(self):
        for cell_bytes, (circ_id, key_material) in CREATE_FAST_CELLS.items():
            self.assertEqual(cell_bytes,
                             CreateFastCell(circ_id, key_material).pack(5))

            cell = Cell.pop(cell_bytes, 5)[0]
            self.assertEqual(circ_id, cell.circ_id)
            self.assertEqual(key_material, cell.key_material)
            self.assertEqual(ZERO * 489, cell.unused)

        self.assertRaisesRegexp(ValueError,
                                'Key material should be 20 bytes, but was 3',
                                CreateFastCell, 5, 'boo')
Example #12
0
    def test_certs_cell(self):
        for cell_bytes, certs in CERTS_CELLS.items():
            self.assertEqual(cell_bytes, CertsCell(certs).pack(2))
            self.assertEqual(certs, Cell.pop(cell_bytes, 2)[0].certificates)

        # extra bytes after the last certificate should be ignored

        self.assertEqual(
            [Certificate(1, '\x08')],
            Cell.pop(b'\x00\x00\x81\x00\x07\x01\x01\x00\x01\x08\x06\x04',
                     2)[0].certificates)

        # ... but truncated or missing certificates should error

        self.assertRaisesRegexp(
            ValueError,
            'CERTS cell should have a certificate with 3 bytes, but only had 1 remaining',
            Cell.pop, b'\x00\x00\x81\x00\x05\x01\x01\x00\x03\x08', 2)
        self.assertRaisesRegexp(
            ValueError,
            'CERTS cell indicates it should have 2 certificates, but only contained 1',
            Cell.pop, b'\x00\x00\x81\x00\x05\x02\x01\x00\x01\x08', 2)
Example #13
0
    def test_netinfo_cell(self):
        for cell_bytes, (timestamp, receiver_address,
                         sender_addresses) in NETINFO_CELLS.items():
            self.assertEqual(
                cell_bytes,
                NetinfoCell(receiver_address, sender_addresses,
                            timestamp).pack(2))

            cell = Cell.pop(cell_bytes, 2)[0]
            self.assertEqual(timestamp, cell.timestamp)
            self.assertEqual(receiver_address, cell.receiver_address)
            self.assertEqual(sender_addresses, cell.sender_addresses)
            self.assertEqual(ZERO * 492, cell.unused)
Example #14
0
    def _recv(self, raw=False):
        """
    Reads the next cell from our ORPort. If none is present this blocks
    until one is available.

    :param bool raw: provides bytes rather than parsing as a cell if **True**

    :returns: next :class:`~stem.client.cell.Cell`
    """

        with self._orport_lock:
            # cells begin with [circ_id][cell_type][...]

            circ_id_size = self.link_protocol.circ_id_size.size

            while len(self._orport_buffer) < (circ_id_size +
                                              CELL_TYPE_SIZE.size):
                self._orport_buffer += self._orport.recv(
                )  # read until we know the cell type

            cell_type = Cell.by_value(
                CELL_TYPE_SIZE.pop(self._orport_buffer[circ_id_size:])[0])

            if cell_type.IS_FIXED_SIZE:
                cell_size = circ_id_size + CELL_TYPE_SIZE.size + FIXED_PAYLOAD_LEN
            else:
                # variable length, our next field is the payload size

                while len(self._orport_buffer) < (circ_id_size +
                                                  CELL_TYPE_SIZE.size +
                                                  FIXED_PAYLOAD_LEN.size):
                    self._orport_buffer += self._orport.recv(
                    )  # read until we know the cell size

                payload_len = FIXED_PAYLOAD_LEN.pop(
                    self._orport_buffer[circ_id_size +
                                        CELL_TYPE_SIZE.size:])[0]
                cell_size = circ_id_size + CELL_TYPE_SIZE.size + FIXED_PAYLOAD_LEN.size + payload_len

            while len(self._orport_buffer) < cell_size:
                self._orport_buffer += self._orport.recv(
                )  # read until we have the full cell

            if raw:
                content, self._orport_buffer = split(self._orport_buffer,
                                                     cell_size)
                return content
            else:
                cell, self._orport_buffer = Cell.pop(self._orport_buffer,
                                                     self.link_protocol)
                return cell
Example #15
0
    def test_destroy_cell(self):
        for cell_bytes, (circ_id, reason, reason_int,
                         unused) in DESTROY_CELLS.items():
            # Packed cells always pad with zeros, so if we're testing something with
            # non-zero padding then skip this check.

            if not unused.strip(ZERO):
                self.assertEqual(cell_bytes,
                                 DestroyCell(circ_id, reason).pack(5))
                self.assertEqual(cell_bytes,
                                 DestroyCell(circ_id, reason_int).pack(5))

            cell = Cell.pop(cell_bytes, 5)[0]
            self.assertEqual(circ_id, cell.circ_id)
            self.assertEqual(reason, cell.reason)
            self.assertEqual(reason_int, cell.reason_int)
            self.assertEqual(unused, cell.unused)
Example #16
0
    def test_auth_challenge_cell(self):
        for cell_bytes, (challenge, methods) in AUTH_CHALLENGE_CELLS.items():
            self.assertEqual(cell_bytes,
                             AuthChallengeCell(methods, challenge).pack(2))

            cell = Cell.pop(cell_bytes, 2)[0]
            self.assertEqual(challenge, cell.challenge)
            self.assertEqual(methods, cell.methods)
            self.assertEqual(b'', cell.unused)

        self.assertRaisesRegexp(
            ValueError,
            'AUTH_CHALLENGE cell should have a payload of 38 bytes, but only had 16',
            Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE[:10] +
            b'\x00\x02\x00\x01\x00\x03', 2)
        self.assertRaisesRegexp(
            ValueError,
            'AUTH_CHALLENGE should have 3 methods, but only had 4 bytes for it',
            Cell.pop,
            b'\x00\x00\x82\x00&' + CHALLENGE + b'\x00\x03\x00\x01\x00\x03', 2)
Example #17
0
    def test_vpadding_cell(self):
        for cell_bytes, payload in VPADDING_CELLS.items():
            self.assertEqual(cell_bytes, VPaddingCell(payload=payload).pack(2))
            self.assertEqual(payload, Cell.pop(cell_bytes, 2)[0].payload)

        empty_constructed_cell = VPaddingCell(size=0)
        self.assertEqual(VPADDING_CELL_EMPTY_PACKED,
                         empty_constructed_cell.pack(2))
        self.assertEqual(b'', empty_constructed_cell.payload)

        self.assertRaisesRegexp(
            ValueError,
            'VPaddingCell constructor specified both a size of 5 bytes and payload of 1 bytes',
            VPaddingCell, 5, '\x02')
        self.assertRaisesRegexp(
            ValueError,
            re.escape('VPaddingCell size (-15) cannot be negative'),
            VPaddingCell, -15)
        self.assertRaisesRegexp(
            ValueError,
            re.escape('VPaddingCell constructor must specify payload or size'),
            VPaddingCell)
Example #18
0
 def test_padding_cell(self):
     for cell_bytes, payload in PADDING_CELLS.items():
         self.assertEqual(cell_bytes, PaddingCell(payload).pack(2))
         self.assertEqual(payload, Cell.pop(cell_bytes, 2)[0].payload)
Example #19
0
 def test_versions_cell(self):
     for cell_bytes, (versions, link_protocol) in VERSIONS_CELLS.items():
         self.assertEqual(cell_bytes,
                          VersionsCell(versions).pack(link_protocol))
         self.assertEqual(versions,
                          Cell.pop(cell_bytes, link_protocol)[0].versions)