def test_get_connections_by_procstat(self, call_mock): """ Checks the get_connections function with the procstat resolver. """ call_mock.return_value = BSD_PROCSTAT_OUTPUT.split('\n') expected = [ Connection('10.0.0.2', 9050, '10.0.0.1', 22370, 'tcp', False), Connection('10.0.0.2', 9050, '10.0.0.1', 44381, 'tcp', False), Connection('10.0.0.2', 33734, '38.229.79.2', 443, 'tcp', False), Connection('10.0.0.2', 47704, '68.169.35.102', 9001, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.BSD_PROCSTAT, process_pid=3561, process_name='tor')) self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_PROCSTAT, process_pid=3561, process_name='stuff') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_PROCSTAT, process_pid=1111, process_name='tor') call_mock.side_effect = OSError('Unable to call procstat') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_PROCSTAT, process_pid=1111)
def test_connections_ipv6(self, open_mock, readlink_mock, path_exists_mock, listdir_mock): """ Tests the connections function with ipv6 addresses. """ pid = 1111 listdir_mock.side_effect = lambda param: { '/proc/%s/fd' % pid: ['1', '2'], }[param] readlink_mock.side_effect = lambda param: { '/proc/%s/fd/1' % pid: 'socket:[42088802]', '/proc/%s/fd/2' % pid: 'socket:[41691357]', }[param] path_exists_mock.side_effect = lambda param: { '/proc/net/tcp6': True, '/proc/net/udp6': False }[param] open_mock.side_effect = lambda param, mode: { '/proc/net/tcp': io.BytesIO(b''), '/proc/net/tcp6': io.BytesIO(TCP6_CONTENT), '/proc/net/udp': io.BytesIO(b''), }[param] expected_results = [ Connection('2a01:04f8:0190:514a:0000:0000:0000:0002', 443, '2001:0638:a000:4140:0000:0000:ffff:0189', 40435, 'tcp', True), Connection('2a01:04f8:0190:514a:0000:0000:0000:0002', 443, '2001:0858:0002:0002:aabb:0000:563b:1526', 44469, 'tcp', True), ] self.assertEqual(expected_results, proc.connections(pid = pid))
def test_connections_ipv6_by_user(self, open_mock, getpwnam_mock, path_exists_mock): """ Tests the connections function with ipv6 addresses. """ getpwnam_mock('me').pw_uid = 106 path_exists_mock.side_effect = lambda param: { '/proc/net/tcp6': True, '/proc/net/udp6': False }[param] open_mock.side_effect = lambda param, mode: { '/proc/net/tcp': io.BytesIO(TITLE_LINE), '/proc/net/tcp6': io.BytesIO(TCP6_CONTENT), '/proc/net/udp': io.BytesIO(TITLE_LINE), }[param] expected = [ Connection('0000:0000:0000:0000:0000:ffff:0509:9e4b', 5222, '0000:0000:0000:0000:0000:ffff:4e36:8621', 38330, 'tcp', True), Connection('2a01:04f8:0190:514a:0000:0000:0000:0002', 5269, '2001:06f8:126f:0011:0000:0000:0000:0026', 50594, 'tcp', True), Connection('0000:0000:0000:0000:0000:ffff:0509:9e4b', 5222, '0000:0000:0000:0000:0000:ffff:4e36:8621', 38174, 'tcp', True), ] self.assertEqual(expected, proc.connections(user='******'))
def test_get_connections_by_fstat(self, call_mock): """ Checks the get_connections function with the fstat resolver. """ call_mock.return_value = BSD_FSTAT_OUTPUT.split('\n') expected = [ Connection('127.0.0.1', 8443, '1.2.3.4', 54581, 'tcp', False), Connection('192.168.1.100', 36174, '4.3.2.1', 443, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.BSD_FSTAT, process_pid=15843, process_name='tor')) self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_FSTAT, process_pid=15843, process_name='stuff') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_FSTAT, process_pid=1111, process_name='tor') call_mock.side_effect = OSError('Unable to call fstat') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_FSTAT, process_pid=1111)
def test_get_connections_by_sockstat(self, call_mock): """ Checks the get_connections function with the sockstat resolver. """ call_mock.return_value = SOCKSTAT_OUTPUT.split('\n') expected = [ Connection('192.168.0.1', 44415, '38.229.79.2', 443, 'tcp', False), Connection('192.168.0.1', 44092, '68.169.35.102', 443, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.SOCKSTAT, process_pid=15843, process_name='tor')) self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.SOCKSTAT, process_pid=15843, process_name='stuff') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.SOCKSTAT, process_pid=1111, process_name='tor') call_mock.side_effect = OSError('Unable to call sockstat') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.SOCKSTAT, process_pid=1111)
def test_get_connections_by_ss_ipv6(self): """ Checks the get_connections function with the ss resolver results on IPv6 conections. This also checks with the output from a hardened Gentoo system which has subtle differences... https://trac.torproject.org/projects/tor/ticket/18079 """ expected = [ Connection('5.9.158.75', 443, '107.170.93.13', 56159, 'tcp', False), Connection('5.9.158.75', 443, '159.203.97.91', 37802, 'tcp', False), Connection('2a01:4f8:190:514a::2', 443, '2001:638:a000:4140::ffff:189', 38556, 'tcp', True), Connection('2a01:4f8:190:514a::2', 443, '2001:858:2:2:aabb:0:563b:1526', 51428, 'tcp', True), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.SS, process_pid=25056, process_name='tor')) self.assertEqual( 2, len( stem.util.connection.get_connections(Resolver.SS, process_name='beam')))
def test_get_connections_by_proc(self, proc_mock): """ Checks the get_connections function with the proc resolver. """ proc_mock.return_value = [ ('17.17.17.17', 4369, '34.34.34.34', 8738, 'tcp', False), ('187.187.187.187', 48059, '204.204.204.204', 52428, 'tcp', False), ] expected = [ Connection('17.17.17.17', 4369, '34.34.34.34', 8738, 'tcp', False), Connection('187.187.187.187', 48059, '204.204.204.204', 52428, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.PROC, process_pid=1111)) proc_mock.side_effect = IOError('No connections for you!') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.PROC, process_pid=1111)
def test_utilities(self, stdout_mock, get_connections_mock): get_connections_mock.return_value = [ Connection('17.17.17.17', 4369, '34.34.34.34', 8738, 'tcp', False), Connection('18.18.18.18', 443, '35.35.35.35', 4281, 'tcp', False), ] import utilities self.assertEqual(EXPECTED_UTILITIES, stdout_mock.getvalue())
def test_get_connections_by_netstat_ipv6(self): """ Checks the get_connections function with the netstat resolver for IPv6. """ expected = [ Connection('2a01:4f8:190:514a::2', 443, '2001:638:a000:4140::ffff:189', 41046, 'tcp', True), Connection('2a01:4f8:190:514a::2', 443, '2001:858:2:2:aabb:0:563b:1526', 38260, 'tcp', True), ] self.assertEqual(expected, stem.util.connection.get_connections(Resolver.NETSTAT, process_pid = 1904, process_name = 'tor'))
def test_get_connections_by_lsof_osx(self): """ Checks the get_connections function with the lsof resolver on OSX. This only includes entries for the tor process. """ expected = [ Connection('192.168.1.20', 9090, '38.229.79.2', 14010, 'tcp', False), Connection('192.168.1.20', 9090, '68.169.35.102', 14815, 'tcp', False), Connection('192.168.1.20', 9090, '62.135.16.134', 14456, 'tcp', False), ] self.assertEqual(expected, stem.util.connection.get_connections(Resolver.LSOF, process_pid = 129, process_name = 'tor'))
def test_relay_connections(self, connect_mock, get_connections_mock): import relay_connections with patch('sys.stdout', new_callable=io.StringIO) as stdout_mock: connect_mock.return_value = None relay_connections.main(['--help']) self.assertEqual(EXPECTED_RELAY_CONNECTIONS_HELP, stdout_mock.getvalue()) with patch('sys.stdout', new_callable=io.StringIO) as stdout_mock: consensus_desc = RouterStatusEntryV2.create({ 'r': 'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0', 's': 'Fast Stable', }) controller = Mock() controller.get_pid.return_value = 123 controller.get_version.return_value = stem.version.Version( '1.2.3.4') controller.get_exit_policy.return_value = ExitPolicy('reject *:*') controller.get_network_status.return_value = consensus_desc controller.get_network_statuses.return_value = [consensus_desc] controller.get_ports.side_effect = lambda port_type, default_val: { Listener.OR: [4369], Listener.DIR: [443], Listener.CONTROL: [9100], }.get(port_type, default_val) connect_mock.return_value = controller get_connections_mock.return_value = [ Connection('17.17.17.17', 4369, '34.34.34.34', 8738, 'tcp', False), Connection('18.18.18.18', 443, '35.35.35.35', 4281, 'tcp', False), Connection('19.19.19.19', 443, '36.36.36.36', 2814, 'tcp', False), Connection('20.20.20.20', 9100, '37.37.37.37', 2814, 'tcp', False), Connection('21.21.21.21', 80, '38.38.38.38', 8142, 'tcp', False), ] relay_connections.main([]) self.assertEqual(EXPECTED_RELAY_CONNECTIONS, stdout_mock.getvalue())
def test_get_connections_by_lsof_ipv6(self): """ Checks the get_connections function with the lsof resolver for IPv6. """ expected = [Connection('2a01:4f8:190:514a::2', 443, '2001:858:2:2:aabb:0:563b:1526', 44811, 'tcp', True)] self.assertEqual(expected, stem.util.connection.get_connections(Resolver.LSOF, process_pid = 1904, process_name = 'tor'))
def test_get_connections_by_ss_with_whitespace(self): """ On some platforms the 'ss' command pads its lines with trailing whitespace. """ expected = [ Connection('192.168.0.1', 44092, '23.112.135.72', 443, 'tcp', False), Connection('192.168.0.1', 44415, '38.229.79.2', 443, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.SS, process_pid=15843, process_name='tor'))
def test_get_connections_by_windows_netstat(self, call_mock): """ Checks the get_connections function with the Windows netstat resolver. """ call_mock.return_value = NETSTAT_WINDOWS_OUTPUT.split('\n') expected = [ Connection('192.168.0.1', 44284, '38.229.79.2', 443, 'tcp', False) ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.NETSTAT_WINDOWS, process_pid=15843, process_name='tor')) self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.NETSTAT_WINDOWS, process_pid=1111, process_name='tor') call_mock.side_effect = OSError('Unable to call netstat') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.NETSTAT_WINDOWS, process_pid=1111)
def test_get_connections_by_sockstat_for_bsd(self, call_mock): """ Checks the get_connections function with the bsd variant of the sockstat resolver. """ call_mock.return_value = BSD_SOCKSTAT_OUTPUT.split('\n') expected = [ Connection('172.27.72.202', 54011, '38.229.79.2', 9001, 'tcp', False), Connection('172.27.72.202', 59374, '68.169.35.102', 9001, 'tcp', False), Connection('172.27.72.202', 59673, '213.24.100.160', 9001, 'tcp', False), Connection('172.27.72.202', 51946, '32.188.221.72', 443, 'tcp', False), Connection('172.27.72.202', 60344, '21.89.91.78', 9001, 'tcp', False), ] self.assertEqual( expected, stem.util.connection.get_connections(Resolver.BSD_SOCKSTAT, process_pid=4397, process_name='tor')) self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_SOCKSTAT, process_pid=4397, process_name='stuff') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_SOCKSTAT, process_pid=1111, process_name='tor') call_mock.side_effect = OSError('Unable to call sockstat') self.assertRaises(IOError, stem.util.connection.get_connections, Resolver.BSD_SOCKSTAT, process_pid=1111)
def test_connections(self, open_mock, readlink_mock, path_exists_mock, listdir_mock): """ Tests the connections function. """ pid = 1111 listdir_mock.side_effect = lambda param: { '/proc/%s/fd' % pid: ['1', '2', '3', '4'], }[param] readlink_mock.side_effect = lambda param: { '/proc/%s/fd/1' % pid: 'socket:[99999999]', '/proc/%s/fd/2' % pid: 'socket:[IIIIIIII]', '/proc/%s/fd/3' % pid: 'pipe:[30303]', '/proc/%s/fd/4' % pid: 'pipe:[40404]', }[param] tcp = TITLE_LINE + b'\n 0: 11111111:1111 22222222:2222 01 44444444:44444444 55:55555555 66666666 1111 8 99999999' udp = TITLE_LINE + b'\n A: BBBBBBBB:BBBB CCCCCCCC:CCCC DD EEEEEEEE:EEEEEEEE FF:FFFFFFFF GGGGGGGG 1111 H IIIIIIII' path_exists_mock.side_effect = lambda param: { '/proc/net/tcp': True, '/proc/net/tcp6': False, '/proc/net/udp': True, '/proc/net/udp6': False }[param] open_mock.side_effect = lambda param, mode: { '/proc/net/tcp': io.BytesIO(tcp), '/proc/net/udp': io.BytesIO(udp) }[param] expected_results = [ Connection('17.17.17.17', 4369, '34.34.34.34', 8738, 'tcp', False), Connection('187.187.187.187', 48059, '204.204.204.204', 52428, 'udp', False), ] self.assertEqual(expected_results, proc.connections(pid))
def test_high_connection_count(self, open_mock, readlink_mock, path_exists_mock, listdir_mock): """ When we have over ten thousand connections the 'SL' column's width changes. Checking that we account for this. """ pid = 1111 listdir_mock.side_effect = lambda param: { '/proc/%s/fd' % pid: ['1', '2', '3', '4'], }[param] readlink_mock.side_effect = lambda param: { '/proc/%s/fd/1' % pid: 'socket:[99999999]', '/proc/%s/fd/2' % pid: 'socket:[88888888]', '/proc/%s/fd/3' % pid: 'socket:[77777777]', '/proc/%s/fd/4' % pid: 'pipe:[30303]', '/proc/%s/fd/5' % pid: 'pipe:[40404]', }[param] path_exists_mock.side_effect = lambda param: { '/proc/net/tcp6': False, '/proc/net/udp6': False }[param] open_mock.side_effect = lambda param, mode: { '/proc/net/tcp': io.BytesIO(SL_WIDTH_CHANGE), '/proc/net/udp': io.BytesIO(TITLE_LINE) }[param] expected = [ Connection('17.17.17.17', 4369, '51.34.34.34', 8772, 'tcp', False), Connection('34.34.34.34', 8738, '68.51.51.51', 13141, 'tcp', False), Connection('51.51.51.51', 13107, '85.68.68.68', 17510, 'tcp', False), ] self.assertEqual(expected, proc.connections(pid))