#!/usr/bin/env python # Impacket - Collection of Python classes for working with network protocols. # # Copyright Fortra, LLC and its affiliated companies # # All rights reserved. # # This software is provided under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # import struct import socket import unittest from unittest import mock from impacket import tds from impacket.examples.ntlmrelayx.servers.socksplugins.mssql import MSSQLSocksRelay class TDSTests(unittest.TestCase): @staticmethod def _build_tds_packet(packet_type, data, status=tds.TDS_STATUS_EOM): packet = tds.TDSPacket() packet["Type"] = packet_type packet["Status"] = status packet["Data"] = data return packet.getData() def test_prelogin_packs_four_byte_threadid(self): token = tds.TDS_PRELOGIN() token["Version"] = b"\x0f\x00\x11\x3a\x00\x00" token["Encryption"] = tds.TDS_ENCRYPT_NOT_SUP token["Instance"] = b"\x00" token["ThreadID"] = struct.pack("H", data, 18)[0], 4) self.assertEqual(data[-4:], struct.pack("L", data, 4)[0], tds.TDS_LOGIN7_VERSION_71 ) def test_negotiate_encryption_does_not_retry_tds8_on_timeout(self): client = tds.MSSQL("server") client.preLogin = mock.Mock(side_effect=socket.timeout("timed out")) client.disconnect = mock.Mock() client.connect = mock.Mock() client._setup_tds8 = mock.Mock() client.set_tls_context = mock.Mock() with self.assertRaises(socket.timeout): client._negotiate_encryption() client.disconnect.assert_not_called() client.connect.assert_not_called() client._setup_tds8.assert_not_called() client.set_tls_context.assert_not_called() def test_negotiate_encryption_retries_tds8_on_connection_close(self): client = tds.MSSQL("server") response = {"Encryption": tds.TDS_ENCRYPT_OFF} client.preLogin = mock.Mock( side_effect=[ConnectionError("Server closed connection"), response] ) client.disconnect = mock.Mock() client.connect = mock.Mock() client._setup_tds8 = mock.Mock() client.set_tls_context = mock.Mock() result = client._negotiate_encryption() self.assertIs(result, response) client.disconnect.assert_called_once_with() client.connect.assert_called_once_with() client._setup_tds8.assert_called_once_with() client.set_tls_context.assert_not_called() def test_wrap_sql_batch_data_adds_headers_for_tds8_sessions(self): client = tds.MSSQL("server") client.tds8 = True sql_text = "SELECT 1\r\n".encode("utf-16le") data = client._wrap_sql_batch_data(sql_text) self.assertEqual(data[:4], struct.pack("