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_flushBlocking(self): sock = MockSocket(bytearray()) msgSock = MessageSocket(sock, None) msgSock.flushBlocking() self.assertEqual(len(sock.sent), 0)
def test_recvMessage_with_unfragmentable_type(self): defragmenter = Defragmenter() defragmenter.addStaticSize(21, 2) sock = MockSocket(bytearray( b'\x17' + # message type b'\x03\x03' + # TLS version b'\x00\x06' + # payload length b'\x00\x04' + b'\xff'*4 )) msgSock = MessageSocket(sock, defragmenter) for res in msgSock.recvMessage(): if res in (0, 1): self.assertTrue(False, "Blocking read") else: break self.assertIsNotNone(res) header, parser = res self.assertEqual(header.type, 23) self.assertEqual(header.version, (3, 3)) self.assertEqual(header.length, 6) self.assertEqual(parser.bytes, bytearray(b'\x00\x04' + b'\xff'*4))
def test_recvMessage_with_blocking_socket(self): defragmenter = Defragmenter() defragmenter.addStaticSize(21, 2) sock = MockSocket(bytearray( b'\x15' + # message type b'\x03\x03' + # TLS version b'\x00\x02' + # payload length b'\xff\xff' # message ), blockEveryOther=True, maxRet=1) msgSock = MessageSocket(sock, defragmenter) gotBlocked = False for res in msgSock.recvMessage(): if res in (0, 1): gotBlocked = True else: break self.assertTrue(gotBlocked) self.assertIsNotNone(res) header, parser = res self.assertEqual(header.type, 21) self.assertEqual(header.version, (3, 3)) self.assertEqual(parser.bytes, bytearray(b'\xff\xff'))
def test_recvMessage(self): defragmenter = Defragmenter() defragmenter.addStaticSize(21, 2) sock = MockSocket(bytearray( b'\x15' + # message type b'\x03\x03' + # TLS version b'\x00\x04' + # payload length b'\xff\xff' + # first message b'\xbb\xbb' # second message )) msgSock = MessageSocket(sock, defragmenter) for res in msgSock.recvMessage(): if res in (0, 1): self.assertTrue(False, "Blocking read") else: break self.assertIsNotNone(res) header, parser = res self.assertEqual(header.type, 21) self.assertEqual(header.version, (3, 3)) self.assertEqual(header.length, 0) self.assertEqual(parser.bytes, bytearray(b'\xff\xff')) res = None for res in msgSock.recvMessage(): if res in (0, 1): self.assertTrue(False, "Blocking read") else: break self.assertIsNotNone(res) header, parser = res self.assertEqual(header.type, 21) self.assertEqual(header.version, (3, 3)) self.assertEqual(header.length, 0) self.assertEqual(parser.bytes, bytearray(b'\xbb\xbb'))
def test_flush(self): sock = MockSocket(bytearray()) msgSock = MessageSocket(sock, None) for res in msgSock.flush(): if res in (0, 1): self.assertTrue(False, "Blocking flush") else: break self.assertEqual(len(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), 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])
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'))
def process(self, state): """Connect to a server""" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect((self.hostname, self.port)) defragmenter = Defragmenter() defragmenter.addStaticSize(ContentType.alert, 2) defragmenter.addStaticSize(ContentType.change_cipher_spec, 1) defragmenter.addDynamicSize(ContentType.handshake, 1, 3) state.msg_sock = MessageSocket(sock, defragmenter) state.msg_sock.version = self.version
def test_recvMessageBlocking(self): defragmenter = Defragmenter() defragmenter.addStaticSize(21, 2) sock = MockSocket(bytearray( b'\x15' + # message type b'\x03\x03' + # TLS version b'\x00\x02' + # payload length b'\xff\xff' # message ), blockEveryOther=True, maxRet=1) msgSock = MessageSocket(sock, defragmenter) res = msgSock.recvMessageBlocking() self.assertIsNotNone(res) header, parser = res self.assertEqual(header.type, 21) self.assertEqual(parser.bytes, bytearray(b'\xff\xff'))
def process(self, state): """Connect to a server.""" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect((self.hostname, self.port)) # disable Nagle - we handle buffering and flushing ourselves sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # allow for later buffering of writes to the socket sock = BufferedSocket(sock) defragmenter = Defragmenter() defragmenter.addStaticSize(ContentType.alert, 2) defragmenter.addStaticSize(ContentType.change_cipher_spec, 1) defragmenter.addDynamicSize(ContentType.handshake, 1, 3) state.msg_sock = MessageSocket(sock, defragmenter) state.msg_sock.version = self.version
def test_flushBlocking_with_data(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) msgSock.flushBlocking() 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])
def test_flushBlocking_with_data(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) msgSock.flushBlocking() self.assertEqual(len(sock.sent), 1) self.assertEqual(bytearray( b'\x16' + b'\x03\x03' + b'\x00\x03' + b'\xaa'*3), sock.sent[0])
def scan(self): """Perform a scan on server.""" defragger = Defragmenter() defragger.addStaticSize(ContentType.change_cipher_spec, 1) defragger.addStaticSize(ContentType.alert, 2) defragger.addDynamicSize(ContentType.handshake, 1, 3) try: raw_sock = socket.create_connection((self.host, self.port), 5) except socket.error as e: return [e] sock = MessageSocket(raw_sock, defragger) if self.hostname is not None: client_hello = self.hello_gen(bytearray(self.hostname, 'utf-8')) else: client_hello = self.hello_gen(None) # record layer version - TLSv1.x # use the version from configuration, if present, or default to the # RFC recommended (3, 1) for TLS and (3, 0) for SSLv3 if hasattr(client_hello, 'record_version'): sock.version = client_hello.record_version elif hasattr(self.hello_gen, 'record_version'): sock.version = self.hello_gen.record_version elif client_hello.client_version > (3, 1): # TLS1.0 sock.version = (3, 1) else: sock.version = client_hello.client_version # we don't want to send invalid messages (SSLv2 hello in SSL record # layer), so set the record layer version to SSLv2 if the hello is # of SSLv2 format if client_hello.ssl2: sock.version = (0, 2) # save the record version used in the end for later analysis client_hello.record_version = sock.version messages = [client_hello] handshake_parser = HandshakeParser() try: sock.sendMessageBlocking(client_hello) except socket.error as e: messages.append(e) return messages except TLSAbruptCloseError as e: sock.sock.close() messages.append(e) return messages # get all the server messages that affect connection, abort as soon # as they've been read try: while True: header, parser = sock.recvMessageBlocking() if header.type == ContentType.alert: alert = Alert() alert.parse(parser) alert.record_version = header.version messages += [alert] elif header.type == ContentType.handshake: msg = handshake_parser.parse(parser) msg.record_version = header.version messages += [msg] if isinstance(msg, ServerHelloDone): return messages else: raise TypeError("Unknown content type: {0}" .format(header.type)) except (TLSAbruptCloseError, TLSIllegalParameterException, ValueError, TypeError, socket.error, SyntaxError) as e: messages += [e] return messages finally: try: sock.sock.close() except (socket.error, OSError): pass
def test___init__(self): msgSock = MessageSocket(None, None) self.assertIsNotNone(msgSock)
def scan(self): """Perform a scan on server.""" defragger = Defragmenter() defragger.addStaticSize(ContentType.change_cipher_spec, 1) defragger.addStaticSize(ContentType.alert, 2) defragger.addDynamicSize(ContentType.handshake, 1, 3) try: raw_sock = socket.create_connection((self.host, self.port), 5) except socket.error as e: return [e] sock = MessageSocket(raw_sock, defragger) if self.hostname is not None: client_hello = self.hello_gen(bytearray(self.hostname, 'utf-8')) else: client_hello = self.hello_gen(None) # record layer version - TLSv1.x # use the version from configuration, if present, or default to the # RFC recommended (3, 1) for TLS and (3, 0) for SSLv3 if hasattr(client_hello, 'record_version'): sock.version = client_hello.record_version elif hasattr(self.hello_gen, 'record_version'): sock.version = self.hello_gen.record_version elif client_hello.client_version > (3, 1): # TLS1.0 sock.version = (3, 1) else: sock.version = client_hello.client_version # we don't want to send invalid messages (SSLv2 hello in SSL record # layer), so set the record layer version to SSLv2 if the hello is # of SSLv2 format if client_hello.ssl2: sock.version = (0, 2) # save the record version used in the end for later analysis client_hello.record_version = sock.version messages = [client_hello] handshake_parser = HandshakeParser() try: sock.sendMessageBlocking(client_hello) except socket.error as e: messages.append(e) return messages except TLSAbruptCloseError as e: sock.sock.close() messages.append(e) return messages # get all the server messages that affect connection, abort as soon # as they've been read try: while True: header, parser = sock.recvMessageBlocking() if header.type == ContentType.alert: alert = Alert() alert.parse(parser) alert.record_version = header.version messages += [alert] elif header.type == ContentType.handshake: msg = handshake_parser.parse(parser) msg.record_version = header.version messages += [msg] if isinstance(msg, ServerHelloDone): return messages else: raise TypeError("Unknown content type: {0}".format( header.type)) except (TLSAbruptCloseError, TLSIllegalParameterException, ValueError, TypeError, socket.error, SyntaxError) as e: messages += [e] return messages finally: try: sock.sock.close() except (socket.error, OSError): pass