def _run(self, cmd): """ Run an email firewall command with bitmask-root Might raise: NoPkexecAvailable, NoPolkitAuthAgentAvailable, :param cmd: command to send to bitmask-root fw-email :type cmd: [str] :returns: exit code of bitmask-root :rtype: int """ command = [] policyChecker = LinuxPolicyChecker() pkexec = policyChecker.maybe_pkexec() if pkexec: command.append(first(pkexec)) command.append(force_eval(self.BITMASK_ROOT)) command.append("fw-email") command += cmd # XXX: will be nice to use twisted ProcessProtocol instead of # subprocess to avoid blocking until it finish return subprocess.call(command)
def cmd_for_missing_scripts(kls, frompath): """ Returns a sh script that can copy the missing files. :param frompath: The path where the helper files live :type frompath: str :rtype: str """ bin_paths = force_eval( (LinuxVPNLauncher.POLKIT_PATH, LinuxVPNLauncher.OPENVPN_BIN_PATH, LinuxVPNLauncher.BITMASK_ROOT) ) polkit_path, openvpn_bin_path, bitmask_root = bin_paths # no system config for now # sys_config = kls.SYSTEM_CONFIG (polkit_file, openvpn_bin_file, bitmask_root_file) = map(lambda p: os.path.split(p)[-1], bin_paths) cmd = "#!/bin/sh\n" cmd += "mkdir -p /usr/local/sbin\n" cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, polkit_file), polkit_path) cmd += 'chmod 644 "%s"\n' % (polkit_path,) cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, bitmask_root_file), bitmask_root) cmd += 'chmod 744 "%s"\n' % (bitmask_root,) if flags.STANDALONE: cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, openvpn_bin_file), openvpn_bin_path) cmd += 'chmod 744 "%s"\n' % (openvpn_bin_path,) return cmd
def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. """ BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "firewall", "stop"]) return True if exitCode is 0 else False
def is_fw_down(self): """ Return whether the firewall is down or not. :rtype: bool """ BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 return fw_is_down()
def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. """ if IS_MAC: # We don't support Mac so far return True BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "firewall", "stop"]) return True if exitCode is 0 else False
def bitmask_root_vpn_down(self): """ Bring openvpn down using the privileged wrapper. """ if IS_MAC: # We don't support Mac so far return True BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "openvpn", "stop"]) return True if exitCode is 0 else False
def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port="unix", openvpn_verb=1): """ Returns the Linux implementation for the vpn launching command. Might raise: EIPNoPkexecAvailable, EIPNoPolkitAuthAgentAvailable, OpenVPNNotFoundException, VPNLauncherException. :param eipconfig: eip configuration object :type eipconfig: EIPConfig :param providerconfig: provider specific configuration :type providerconfig: ProviderConfig :param socket_host: either socket path (unix) or socket IP :type socket_host: str :param socket_port: either string "unix" if it's a unix socket, or port otherwise :type socket_port: str :param openvpn_verb: the openvpn verbosity wanted :type openvpn_verb: int :return: A VPN command ready to be launched. :rtype: list """ # we use `super` in order to send the class to use command = super(LinuxVPNLauncher, kls).get_vpn_command(eipconfig, providerconfig, socket_host, socket_port, openvpn_verb) command.insert(0, force_eval(kls.BITMASK_ROOT)) command.insert(1, "openvpn") command.insert(2, "start") policyChecker = LinuxPolicyChecker() try: pkexec = policyChecker.maybe_pkexec() except NoPolkitAuthAgentAvailable: raise EIPNoPolkitAuthAgentAvailable() except NoPkexecAvailable: raise EIPNoPkexecAvailable() if pkexec: command.insert(0, first(pkexec)) return command
def bitmask_root_vpn_down(self): """ Bring openvpn down using the privileged wrapper. """ if IS_MAC: cmd = 'openvpn_stop' helper = darwinvpnlauncher.DarwinHelperCommand() result = helper.send(cmd) return True if IS_LINUX: BM_ROOT = force_eval( linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "openvpn", "stop"]) return True if exitCode is 0 else False
def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. """ if IS_MAC: cmd = 'firewall_stop' helper = darwinvpnlauncher.DarwinHelperCommand() result = helper.send(cmd) return True if IS_LINUX: BM_ROOT = force_eval( linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "firewall", "stop"]) return True if exitCode is 0 else False
def _can_start(self, domain): """ Returns True if it has everything that is needed to run EIP, False otherwise :param domain: the domain for the provider to check :type domain: str """ if IS_LINUX and not LinuxPolicyChecker.is_up(): logger.error("No polkit agent running.") return False provider_config = ProviderConfig.get_provider_config(domain) if EIP_SERVICE not in provider_config.get_services(): return False eip_config = eipconfig.EIPConfig() api_version = provider_config.get_api_version() eip_config.set_api_version(api_version) eip_loaded = eip_config.load(eipconfig.get_eipconfig_path(domain)) launcher = get_vpn_launcher() ovpn_path = force_eval(launcher.OPENVPN_BIN_PATH) if not os.path.isfile(ovpn_path): logger.error("Cannot start OpenVPN, binary not found: %s" % (ovpn_path,)) return False # check for other problems if not eip_loaded or provider_config is None: logger.error("Cannot load provider and eip config, cannot " "autostart") return False client_cert_path = eip_config.\ get_client_cert_path(provider_config, about_to_download=True) if leap_certs.should_redownload(client_cert_path): logger.error("The client should redownload the certificate," " cannot autostart") return False if not os.path.isfile(client_cert_path): logger.error("Can't find the certificate, cannot autostart") return False return True
def _can_start(self, domain): """ Returns True if it has everything that is needed to run EIP, False otherwise :param domain: the domain for the provider to check :type domain: str """ if not LinuxPolicyChecker.is_up(): logger.error("No polkit agent running.") return False eip_config = eipconfig.EIPConfig() provider_config = ProviderConfig.get_provider_config(domain) api_version = provider_config.get_api_version() eip_config.set_api_version(api_version) eip_loaded = eip_config.load(eipconfig.get_eipconfig_path(domain)) launcher = get_vpn_launcher() ovpn_path = force_eval(launcher.OPENVPN_BIN_PATH) if not os.path.isfile(ovpn_path): logger.error("Cannot start OpenVPN, binary not found: %s" % (ovpn_path, )) return False # check for other problems if not eip_loaded or provider_config is None: logger.error("Cannot load provider and eip config, cannot " "autostart") return False client_cert_path = eip_config.\ get_client_cert_path(provider_config, about_to_download=True) if leap_certs.should_redownload(client_cert_path): logger.error("The client should redownload the certificate," " cannot autostart") return False if not os.path.isfile(client_cert_path): logger.error("Can't find the certificate, cannot autostart") return False return True
def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port="unix", openvpn_verb=1): """ Returns the Linux implementation for the vpn launching command. Might raise: EIPNoPkexecAvailable, EIPNoPolkitAuthAgentAvailable, OpenVPNNotFoundException, VPNLauncherException. :param eipconfig: eip configuration object :type eipconfig: EIPConfig :param providerconfig: provider specific configuration :type providerconfig: ProviderConfig :param socket_host: either socket path (unix) or socket IP :type socket_host: str :param socket_port: either string "unix" if it's a unix socket, or port otherwise :type socket_port: str :param openvpn_verb: the openvpn verbosity wanted :type openvpn_verb: int :return: A VPN command ready to be launched. :rtype: list """ # we use `super` in order to send the class to use command = super(LinuxVPNLauncher, kls).get_vpn_command( eipconfig, providerconfig, socket_host, socket_port, openvpn_verb ) command.insert(0, force_eval(kls.BITMASK_ROOT)) command.insert(1, "openvpn") command.insert(2, "start") policyChecker = LinuxPolicyChecker() try: pkexec = policyChecker.maybe_pkexec() except NoPolkitAuthAgentAvailable: raise EIPNoPolkitAuthAgentAvailable() except NoPkexecAvailable: raise EIPNoPkexecAvailable() if pkexec: command.insert(0, first(pkexec)) return command
def is_fw_down(self): """ Return whether the firewall is down or not. :rtype: bool """ if IS_LINUX: BM_ROOT = force_eval( linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 return fw_is_down() if IS_MAC: cmd = 'firewall_isup' helper = darwinvpnlauncher.DarwinHelperCommand() result = helper.send(cmd) return True
def _launch_firewall_linux(self, gateways, restart=False): """ Launch the firewall using the privileged wrapper (linux). :param gateways: :type gateways: list :returns: True if the exitcode of calling the root helper in a subprocess is 0. :rtype: bool """ # XXX could check for wrapper existence, check it's root owned etc. # XXX could check that the iptables rules are in place. BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) cmd = ["pkexec", BM_ROOT, "firewall", "start"] if restart: cmd.append("restart") exitCode = subprocess.call(cmd + gateways) return True if exitCode is 0 else False
def _launch_firewall(self, gateways, restart=False): """ Launch the firewall using the privileged wrapper. :param gateways: :type gateways: list :returns: True if the exitcode of calling the root helper in a subprocess is 0. :rtype: bool """ # XXX could check for wrapper existence, check it's root owned etc. # XXX could check that the iptables rules are in place. BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) cmd = ["pkexec", BM_ROOT, "firewall", "start"] if restart: cmd.append("restart") exitCode = subprocess.call(cmd + gateways) return True if exitCode is 0 else False
def missing_other_files(kls): """ Return what other important files are missing during startup. Same as missing_updown_scripts but does not check for exec bit. :rtype: list """ leap_assert( kls.OTHER_FILES is not None, "Need to define OTHER_FILES for this particular " "auncher before calling this method") other = force_eval(kls.OTHER_FILES) file_exist = partial(_has_other_files, warn=False) if flags.STANDALONE: try: from leap.bitmask import _binaries except ImportError: raise RuntimeError( "Could not find binary hash info in this bundle!") _, bitmask_root_path, openvpn_bin_path = other check_hash = _has_expected_binary_hash openvpn_hash = _binaries.OPENVPN_BIN bitmask_root_hash = _binaries.BITMASK_ROOT correct_hash = ( True, # we do not check the polkit file check_hash(bitmask_root_path, bitmask_root_hash), check_hash(openvpn_bin_path, openvpn_hash)) zipped = zip(other, map(file_exist, other), correct_hash) missing = filter( lambda (path, exists, hash_ok): (exists is False or hash_ok is False), zipped) return [path for path, exists, hash_ok in missing] else: zipped = zip(other, map(file_exist, other)) missing = filter(lambda (path, exists): exists is False, zipped) return [path for path, exists in missing]
def missing_other_files(kls): """ Return what other important files are missing during startup. Same as missing_updown_scripts but does not check for exec bit. :rtype: list """ leap_assert(kls.OTHER_FILES is not None, "Need to define OTHER_FILES for this particular " "auncher before calling this method") other = force_eval(kls.OTHER_FILES) file_exist = partial(_has_other_files, warn=False) if flags.STANDALONE: try: from leap.bitmask import _binaries except ImportError: raise RuntimeError( "Could not find binary hash info in this bundle!") _, bitmask_root_path, openvpn_bin_path = other check_hash = _has_expected_binary_hash openvpn_hash = _binaries.OPENVPN_BIN bitmask_root_hash = _binaries.BITMASK_ROOT correct_hash = ( True, # we do not check the polkit file check_hash(bitmask_root_path, bitmask_root_hash), check_hash(openvpn_bin_path, openvpn_hash)) zipped = zip(other, map(file_exist, other), correct_hash) missing = filter( lambda (path, exists, hash_ok): ( exists is False or hash_ok is False), zipped) return [path for path, exists, hash_ok in missing] else: zipped = zip(other, map(file_exist, other)) missing = filter(lambda (path, exists): exists is False, zipped) return [path for path, exists in missing]
def cmd_for_missing_scripts(kls, frompath): """ Returns a sh script that can copy the missing files. :param frompath: The path where the helper files live :type frompath: str :rtype: str """ bin_paths = force_eval( (LinuxVPNLauncher.POLKIT_PATH, LinuxVPNLauncher.OPENVPN_BIN_PATH, LinuxVPNLauncher.BITMASK_ROOT)) polkit_path, openvpn_bin_path, bitmask_root = bin_paths # no system config for now # sys_config = kls.SYSTEM_CONFIG (polkit_file, openvpn_bin_file, bitmask_root_file) = map( lambda p: os.path.split(p)[-1], bin_paths) cmd = '#!/bin/sh\n' cmd += 'mkdir -p /usr/local/sbin\n' cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, polkit_file), polkit_path) cmd += 'chmod 644 "%s"\n' % (polkit_path, ) cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, bitmask_root_file), bitmask_root) cmd += 'chmod 744 "%s"\n' % (bitmask_root, ) if flags.STANDALONE: cmd += 'cp "%s" "%s"\n' % ( os.path.join(frompath, openvpn_bin_file), openvpn_bin_path) cmd += 'chmod 744 "%s"\n' % (openvpn_bin_path, ) return cmd
def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port, openvpn_verb=1): """ Return the platform-dependant vpn command for launching openvpn. Might raise: OpenVPNNotFoundException, VPNLauncherException. :param eipconfig: eip configuration object :type eipconfig: EIPConfig :param providerconfig: provider specific configuration :type providerconfig: ProviderConfig :param socket_host: either socket path (unix) or socket IP :type socket_host: str :param socket_port: either string "unix" if it's a unix socket, or port otherwise :type socket_port: str :param openvpn_verb: the openvpn verbosity wanted :type openvpn_verb: int :return: A VPN command ready to be launched. :rtype: list """ leap_assert_type(eipconfig, EIPConfig) leap_assert_type(providerconfig, ProviderConfig) # XXX this still has to be changed on osx and windows accordingly # kwargs = {} # openvpn_possibilities = which(kls.OPENVPN_BIN, **kwargs) # if not openvpn_possibilities: # raise OpenVPNNotFoundException() # openvpn = first(openvpn_possibilities) # ----------------------------------------- openvpn_path = force_eval(kls.OPENVPN_BIN_PATH) if not os.path.isfile(openvpn_path): logger.warning("Could not find openvpn bin in path %s" % (openvpn_path)) raise OpenVPNNotFoundException() args = [] args += ['--setenv', "LEAPOPENVPN", "1", '--nobind'] if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb, )] gateways = kls.get_gateways(eipconfig, providerconfig) for gw in gateways: args += ['--remote', gw, '1194', 'udp'] args += [ '--client', '--dev', 'tun', '--persist-key', '--tls-client', '--remote-cert-tls', 'server' ] openvpn_configuration = eipconfig.get_openvpn_configuration() for key, value in openvpn_configuration.items(): args += ['--%s' % (key, ), value] user = getpass.getuser() if socket_port == "unix": # that's always the case for linux args += ['--management-client-user', user] args += [ '--management-signal', '--management', socket_host, socket_port, '--script-security', '2' ] if kls.UP_SCRIPT is not None: if _has_updown_scripts(kls.UP_SCRIPT): args += [ '--up', '\"%s\"' % (kls.UP_SCRIPT, ), ] if kls.DOWN_SCRIPT is not None: if _has_updown_scripts(kls.DOWN_SCRIPT): args += ['--down', '\"%s\"' % (kls.DOWN_SCRIPT, )] args += [ '--cert', eipconfig.get_client_cert_path(providerconfig), '--key', eipconfig.get_client_cert_path(providerconfig), '--ca', providerconfig.get_ca_cert_path() ] args += ['--ping', '10', '--ping-restart', '30'] command_and_args = [openvpn_path] + args return command_and_args
def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port, openvpn_verb=1): """ Return the platform-dependant vpn command for launching openvpn. Might raise: OpenVPNNotFoundException, VPNLauncherException. :param eipconfig: eip configuration object :type eipconfig: EIPConfig :param providerconfig: provider specific configuration :type providerconfig: ProviderConfig :param socket_host: either socket path (unix) or socket IP :type socket_host: str :param socket_port: either string "unix" if it's a unix socket, or port otherwise :type socket_port: str :param openvpn_verb: the openvpn verbosity wanted :type openvpn_verb: int :return: A VPN command ready to be launched. :rtype: list """ leap_assert_type(eipconfig, EIPConfig) leap_assert_type(providerconfig, ProviderConfig) # XXX this still has to be changed on osx and windows accordingly # kwargs = {} # openvpn_possibilities = which(kls.OPENVPN_BIN, **kwargs) # if not openvpn_possibilities: # raise OpenVPNNotFoundException() # openvpn = first(openvpn_possibilities) # ----------------------------------------- openvpn_path = force_eval(kls.OPENVPN_BIN_PATH) if not os.path.isfile(openvpn_path): logger.warning("Could not find openvpn bin in path %s" % ( openvpn_path)) raise OpenVPNNotFoundException() args = [] args += [ '--setenv', "LEAPOPENVPN", "1", '--nobind' ] if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] gateways = kls.get_gateways(eipconfig, providerconfig) for ip, port in gateways: args += ['--remote', ip, port, 'udp'] args += [ '--client', '--dev', 'tun', '--persist-key', '--tls-client', '--remote-cert-tls', 'server' ] openvpn_configuration = eipconfig.get_openvpn_configuration() for key, value in openvpn_configuration.items(): args += ['--%s' % (key,), value] user = getpass.getuser() if socket_port == "unix": # that's always the case for linux args += [ '--management-client-user', user ] args += [ '--management-signal', '--management', socket_host, socket_port, '--script-security', '2' ] if kls.UP_SCRIPT is not None: if _has_updown_scripts(kls.UP_SCRIPT): args += [ '--up', '\"%s\"' % (kls.UP_SCRIPT,), ] if kls.DOWN_SCRIPT is not None: if _has_updown_scripts(kls.DOWN_SCRIPT): args += [ '--down', '\"%s\"' % (kls.DOWN_SCRIPT,) ] args += [ '--cert', eipconfig.get_client_cert_path(providerconfig), '--key', eipconfig.get_client_cert_path(providerconfig), '--ca', providerconfig.get_ca_cert_path() ] args += [ '--ping', '10', '--ping-restart', '30'] command_and_args = [openvpn_path] + args return command_and_args