# -*- coding: utf-8 -*- # linux # Copyright (C) 2013-2017 LEAP # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Linux VPN launcher implementation. """ import commands import os from twisted.logger import Logger from leap.bitmask.util import STANDALONE from leap.bitmask.vpn.utils import first, force_eval from leap.bitmask.vpn.privilege import LinuxPolicyChecker from leap.bitmask.vpn.launcher import VPNLauncher logger = Logger() COM = commands class LinuxVPNLauncher(VPNLauncher): # The following classes depend on force_eval to be called against # the classes, to get the evaluation of the standalone flag on runtine. # If we keep extending this kind of classes, we should abstract the # handling of the STANDALONE flag in a base class class BITMASK_ROOT(object): def __call__(self): _global = '/usr/sbin/bitmask-root' _local = '/usr/local/sbin/bitmask-root' if os.path.isfile(_global): return _global elif os.path.isfile(_local): return _local else: return 'bitmask-root' class OPENVPN_BIN_PATH(object): def __call__(self): return ("/usr/local/sbin/leap-openvpn" if STANDALONE else "/usr/sbin/openvpn") class POLKIT_PATH(object): def __call__(self): # LinuxPolicyChecker will give us the right path if standalone. return LinuxPolicyChecker.get_polkit_path() OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT, OPENVPN_BIN_PATH) @classmethod def get_vpn_command(kls, vpnconfig, providerconfig, socket_host, remotes, socket_port="unix", openvpn_verb=1): """ Returns the Linux implementation for the vpn launching command. Might raise: NoPkexecAvailable, NoPolkitAuthAgentAvailable, OpenVPNNotFoundException, VPNLauncherException. :param vpnconfig: vpn configuration object :type vpnconfig: VPNConfig :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( vpnconfig, providerconfig, socket_host, socket_port, remotes, openvpn_verb) command.insert(0, force_eval(kls.BITMASK_ROOT)) command.insert(1, "openvpn") command.insert(2, "start") if os.getuid() != 0: policyChecker = LinuxPolicyChecker() pkexec = policyChecker.maybe_pkexec() if pkexec: command.insert(0, first(pkexec)) return command