def punch_hole_in_firewall(ips): if current_os() == 'macos': pf = PFCtl() ip_list = '{ ' + ', '.join(ips) + ' }' pf.set_rules([ "pass in quick from {} no state".format(ip_list), "pass out quick to {} no state".format(ip_list) ]) elif current_os() == 'windows': L.warning( "Ignoring option to open up firewall for {} on Windows".format( ', '.join(ips))) else: raise XVEx('Editing the firewall is only supported for PF/macOS')
def discover_device(self, discovery_keys): if 'device_id' not in discovery_keys or discovery_keys['device_id'] != 'localhost': return None if len(discovery_keys) != 1: L.warning( "Only the 'device_id' discovery key is valid for discovering localhost. The others " "will be ignored: {}".format(discovery_keys)) if current_os() == 'windows': connector = WindowsLocalShellConnector() else: connector = LocalShellConnector() return create_device(current_os(), self._localhost_config, connector)
def test_current_os(self): for plat in ['linux', 'linux2']: with mock.patch.object(sys, 'platform', plat): self.assertEqual(current_os(), 'linux') with mock.patch.object(sys, 'platform', 'darwin'): self.assertEqual(current_os(), 'macos') for plat in ['win32', 'cygwin']: with mock.patch.object(sys, 'platform', plat): self.assertEqual(current_os(), 'windows') with mock.patch.object(sys, 'platform', 'unknown'): with self.assertRaises(Exception): current_os()
def _create_route_to_ip(self, ip): default_gateway = netifaces.gateways()['default'][netifaces.AF_INET][0] L.debug("Adding route to ip: {} -> {}".format(ip, default_gateway)) if current_os() == 'windows': raise XVEx("TODO: Implement route on windows") else: route = [ip, default_gateway] subprocess.check_output(['route', 'add'] + route) self._routes_to_remote.append(route)
def detect(self): if current_os() != "macos": return None L.debug("Trying to determine if we're using a macOS network extension") vpn_info = VPNInfo() if not self._ne_processes(): L.debug('Not using a network extension') return None L.info("Detected a VPN network extension (unknown protocol)") vpn_info.vpn_processes = self._ne_processes() return vpn_info
def main(argv=None): if argv is None: argv = sys.argv[1:] # Some of these command line args are also specified in the context. This is just for # convenience as certain of the arguments are changed often enough to warrant specifying them # on the command line. parser = argparse.ArgumentParser( description= 'Run a set of tests locally on the current machine. The exit code of this ' '"command will be the number of tests which failed or, if an unexpected error occured, -1.' ) parser.add_argument( '-o', '--output-root', help='Root folder where all output for this test run will be ' 'written. Defaults to a system temp directory for the current user.') parser.add_argument( '-c', '--test-configs', default=[], nargs='+', help='Either: a python file with a module ' 'level list attribute TESTS is list of tests; a json file whose top level element is an ' 'array of tests; or a json string parsable to a list of tests.') parser.add_argument( '-d', '--test-devices', default=[], nargs='+', help='Either: a python file with a module ' 'level list attribute DEVICES is list of devices; a json file whose top level element is ' 'an array of devices; or a json string parsable to a list of tests.') parser.add_argument( '-r', '--run-directory', default=None, help='A unique subdirectory of the output_root ' 'where results for this specific run will go. If not specified then a unique one will be ' "generated based on the run timestamp. The directory will be created if it doesn't exist" ) parser.add_argument( '-m', '--allow-manual', default=None, action='store_true', help= 'Allow manual tests. If this is not specified then any test which requires manual ' 'interaction will fail') parser.add_argument( '-s', '--stop-on-fail', default=None, action='store_true', help= 'If specified, the test run will stop as soon as the first test fails.' ) parser.add_argument('-t', '--test-regex', default=None, help='If specified, only run tests whose test class ' 'name matches the passed regex.') parser.add_argument('-x', '--context', default='default_context.py', help='If specified, only run tests whose ' 'test class name matches the passed regex.') parser.add_argument('-l', '--log-level', default=None, help='Log level. Valid values ["ERROR", "WARNING", ' '"INFO", "DEBUG", "VERBOSE"].') parser.add_argument('-2', '--v2', default=False, action='store_true', help='DEPRECATED: Does nothing') args = parser.parse_args(argv) args.log_level = args.log_level.upper() if args.log_level else None # We'll reconfigure in a second but lets get logging going asap! inital_log_level = args.log_level if args.log_level else "INFO" TestRunner.configure_logger(level=inital_log_level) if args.output_root is None: if current_os() == "windows": args.output_root = tempfile.mkdtemp() else: # Don't make the folder as root else we'll get perms issues. This also ensures we use # the user's temp directory not root's temp directory. args.output_root = subprocess.check_output( ['sudo', '-u', tools_user()[1], 'mktemp', '-d']).decode().strip() L.warning("You didn't specify an output folder. Using: {}".format( args.output_root)) args.output_root = windows_safe_path(args.output_root) if not os.path.exists(args.output_root): makedirs_safe(args.output_root) if args.run_directory is None: args.run_directory = "Run_{}".format(time.time()) # Just add output_directory to the args object as it makes life simpler. args.output_directory = os.path.join(args.output_root, args.run_directory) makedirs_safe(args.output_directory) context_dict = import_by_filename(args.context).CONTEXT cmd_line_overrides = [ 'run_directory', 'output_directory', 'allow_manual', 'stop_on_fail', 'log_level', ] for override in cmd_line_overrides: value = getattr(args, override) if value is not None: context_dict[override] = value # Log level might need updating based on config TestRunner.configure_logger(args.output_directory, level=getattr(L, context_dict['log_level'])) test_configs = [] for test_config_file in args.test_configs: test_configs += object_from_command_line(test_config_file, 'TESTS') test_devices = [] for test_device_file in args.test_devices: test_devices += object_from_command_line(test_device_file, 'DEVICES') if args.test_regex: test_configs = filter_tests(test_configs, args.test_regex) # This call shouldn't throw. If it does then we need to tweak the TestRunner. if args.v2: L.warning( "Argument -2 is DEPRECATED and will be ignored. Test runner v2 is the default now" ) return TestRunner(TestRunContext(context_dict), test_devices, test_configs).run()
def bin_path(): if current_os() == 'macos': return '/usr/local/bin/' return '/usr/bin/'
def getch(): if current_os() == 'windows' and is_dos(): import msvcrt # pylint: disable=import-error return msvcrt.getch() return _getch_unix()
"device_name": "localhost", 'components': { 'vpn_application': { 'name': 'generic', } }, }], 'parameters': { 'browser': Replacee('$BROWSER'), 'ask_perms': True, } } # Run the tests on all major browsers for the current OS. BROWSERS = ['chrome', 'opera', 'firefox'] if current_os() == 'macos': BROWSERS.append('safari') elif current_os() == 'windows': BROWSERS.append('edge') # Duplicate the test templates for each browser TESTS += TemplateEvaluator.generate([{ 'TEMPLATE': TEMPLATE_VANILLA, '$BROWSER': Each(BROWSERS) }]) TESTS += TemplateEvaluator.generate([{ 'TEMPLATE': TEMPLATE_PERMISSIONS_GRANTED, '$BROWSER': Each(BROWSERS) }])
from xv_leak_tools.helpers import current_os from xv_leak_tools.test_templating.templating import TemplateEvaluator, Replacee, Each # TODO: Add variants of the test which explicitly require local and public DNS servers. # TODO: Ensure the tests check for number of adapters (they will fail, but checking is nicer) # Note that packet capture tests are inherently noisy at the moment. Very few (if any) VPN providers # guarantee no non-tunnel traffic so false positives are almost guaranteed. The tests are still # useful for investigatory purposes. # This list will contain all the individual test configurations TESTS = [] if current_os() == "macos": TEST_NAMES = [ "TestMacOSDNSDisruptEnableNewService", "TestMacOSDNSDisruptInterface", "TestMacOSDNSDisruptService", "TestMacOSDNSDisruptWifiPower", "TestMacOSIPResponderDisruptEnableNewService", "TestMacOSIPResponderDisruptInterface", "TestMacOSIPResponderDisruptService", "TestMacOSIPResponderDisruptWifiPower", "TestMacOSPacketCaptureDisruptEnableNewService", "TestMacOSPacketCaptureDisruptInterface", "TestMacOSPacketCaptureDisruptService", "TestMacOSPacketCaptureDisruptWifiPower", ] elif current_os() == "windows": TEST_NAMES = [ "TestWindowsDNSDisruptEnableNewAdapter",
def _vmrun_path(): if current_os() == 'macos': return '/Applications/VMware Fusion.app/Contents/Library/vmrun' raise XVEx("TODO: Implement VMWare support for OS '{}'".format(current_os()))