def test_sendMessageBlocking(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')) msgSock.sendMessageBlocking(msg) 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])
def test_is_match_with_arbitrary_data(self): exp = ExpectChangeCipherSpec() msg = Message(ContentType.change_cipher_spec, bytearray([243])) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_content_type(self): exp = ExpectChangeCipherSpec() msg = Message(ContentType.application_data, bytearray([0])) self.assertFalse(exp.is_match(msg))
def test_is_match(self): exp = ExpectChangeCipherSpec() msg = Message(ContentType.change_cipher_spec, bytearray([0])) self.assertTrue(exp.is_match(msg))
def test_is_match(self): exp = ExpectAlert() msg = Message(ContentType.alert, bytearray(2)) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_content_type(self): exp = ExpectFinished() msg = Message(ContentType.application_data, bytearray([HandshakeType.finished])) self.assertFalse(exp.is_match(msg))
def test__sendMsg_with_very_slow_socket(self): mockSock = MockSocket(bytearray(0), maxWrite=1, blockEveryOther=True) sock = TLSRecordLayer(mockSock) msg = Message(ContentType.handshake, bytearray(b'\x32' * 2)) gotRetry = False # XXX using private method! for result in sock._sendMsg(msg, False): if result in (0, 1): gotRetry = True else: break self.assertTrue(gotRetry) self.assertEqual( [ bytearray(b'\x16'), # handshake message bytearray(b'\x00'), bytearray(b'\x00'), # version (unset) bytearray(b'\x00'), bytearray(b'\x02'), # payload length bytearray(b'\x32'), bytearray(b'\x32') ], mockSock.sent)
def test_process_with_non_matching_alert(self): exp = ExpectSSL2Alert(SSL2ErrorDescription.bad_certificate) msg = Message(ContentType.handshake, bytearray([SSL2HandshakeType.error, 0x00, 0x01])) with self.assertRaises(AssertionError): exp.process(None, msg)
def test_is_match(self): exp = ExpectApplicationData() msg = Message(ContentType.application_data, bytearray(0)) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_handshake_type(self): exp = ExpectFinished() msg = Message(ContentType.handshake, bytearray([HandshakeType.client_hello])) self.assertFalse(exp.is_match(msg))
def test_process(self): exp = ExpectAlert() state = ConnectionState() msg = Message(ContentType.alert, bytearray(2)) exp.process(state, msg)
def test_is_match(self): exp = ExpectFinished() msg = Message(ContentType.handshake, bytearray([HandshakeType.finished])) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_content_type(self): exp = ExpectCertificateStatus() msg = Message(ContentType.application_data, bytearray([HandshakeType.certificate_status])) self.assertFalse(exp.is_match(msg))
def test_is_match(self): exp = ExpectServerHelloDone() msg = Message(ContentType.handshake, bytearray([HandshakeType.server_hello_done])) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_content_type(self): exp = ExpectServerHelloDone() msg = Message(ContentType.application_data, bytearray([HandshakeType.server_hello_done])) self.assertFalse(exp.is_match(msg))
def test_is_match(self): exp = ExpectCertificate() msg = Message(ContentType.handshake, bytearray([HandshakeType.certificate])) self.assertTrue(exp.is_match(msg))
def test_process(self): exp = ExpectApplicationData() state = ConnectionState() msg = Message(ContentType.application_data, bytearray(0)) exp.process(state, msg)
def test_is_match_with_empty_message(self): exp = ExpectHandshake(ContentType.handshake, HandshakeType.client_hello) ret = exp.is_match(Message(ContentType.handshake, bytearray(0))) self.assertFalse(ret)
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): exp.process(state, msg)
def test_is_match_with_values(self): exp = ExpectAlert(AlertLevel.warning, AlertDescription.unknown_psk_identity) msg = Message(ContentType.alert, bytearray(2)) self.assertTrue(exp.is_match(msg))
def test_process_with_values(self): exp = ExpectAlert(AlertLevel.warning, AlertDescription.unknown_psk_identity) state = ConnectionState() msg = Message(ContentType.alert, bytearray(b'\x01\x73')) exp.process(state, msg)
def test_process(self): exp = ExpectSSL2Alert(SSL2ErrorDescription.bad_certificate) msg = Message(ContentType.handshake, bytearray([SSL2HandshakeType.error, 0x00, 0x04])) exp.process(None, msg)
def test_is_match_with_unmatching_handshake_type(self): exp = ExpectCertificateRequest() state = ConnectionState() msg = Message(ContentType.application_data, bytearray([HandshakeType.certificate_request])) self.assertFalse(exp.is_match(msg))
def test_is_match(self): exp = ExpectCertificateRequest() state = ConnectionState() msg = Message(ContentType.handshake, bytearray([HandshakeType.certificate_request])) self.assertTrue(exp.is_match(msg))
def test_is_match(self): exp = ExpectServerKeyExchange() state = ConnectionState() msg = Message(ContentType.handshake, bytearray([HandshakeType.server_key_exchange])) self.assertTrue(exp.is_match(msg))
def test_process_with_values_and_not_matching_level(self): exp = ExpectAlert(AlertLevel.fatal, AlertDescription.unknown_psk_identity) state = ConnectionState() msg = Message(ContentType.alert, bytearray(b'\x01\x73')) with self.assertRaises(AssertionError): exp.process(state, msg)
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
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])
def test_process_with_non_matching_data(self): exp = ExpectApplicationData(bytearray(b"hello")) state = ConnectionState() msg = Message(ContentType.application_data, bytearray(b"bye")) self.assertTrue(exp.is_match(msg)) with self.assertRaises(AssertionError): exp.process(state, msg)
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)