Пример #1
0
    def test_process(self):
        exp = ExpectFinished()
        # this probably should use mock objects to check if calcFinished
        # is called with them
        state = ConnectionState()
        msg = Message(
            ContentType.handshake,
            bytearray([HandshakeType.finished, 0, 0, 12]) +
            bytearray(b"\xa3;\x9c\xc9\'E\xbc\xf6\xc7\x96\xaf\x7f"))

        exp.process(state, msg)
Пример #2
0
    def test_process_with_multiple_values_one_matching_description(self):
        exp = ExpectAlert(AlertLevel.fatal, [
            AlertDescription.record_overflow,
            AlertDescription.decompression_failure
        ])

        state = ConnectionState()
        msg = Message(ContentType.alert, bytearray(b'\x02\x16'))

        # does NOT raise exception
        exp.process(state, msg)
Пример #3
0
 def generate(self, state):
     """Creata a single message to empty the list."""
     msg = self.fragment_list.pop(0)
     content_type = msg.contentType
     data = msg.write()
     while len(self.fragment_list) > 0:
         msg_frag = self.fragment_list.pop(0)
         assert msg_frag.contentType == content_type
         data += msg_frag.write()
     msg_ret = Message(content_type, data)
     return msg_ret
Пример #4
0
    def test_sendMessage(self):
        sock = MockSocket(bytearray(), blockEveryOther=True)
        sock.blockWrite = True

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        blocked = False
        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                blocked = True
            else:
                break

        # no write so no blocking
        self.assertFalse(blocked)
        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\x02\x01'))

        blocked = False
        for res in msgSock.sendMessage(msg):
            if res in (0, 1):
                blocked = True
            else:
                break

        self.assertTrue(blocked)
        self.assertEqual(len(sock.sent), 2)
        self.assertEqual(bytearray(
            b'\x16' +
            b'\x03\x03' +
            b'\x00\x03' +
            b'\xaa'*3), sock.sent[0])
        self.assertEqual(bytearray(
            b'\x15' +
            b'\x03\x03' +
            b'\x00\x02' +
            b'\x02\x01'), sock.sent[1])
Пример #5
0
    def test_process(self):
        exp = ExpectChangeCipherSpec()

        state = ConnectionState()
        state.msg_sock = mock.MagicMock()

        msg = Message(ContentType.change_cipher_spec, bytearray(1))

        exp.process(state, msg)

        state.msg_sock.calcPendingStates.assert_not_called()
        state.msg_sock.changeReadState.assert_called_once_with()
    def test__sendMsg_with_errored_out_socket(self):
        mockSock = mock.MagicMock()
        mockSock.send.side_effect = socket.error(errno.ETIMEDOUT)

        sock = TLSRecordLayer(mockSock)

        msg = Message(ContentType.handshake, bytearray(10))

        gen = sock._sendMsg(msg, False)

        with self.assertRaises(TLSAbruptCloseError):
            next(gen)
    def test_queueMessageBlocking(self):
        sock = MockSocket(bytearray(), blockEveryOther=True)
        sock.blockWrite = True

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        msgSock.queueMessageBlocking(msg)

        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\x02\x01'))

        msgSock.queueMessageBlocking(msg)

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(
            bytearray(b'\x16' + b'\x03\x03' + b'\x00\x03' + b'\xaa' * 3),
            sock.sent[0])
    def test_queueMessage_with_conflicting_types(self):
        sock = MockSocket(bytearray())

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\x02\x01'))

        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(
            bytearray(b'\x16' + b'\x03\x03' + b'\x00\x03' + b'\xaa' * 3),
            sock.sent[0])

        for res in msgSock.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 2)
        self.assertEqual(
            bytearray(b'\x15' + b'\x03\x03' + b'\x00\x02' + b'\x02\x01'),
            sock.sent[1])
Пример #9
0
    def test_process_with_values_not_matching_anything(self):
        exp = ExpectAlert(AlertLevel.warning, AlertDescription.bad_record_mac)
        state = ConnectionState()
        msg = Message(ContentType.alert, bytearray(b'\xff\xff'))

        with self.assertRaises(AssertionError) as e:
            exp.process(state, msg)

        self.assertEqual(
            str(e.exception), "Alert level 255 != 1, "
            "Expected alert description "
            "\"bad_record_mac\" does not match received "
            "\"255\"")
Пример #10
0
    def test_process(self):
        exp = ExpectCertificateRequest()

        state = ConnectionState()
        msg = CertificateRequest((3, 3))
        msg.create([
            ClientCertificateType.rsa_sign, ClientCertificateType.rsa_fixed_dh
        ], [], [(HashAlgorithm.sha1, SignatureAlgorithm.rsa),
                (HashAlgorithm.sha256, SignatureAlgorithm.rsa),
                (HashAlgorithm.sha384, SignatureAlgorithm.rsa)])
        msg = Message(ContentType.handshake, msg.write())

        exp.process(state, msg)
Пример #11
0
    def run(self):
        """Execute conversation"""
        node = self.conversation
        try:
            while node is not None:
                msg = None
                if node.is_command():
                    # update connection state
                    node.process(self.state)

                    node = node.child
                    continue
                elif node.is_expect():
                    # check peer response
                    try:
                        header, parser = self.state.msg_sock.recvMessageBlocking()
                    except TLSAbruptCloseError:
                        close_node = next((n for n in node.get_all_siblings() if isinstance(n, ExpectClose)), None)
                        if close_node:
                            node = close_node.child
                            continue
                        else:
                            raise AssertionError("Unexpected closure from peer")
                    msg = Message(header.type, parser.bytes)

                    node = next((proc for proc in node.get_all_siblings() if proc.is_match(msg)), None)
                    if node is None:
                        # since we're aborting, the user can't clean up
                        self.state.msg_sock.sock.close()
                        raise AssertionError(
                            "Unexpected message from peer: " + str(msg.contentType) + ", " + str(msg.write()[0])
                        )

                    node.process(self.state, msg)

                    node = node.child
                    continue
                elif node.is_generator():
                    # send message to peer
                    msg = node.generate(self.state)
                    self.state.msg_sock.sendMessageBlocking(msg)
                    node.post_send(self.state)

                    node = node.child
                    continue
                else:
                    raise AssertionError("Unknown decision tree node")
        except:
            # TODO put into a log
            print("Error encountered while processing node " + str(node) + " with last message being: " + repr(msg))
            raise
Пример #12
0
    def test_queueMessage(self):
        sock = MockSocket(bytearray())

        msgSocket = MessageSocket(sock, None)

        msg = Message(ContentType.alert, bytearray(b'\xff\xbb'))

        for res in msgSocket.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\xff\xaa'))

        for res in msgSocket.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        for res in msgSocket.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(sock.sent[0], bytearray(
            b'\x15' +
            b'\x00\x00' +
            b'\x00\x04' +
            b'\xff\xbb' +
            b'\xff\xaa'))
Пример #13
0
    def new_generate(state, old_generate=generator.generate,
                     fragment_list=fragment_list, size=size):
        """Monkey patch for the generate method of the message generator."""
        msg = old_generate(state)
        content_type = msg.contentType
        data = msg.write()
        # since empty messages can be created much more easily with
        # RawMessageGenerator, we don't handle 0 length messages here
        while len(data) > 0:
            # move the data to fragment_list (outside the method)
            fragment_list.append(Message(content_type, data[:size]))
            data = data[size:]

        return fragment_list.pop(0)
Пример #14
0
    def test_sig_algs_mismatched(self):
        sig_algs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa),
                    (HashAlgorithm.sha256, SignatureAlgorithm.rsa),
                    (HashAlgorithm.sha384, SignatureAlgorithm.rsa)]
        exp = ExpectCertificateRequest(sig_algs=sig_algs[0:0])

        state = ConnectionState()
        msg = CertificateRequest((3, 3))
        msg.create([
            ClientCertificateType.rsa_sign, ClientCertificateType.rsa_fixed_dh
        ], [], sig_algs)
        msg = Message(ContentType.handshake, msg.write())

        with self.assertRaises(AssertionError):
            exp.process(state, msg)
Пример #15
0
        def new_send(message, padding, old_send=old_send,
                     substitutions=substitutions, xors=xors):
            """
            Monkey patch for the send method of msg socket.

            message.data is the encrypted tls record, e.g.

            message.data = aead_encrypt(plain); defined by aead suite
            message.data = encrypt(plain + padding) + mac; etm
            message.data = encrypt(plain + mac + padding); mte
            """
            data = message.write()

            data = substitute_and_xor(data, substitutions, xors)

            new_message = Message(message.contentType, data)

            return old_send(new_message, padding)
Пример #16
0
    def test_process_with_resumption(self):
        exp = ExpectChangeCipherSpec()

        state = ConnectionState()
        state.msg_sock = mock.MagicMock()
        state.resuming = True

        state.cipher = mock.Mock(name="cipher")
        state.master_secret = mock.Mock(name="master_secret")
        state.client_random = mock.Mock(name="client_random")
        state.server_random = mock.Mock(name="server_random")

        msg = Message(ContentType.change_cipher_spec, bytearray(1))

        exp.process(state, msg)

        state.msg_sock.calcPendingStates.assert_called_once_with(
            state.cipher, state.master_secret, state.client_random,
            state.server_random, None)
        state.msg_sock.changeReadState.assert_called_once_with()
    def test__sendMsg(self):
        mockSock = MockSocket(bytearray(0))
        sock = TLSRecordLayer(mockSock)
        sock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(10))

        # XXX using private method
        for result in sock._sendMsg(msg, False):
            if result in (0, 1):
                self.assertTrue(False, "Blocking socket")
            else:
                break

        self.assertEqual(len(mockSock.sent), 1)
        self.assertEqual(
            bytearray(b'\x16' +  # handshake message
                      b'\x03\x03' +  # version
                      b'\x00\x0a' +  # payload length
                      b'\x00' * 10  # payload
                      ),
            mockSock.sent[0])
Пример #18
0
 def generate(self, state):
     """Create a tlslite-ng message that can be send"""
     message = Message(self.content_type, self.data)
     return message
Пример #19
0
    def test_is_match(self):
        exp = ExpectChangeCipherSpec()

        msg = Message(ContentType.change_cipher_spec, bytearray([0]))

        self.assertTrue(exp.is_match(msg))
Пример #20
0
    def process(self, state):
        """Send the message over the socket."""
        msg = Message(self.content_type, self.data)

        for _ in state.msg_sock._recordSocket.send(msg):
            pass
Пример #21
0
    def test_is_match_with_unmatching_content_type(self):
        exp = ExpectChangeCipherSpec()

        msg = Message(ContentType.application_data, bytearray([0]))

        self.assertFalse(exp.is_match(msg))
Пример #22
0
    def run(self):
        """Execute conversation"""
        node = self.conversation
        try:
            while node is not None:
                old_node = None
                msg = None
                if node.is_command():
                    # update connection state
                    node.process(self.state)

                    node = node.child
                    continue
                elif node.is_expect():
                    # check peer response
                    try:
                        header, parser = self.state.msg_sock.recvMessageBlocking()
                    except (TLSAbruptCloseError, socket.error):
                        close_node = next((n for n in node.get_all_siblings() \
                                           if isinstance(n, ExpectClose)), None)
                        if close_node:
                            close_node.process(self.state, None)
                            node = close_node.child
                            continue
                        else:
                            raise AssertionError("Unexpected closure from peer")
                    msg = Message(header.type, parser.bytes)
                    old_node = node

                    node = next((proc for proc in node.get_all_siblings()
                                 if proc.is_match(msg)), None)
                    if node is None:
                        # since we're aborting, the user can't clean up
                        self.state.msg_sock.sock.close()
                        raise AssertionError("Unexpected message from peer: " +
                                             guess_response(\
                                                 msg.contentType,
                                                 msg.write(),
                                                 isinstance(header,
                                                            RecordHeader2)))

                    node.process(self.state, msg)

                    node = node.child
                    continue
                elif node.is_generator():
                    # send message to peer
                    msg = node.generate(self.state)
                    try:
                        if msg.write():
                            # sendMessageBlocking is buffered and fragmenting
                            # that means that 0-length messages would get lost
                            self.state.msg_sock.sendMessageBlocking(msg)
                        else:
                            for _ in self.state.msg_sock.sendRecord(msg):
                                # make the method into a blocking one
                                pass
                    except socket.error:
                        close_node = next((n for n in node.get_all_siblings()
                                           if isinstance(n, ExpectClose)), None)
                        if close_node:
                            node = close_node.child
                            continue
                        else:
                            raise AssertionError("Unexpected closure from peer")
                    # allow generators to perform actions after the message
                    # was sent like updating handshake hashes
                    node.post_send(self.state)

                    node = node.child
                    continue
                else:
                    raise AssertionError("Unknown decision tree node")
        except:
            if self.state.msg_sock:
                self.state.msg_sock.sock.close()
            # TODO put into a log
            if node is None:
                node = old_node
            print("Error encountered while processing node " + str(node) +
                  " (child: " + str(node.child) + ") with last message " +
                  "being: " + repr(msg))
            raise
Пример #23
0
    def run(self):
        """Execute conversation"""
        node = self.conversation
        try:
            while node is not None:
                old_node = None
                msg = None
                if node.is_command():
                    # update connection state
                    node.process(self.state)

                    node = node.child
                    continue
                elif node.is_expect():
                    if isinstance(node, ExpectNoMessage):
                        old_timeout = self.state.msg_sock.sock.gettimeout()
                        self.state.msg_sock.sock.settimeout(node.timeout)
                    # check peer response
                    try:
                        header, parser = self.state.msg_sock.\
                            recvMessageBlocking()
                    except (TLSAbruptCloseError, socket.error) as exc:
                        if isinstance(exc, socket.timeout) and \
                                isinstance(node, ExpectNoMessage):
                            # for ExpectNoMessage we have nothing to do
                            # but to continue
                            self.state.msg_sock.sock.settimeout(old_timeout)
                            node = node.child
                            continue
                        close_node = next((n for n in node.get_all_siblings()
                                           if isinstance(n, ExpectClose)),
                                          None)
                        # timeout will happen if the other side hanged, to
                        # try differentiated between (when no alerts are sent)
                        # allow for close only when the connection was actively
                        # closed
                        if close_node and not isinstance(exc, socket.timeout):
                            close_node.process(self.state, None)
                            node = close_node.child
                            continue
                        else:
                            if isinstance(exc, socket.timeout):
                                raise AssertionError(
                                    "Timeout when waiting for peer message")
                            else:
                                raise AssertionError(
                                    "Unexpected closure from peer")
                    msg = Message(header.type, parser.bytes)
                    old_node = node

                    node = next((proc for proc in node.get_all_siblings()
                                 if proc.is_match(msg)), None)
                    if node is None:
                        # since we're aborting, the user can't clean up
                        self.state.msg_sock.sock.close()
                        raise AssertionError("Unexpected message from peer: " +
                                             guess_response(\
                                                 msg.contentType,
                                                 msg.write(),
                                                 isinstance(header,
                                                            RecordHeader2)))

                    node.process(self.state, msg)

                    node = node.child
                    continue
                elif node.is_generator():
                    # send message to peer
                    msg = node.generate(self.state)
                    try:
                        if msg.write():
                            # sendMessageBlocking is buffered and fragmenting
                            # that means that 0-length messages would get lost
                            self.state.msg_sock.sendMessageBlocking(msg)
                        else:
                            for _ in self.state.msg_sock.sendRecord(msg):
                                # make the method into a blocking one
                                pass
                    except socket.error:
                        close_node = next(
                            (n for n in node.get_all_siblings()
                             if isinstance(n, (ExpectClose, ExpectAlert))),
                            None)
                        if close_node:
                            node = close_node.child
                            continue
                        else:
                            raise AssertionError(
                                "Unexpected closure from peer")
                    # allow generators to perform actions after the message
                    # was sent like updating handshake hashes
                    node.post_send(self.state)

                    node = node.child
                    continue
                else:
                    raise AssertionError("Unknown decision tree node")
        except:
            if self.state.msg_sock:
                self.state.msg_sock.sock.close()
            # TODO put into a log
            if node is None:
                node = old_node
            print("Error encountered while processing node " + str(node) +
                  " (child: " + str(node.child) + ") with last message " +
                  "being: " + repr(msg))
            raise
Пример #24
0
    def test_is_match_with_arbitrary_data(self):
        exp = ExpectChangeCipherSpec()

        msg = Message(ContentType.change_cipher_spec, bytearray([243]))

        self.assertTrue(exp.is_match(msg))
Пример #25
0
    def test_process(self):
        exp = ExpectVerify()
        msg = Message(ContentType.handshake,
                      bytearray([SSL2HandshakeType.server_verify]))

        exp.process(None, msg)
Пример #26
0
    def test_is_match(self):
        exp = ExpectApplicationData()

        msg = Message(ContentType.application_data, bytearray(0))

        self.assertTrue(exp.is_match(msg))
Пример #27
0
    def test_process(self):
        exp = ExpectSSL2Alert(SSL2ErrorDescription.bad_certificate)

        msg = Message(ContentType.handshake,
                      bytearray([SSL2HandshakeType.error, 0x00, 0x04]))
        exp.process(None, msg)
Пример #28
0
    def test_is_match(self):
        exp = ExpectAlert()

        msg = Message(ContentType.alert, bytearray(2))

        self.assertTrue(exp.is_match(msg))