summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/services/eip
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask/services/eip')
-rw-r--r--src/leap/bitmask/services/eip/linuxvpnlauncher.py74
-rw-r--r--src/leap/bitmask/services/eip/vpnlauncher.py75
-rw-r--r--src/leap/bitmask/services/eip/vpnprocess.py8
3 files changed, 110 insertions, 47 deletions
diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
index 955768d1..8ec0c050 100644
--- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py
+++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
@@ -29,7 +29,7 @@ from leap.bitmask.util.privilege_policies import LinuxPolicyChecker
from leap.common.files import which
from leap.bitmask.services.eip.vpnlauncher import VPNLauncher
from leap.bitmask.services.eip.vpnlauncher import VPNLauncherException
-from leap.bitmask.util import get_path_prefix
+from leap.bitmask.util import get_path_prefix, force_eval
from leap.common.check import leap_assert
from leap.bitmask.util import first
@@ -105,26 +105,34 @@ leapfile = lambda f: "%s/%s" % (SYSTEM_CONFIG, f)
class LinuxVPNLauncher(VPNLauncher):
PKEXEC_BIN = 'pkexec'
- BITMASK_ROOT = "/usr/sbin/bitmask-root"
- # We assume this is there by our openvpn dependency, and
- # we will put it there on the bundle too.
- if flags.STANDALONE:
- OPENVPN_BIN_PATH = "/usr/sbin/leap-openvpn"
- else:
- OPENVPN_BIN_PATH = "/usr/sbin/openvpn"
-
- POLKIT_PATH = LinuxPolicyChecker.get_polkit_path()
-
- if flags.STANDALONE:
- RESOLVCONF_BIN_PATH = "/usr/local/sbin/leap-resolvconf"
- else:
+ # 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):
+ return ("/usr/local/sbin/bitmask-root" if flags.STANDALONE else
+ "/usr/sbin/bitmask-root")
+
+ class OPENVPN_BIN_PATH(object):
+ def __call__(self):
+ return ("/usr/local/sbin/leap-openvpn" if flags.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()
+
+ class RESOLVCONF_BIN_PATH(object):
+ def __call__(self):
+ return ("/usr/local/sbin/leap-resolvconf" if flags.STANDALONE else
+ "/sbin/resolvconf")
# this only will work with debian/ubuntu distros.
- RESOLVCONF_BIN_PATH = "/sbin/resolvconf"
- # XXX openvpn binary TOO
- OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT, OPENVPN_BIN_PATH,
- RESOLVCONF_BIN_PATH)
+ OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT, OPENVPN_BIN_PATH)
@classmethod
def maybe_pkexec(kls):
@@ -187,7 +195,7 @@ class LinuxVPNLauncher(VPNLauncher):
command = super(LinuxVPNLauncher, kls).get_vpn_command(
eipconfig, providerconfig, socket_host, socket_port, openvpn_verb)
- command.insert(0, kls.BITMASK_ROOT)
+ command.insert(0, force_eval(kls.BITMASK_ROOT))
command.insert(1, "openvpn")
command.insert(2, "start")
@@ -207,35 +215,37 @@ class LinuxVPNLauncher(VPNLauncher):
: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, resolvconf_bin_file) = map(
+ bitmask_root_file) = map(
lambda p: os.path.split(p)[-1],
- (kls.POLKIT_PATH, kls.OPENVPN_BIN_PATH,
- kls.BITMASK_ROOT, kls.RESOLVCONF_BIN_PATH))
+ bin_paths)
cmd = '#!/bin/sh\n'
cmd += 'mkdir -p /usr/local/sbin\n'
cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, polkit_file),
- kls.POLKIT_PATH)
- cmd += 'chmod 644 "%s"\n' % (kls.POLKIT_PATH, )
+ polkit_path)
+ cmd += 'chmod 644 "%s"\n' % (polkit_path, )
cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, bitmask_root_file),
- kls.BITMASK_ROOT)
- cmd += 'chmod 744 "%s"\n' % (kls.BITMASK_ROOT, )
+ bitmask_root)
+ cmd += 'chmod 744 "%s"\n' % (bitmask_root, )
if flags.STANDALONE:
cmd += 'cp "%s" "%s"\n' % (
os.path.join(frompath, openvpn_bin_file),
- kls.OPENVPN_BIN_PATH)
- cmd += 'chmod 744 "%s"\n' % (kls.POLKIT_PATH, )
+ openvpn_bin_path)
+ cmd += 'chmod 744 "%s"\n' % (openvpn_bin_path, )
- cmd += 'cp "%s" "%s"\n' % (
- os.path.join(frompath, resolvconf_bin_file),
- kls.RESOLVCONF_BIN_PATH)
- cmd += 'chmod 744 "%s"\n' % (kls.POLKIT_PATH, )
return cmd
@classmethod
diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py
index 9629afae..0731bee3 100644
--- a/src/leap/bitmask/services/eip/vpnlauncher.py
+++ b/src/leap/bitmask/services/eip/vpnlauncher.py
@@ -18,6 +18,7 @@
Platform independant VPN launcher interface.
"""
import getpass
+import hashlib
import logging
import os
import stat
@@ -30,6 +31,7 @@ from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.config.providerconfig import ProviderConfig
from leap.bitmask.platform_init import IS_LINUX
from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector
+from leap.bitmask.util import force_eval
from leap.common.check import leap_assert, leap_assert_type
@@ -76,7 +78,7 @@ def _has_updown_scripts(path, warn=True):
def _has_other_files(path, warn=True):
"""
- Checks the existence of other important files.
+ Check the existence of other important files.
:param path: the path to be checked
:type path: str
@@ -179,12 +181,13 @@ class VPNLauncher(object):
#raise OpenVPNNotFoundException()
#openvpn = first(openvpn_possibilities)
# -----------------------------------------
- if not os.path.isfile(kls.OPENVPN_BIN_PATH):
+ 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" % (
- kls.OPENVPN_BIN_PATH))
+ openvpn_path))
raise OpenVPNNotFoundException()
- openvpn = kls.OPENVPN_BIN_PATH
args = []
args += [
@@ -248,13 +251,13 @@ class VPNLauncher(object):
'--ping', '10',
'--ping-restart', '30']
- command_and_args = [openvpn] + args
+ command_and_args = [openvpn_path] + args
return command_and_args
@classmethod
def get_vpn_env(kls):
"""
- Returns a dictionary with the custom env for the platform.
+ Return a dictionary with the custom env for the platform.
This is mainly used for setting LD_LIBRARY_PATH to the correct
path when distributing a standalone client
@@ -265,7 +268,7 @@ class VPNLauncher(object):
@classmethod
def missing_updown_scripts(kls):
"""
- Returns what updown scripts are missing.
+ Return what updown scripts are missing.
:rtype: list
"""
@@ -285,7 +288,7 @@ class VPNLauncher(object):
@classmethod
def missing_other_files(kls):
"""
- Returns what other important files are missing during startup.
+ Return what other important files are missing during startup.
Same as missing_updown_scripts but does not check for exec bit.
:rtype: list
@@ -293,7 +296,57 @@ class VPNLauncher(object):
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)
- zipped = zip(kls.OTHER_FILES, map(file_exist, kls.OTHER_FILES))
- missing = filter(lambda (path, exists): exists is False, zipped)
- return [path for path, exists in missing]
+
+ 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 _has_expected_binary_hash(path, expected_hash):
+ """
+ Check if the passed path matches the expected hash.
+
+ Used from within the bundle, to know if we have to reinstall the shipped
+ binaries into the system path.
+
+ This path will be /usr/local/sbin for linux.
+
+ :param path: the path to check.
+ :type path: str
+ :param expected_hash: the sha256 hash that we expect
+ :type expected_hash: str
+ :rtype: bool
+ """
+ try:
+ with open(path) as f:
+ file_hash = hashlib.sha256(f.read()).hexdigest()
+ return expected_hash == file_hash
+ except IOError:
+ return False
diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py
index f56d464e..b54f2925 100644
--- a/src/leap/bitmask/services/eip/vpnprocess.py
+++ b/src/leap/bitmask/services/eip/vpnprocess.py
@@ -43,7 +43,7 @@ from leap.bitmask.services.eip import get_vpn_launcher
from leap.bitmask.services.eip import linuxvpnlauncher
from leap.bitmask.services.eip.eipconfig import EIPConfig
from leap.bitmask.services.eip.udstelnet import UDSTelnet
-from leap.bitmask.util import first
+from leap.bitmask.util import first, force_eval
from leap.bitmask.platform_init import IS_MAC, IS_LINUX
from leap.common.check import leap_assert, leap_assert_type
@@ -233,7 +233,7 @@ class VPN(object):
# XXX could check for wrapper existence, check it's root owned etc.
# XXX could check that the iptables rules are in place.
- BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT
+ BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT)
cmd = ["pkexec", BM_ROOT, "firewall", "start"]
if restart:
cmd.append("restart")
@@ -246,7 +246,7 @@ class VPN(object):
:rtype: bool
"""
- BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT
+ 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()
@@ -255,7 +255,7 @@ class VPN(object):
"""
Tear the firewall down using the privileged wrapper.
"""
- BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT
+ BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT)
exitCode = subprocess.call(["pkexec",
BM_ROOT, "firewall", "stop"])
return True if exitCode is 0 else False