summaryrefslogtreecommitdiff
path: root/src/leap/eip/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/eip/config.py')
-rw-r--r--src/leap/eip/config.py190
1 files changed, 152 insertions, 38 deletions
diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py
index ef0f52b4..917871da 100644
--- a/src/leap/eip/config.py
+++ b/src/leap/eip/config.py
@@ -1,10 +1,12 @@
import logging
import os
import platform
+import re
import tempfile
from leap import __branding as BRANDING
from leap import certs
+from leap.util.misc import null_check
from leap.util.fileutil import (which, mkdir_p, check_and_fix_urw_only)
from leap.base import config as baseconfig
@@ -16,6 +18,8 @@ from leap.eip import specs as eipspecs
logger = logging.getLogger(name=__name__)
provider_ca_file = BRANDING.get('provider_ca_file', None)
+_platform = platform.system()
+
class EIPConfig(baseconfig.JSONLeapConfig):
spec = eipspecs.eipconfig_spec
@@ -35,9 +39,13 @@ class EIPServiceConfig(baseconfig.JSONLeapConfig):
spec = eipspecs.eipservice_config_spec
def _get_slug(self):
+ domain = getattr(self, 'domain', None)
+ if domain:
+ path = baseconfig.get_provider_path(domain)
+ else:
+ path = baseconfig.get_default_provider_path()
return baseconfig.get_config_file(
- 'eip-service.json',
- folder=baseconfig.get_default_provider_path())
+ 'eip-service.json', folder=path)
def _set_slug(self):
raise AttributeError("you cannot set slug")
@@ -49,45 +57,96 @@ def get_socket_path():
socket_path = os.path.join(
tempfile.mkdtemp(prefix="leap-tmp"),
'openvpn.socket')
- logger.debug('socket path: %s', socket_path)
+ #logger.debug('socket path: %s', socket_path)
return socket_path
-def get_eip_gateway():
+def get_eip_gateway(eipconfig=None, eipserviceconfig=None):
"""
return the first host in eip service config
that matches the name defined in the eip.json config
file.
"""
- placeholder = "testprovider.example.org"
- eipconfig = EIPConfig()
- #import ipdb;ipdb.set_trace()
- eipconfig.load()
+ # XXX eventually we should move to a more clever
+ # gateway selection. maybe we could return
+ # all gateways that match our cluster.
+
+ null_check(eipconfig, "eipconfig")
+ null_check(eipserviceconfig, "eipserviceconfig")
+ PLACEHOLDER = "testprovider.example.org"
+
conf = eipconfig.config
+ eipsconf = eipserviceconfig.config
primary_gateway = conf.get('primary_gateway', None)
if not primary_gateway:
- return placeholder
+ return PLACEHOLDER
- eipserviceconfig = EIPServiceConfig()
- eipserviceconfig.load()
- eipsconf = eipserviceconfig.get_config()
gateways = eipsconf.get('gateways', None)
if not gateways:
logger.error('missing gateways in eip service config')
- return placeholder
+ return PLACEHOLDER
+
if len(gateways) > 0:
for gw in gateways:
- if gw['name'] == primary_gateway:
- hosts = gw['hosts']
- if len(hosts) > 0:
- return hosts[0]
- else:
- logger.error('no hosts')
+ clustername = gw.get('cluster', None)
+ if not clustername:
+ logger.error('no cluster name')
+ return
+
+ if clustername == primary_gateway:
+ # XXX at some moment, we must
+ # make this a more generic function,
+ # and return ports, protocols...
+ ipaddress = gw.get('ip_address', None)
+ if not ipaddress:
+ logger.error('no ip_address')
+ return
+ return ipaddress
logger.error('could not find primary gateway in provider'
'gateway list')
+def get_cipher_options(eipserviceconfig=None):
+ """
+ gathers optional cipher options from eip-service config.
+ :param eipserviceconfig: EIPServiceConfig instance
+ """
+ null_check(eipserviceconfig, 'eipserviceconfig')
+ eipsconf = eipserviceconfig.get_config()
+
+ ALLOWED_KEYS = ("auth", "cipher", "tls-cipher")
+ CIPHERS_REGEX = re.compile("[A-Z0-9\-]+")
+ opts = []
+ if 'openvpn_configuration' in eipsconf:
+ config = eipserviceconfig.config.get(
+ "openvpn_configuration", {})
+ for key, value in config.items():
+ if key in ALLOWED_KEYS and value is not None:
+ sanitized_val = CIPHERS_REGEX.findall(value)
+ if len(sanitized_val) != 0:
+ _val = sanitized_val[0]
+ opts.append('--%s' % key)
+ opts.append('%s' % _val)
+ return opts
+
+LINUX_UP_DOWN_SCRIPT = "/etc/leap/resolv-update"
+OPENVPN_DOWN_ROOT = "/usr/lib/openvpn/openvpn-down-root.so"
+
+
+def has_updown_scripts():
+ """
+ checks the existence of the up/down scripts
+ """
+ # XXX should check permissions too
+ is_file = os.path.isfile(LINUX_UP_DOWN_SCRIPT)
+ if not is_file:
+ logger.warning(
+ "Could not find up/down scripts at %s! "
+ "Risk of DNS Leaks!!!")
+ return is_file
+
+
def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
"""
build a list of options
@@ -103,6 +162,12 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
# since we will need to take some
# things from there if present.
+ provider = kwargs.pop('provider', None)
+ eipconfig = EIPConfig(domain=provider)
+ eipconfig.load()
+ eipserviceconfig = EIPServiceConfig(domain=provider)
+ eipserviceconfig.load()
+
# get user/group name
# also from config.
user = baseconfig.get_username()
@@ -123,18 +188,32 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
opts.append('--verb')
opts.append("%s" % verbosity)
- # remote
+ # remote ##############################
+ # (server, port, protocol)
+
opts.append('--remote')
- gw = get_eip_gateway()
+
+ gw = get_eip_gateway(eipconfig=eipconfig,
+ eipserviceconfig=eipserviceconfig)
logger.debug('setting eip gateway to %s', gw)
opts.append(str(gw))
+
+ # get port/protocol from eipservice too
opts.append('1194')
+ #opts.append('80')
opts.append('udp')
opts.append('--tls-client')
opts.append('--remote-cert-tls')
opts.append('server')
+ # get ciphers #######################
+
+ ciphers = get_cipher_options(
+ eipserviceconfig=eipserviceconfig)
+ for cipheropt in ciphers:
+ opts.append(str(cipheropt))
+
# set user and group
opts.append('--user')
opts.append('%s' % user)
@@ -149,8 +228,13 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
# interface. unix sockets or telnet interface for win.
# XXX take them from the config object.
- ourplatform = platform.system()
- if ourplatform in ("Linux", "Mac"):
+ if _platform == "Windows":
+ opts.append('--management')
+ opts.append('localhost')
+ # XXX which is a good choice?
+ opts.append('7777')
+
+ if _platform in ("Linux", "Darwin"):
opts.append('--management')
if socket_path is None:
@@ -158,19 +242,30 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
opts.append(socket_path)
opts.append('unix')
- if ourplatform == "Windows":
- opts.append('--management')
- opts.append('localhost')
- # XXX which is a good choice?
- opts.append('7777')
+ opts.append('--script-security')
+ opts.append('2')
+
+ if _platform == "Linux":
+ if has_updown_scripts():
+ opts.append("--up")
+ opts.append(LINUX_UP_DOWN_SCRIPT)
+ opts.append("--down")
+ opts.append(LINUX_UP_DOWN_SCRIPT)
+ opts.append("--plugin")
+ opts.append(OPENVPN_DOWN_ROOT)
+ opts.append("'script_type=down %s'" % LINUX_UP_DOWN_SCRIPT)
# certs
+ client_cert_path = eipspecs.client_cert_path(provider)
+ ca_cert_path = eipspecs.provider_ca_path(provider)
+
+ # XXX FIX paths for MAC
opts.append('--cert')
- opts.append(eipspecs.client_cert_path())
+ opts.append(client_cert_path)
opts.append('--key')
- opts.append(eipspecs.client_cert_path())
+ opts.append(client_cert_path)
opts.append('--ca')
- opts.append(eipspecs.provider_ca_path())
+ opts.append(ca_cert_path)
# we cannot run in daemon mode
# with the current subp setting.
@@ -178,7 +273,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs):
#if daemon is True:
#opts.append('--daemon')
- logger.debug('vpn options: %s', opts)
+ logger.debug('vpn options: %s', ' '.join(opts))
return opts
@@ -198,7 +293,7 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None,
# XXX get use_pkexec from config instead.
- if platform.system() == "Linux" and use_pkexec and do_pkexec_check:
+ if _platform == "Linux" and use_pkexec and do_pkexec_check:
# check for both pkexec
# AND a suitable authentication
@@ -218,8 +313,16 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None,
raise eip_exceptions.EIPNoPolkitAuthAgentAvailable
command.append('pkexec')
+
if vpnbin is None:
- ovpn = which('openvpn')
+ if _platform == "Darwin":
+ # XXX Should hardcode our installed path
+ # /Applications/LEAPClient.app/Contents/Resources/openvpn.leap
+ openvpn_bin = "openvpn.leap"
+ else:
+ openvpn_bin = "openvpn"
+ #XXX hardcode for darwin
+ ovpn = which(openvpn_bin)
else:
ovpn = vpnbin
if ovpn:
@@ -235,10 +338,20 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None,
# XXX check len and raise proper error
- return [command[0], command[1:]]
+ if _platform == "Darwin":
+ OSX_ASADMIN = 'do shell script "%s" with administrator privileges'
+ # XXX fix workaround for Nones
+ _command = [x if x else " " for x in command]
+ # XXX debugging!
+ # XXX get openvpn log path from debug flags
+ _command.append('--log')
+ _command.append('/tmp/leap_openvpn.log')
+ return ["osascript", ["-e", OSX_ASADMIN % ' '.join(_command)]]
+ else:
+ return [command[0], command[1:]]
-def check_vpn_keys():
+def check_vpn_keys(provider=None):
"""
performs an existance and permission check
over the openvpn keys file.
@@ -246,8 +359,9 @@ def check_vpn_keys():
per provider, containing the CA cert,
the provider key, and our client certificate
"""
- provider_ca = eipspecs.provider_ca_path()
- client_cert = eipspecs.client_cert_path()
+ assert provider is not None
+ provider_ca = eipspecs.provider_ca_path(provider)
+ client_cert = eipspecs.client_cert_path(provider)
logger.debug('provider ca = %s', provider_ca)
logger.debug('client cert = %s', client_cert)