summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@leap.se>2012-12-15 02:25:50 +0900
committerkali <kali@leap.se>2012-12-15 02:25:50 +0900
commit5e7ca61cfd942404663e68d2d4eae062dfbc66bc (patch)
tree1540883cdc002930210365c4d2e975a93b2a7989
parentf3cbae1d2c14e2ff22888d4fc83d03ec6c452541 (diff)
parent914a07aaf8ef52b2eaf88f1bf01fb6f72adcac5a (diff)
Merge branch 'feature/eip-service-formatchange' into develop
-rw-r--r--src/leap/base/auth.py14
-rw-r--r--src/leap/base/specs.py16
-rw-r--r--src/leap/base/tests/test_providers.py6
-rw-r--r--src/leap/baseapp/eip.py2
-rw-r--r--src/leap/baseapp/network.py8
-rw-r--r--src/leap/crypto/certs.py42
-rw-r--r--src/leap/crypto/tests/__init__.py0
-rw-r--r--src/leap/crypto/tests/test_certs.py11
-rw-r--r--src/leap/eip/checks.py29
-rw-r--r--src/leap/eip/config.py27
-rw-r--r--src/leap/eip/specs.py37
-rw-r--r--src/leap/eip/tests/data.py33
-rw-r--r--src/leap/eip/tests/test_config.py64
-rw-r--r--src/leap/gui/firstrun/regvalidation.py14
14 files changed, 212 insertions, 91 deletions
diff --git a/src/leap/base/auth.py b/src/leap/base/auth.py
index 73856bb0..c6bd3518 100644
--- a/src/leap/base/auth.py
+++ b/src/leap/base/auth.py
@@ -43,7 +43,7 @@ class LeapSRPRegister(object):
def __init__(self,
schema="https",
provider=None,
- port=None,
+ #port=None,
verify=True,
register_path="1/users.json",
method="POST",
@@ -57,8 +57,8 @@ class LeapSRPRegister(object):
self.schema = schema
# XXX FIXME
- self.provider = provider
- self.port = port
+ #self.provider = provider
+ #self.port = port
# XXX splitting server,port
# deprecate port call.
domain, port = get_https_domain_and_port(provider)
@@ -255,6 +255,7 @@ class SRPAuth(requests.auth.AuthBase):
try:
assert self.srp_usr.authenticated()
logger.debug('user is authenticated!')
+ print 'user is authenticated!'
except (AssertionError):
raise SRPAuthenticationError(
"Auth verification failed.")
@@ -355,8 +356,11 @@ if __name__ == "__main__":
req.raise_for_status
return req
- req = test_srp_protected_get('https://localhost:8443/1/cert')
- print 'cert :', req.content[:200] + "..."
+ #req = test_srp_protected_get('https://localhost:8443/1/cert')
+ req = test_srp_protected_get('%s/1/cert' % SERVER)
+ import ipdb;ipdb.set_trace()
+ #print 'cert :', req.content[:200] + "..."
+ print 'cert :', req.content
sys.exit(0)
if action == "add":
diff --git a/src/leap/base/specs.py b/src/leap/base/specs.py
index b4bb8dcf..962aa07d 100644
--- a/src/leap/base/specs.py
+++ b/src/leap/base/specs.py
@@ -2,22 +2,26 @@ leap_provider_spec = {
'description': 'provider definition',
'type': 'object',
'properties': {
- 'serial': {
- 'type': int,
- 'default': 1,
- 'required': True,
- },
+ #'serial': {
+ #'type': int,
+ #'default': 1,
+ #'required': True,
+ #},
'version': {
'type': unicode,
'default': '0.1.0'
#'required': True
},
+ "default_language": {
+ 'type': unicode,
+ 'default': 'en'
+ },
'domain': {
'type': unicode, # XXX define uri type
'default': 'testprovider.example.org'
#'required': True,
},
- 'display_name': {
+ 'name': {
'type': dict, # XXX multilingual object?
'default': {u'en': u'Test Provider'}
#'required': True
diff --git a/src/leap/base/tests/test_providers.py b/src/leap/base/tests/test_providers.py
index d9604fab..8801a3eb 100644
--- a/src/leap/base/tests/test_providers.py
+++ b/src/leap/base/tests/test_providers.py
@@ -16,10 +16,12 @@ from leap.base import providers
EXPECTED_DEFAULT_CONFIG = {
u"api_version": u"0.1.0",
u"description": {u'en': u"Test provider"},
- u"display_name": {u'en': u"Test Provider"},
+ u"default_language": u"en",
+ #u"display_name": {u'en': u"Test Provider"},
u"domain": u"testprovider.example.org",
+ u'name': {u'en': u'Test Provider'},
u"enrollment_policy": u"open",
- u"serial": 1,
+ #u"serial": 1,
u"services": [
u"eip"
],
diff --git a/src/leap/baseapp/eip.py b/src/leap/baseapp/eip.py
index 54acbc0e..0d7506b3 100644
--- a/src/leap/baseapp/eip.py
+++ b/src/leap/baseapp/eip.py
@@ -203,6 +203,8 @@ class EIPConductorAppMixin(object):
# we could bring Timer Init to this Mixin
# or to its own Mixin.
self.timer.start(constants.TIMER_MILLISECONDS)
+ # XXX EMIT SIGNAL INSTEAD (when first run,
+ # network checker does not exist...)
self.network_checker.start()
return
diff --git a/src/leap/baseapp/network.py b/src/leap/baseapp/network.py
index 3e57490d..7363cfaa 100644
--- a/src/leap/baseapp/network.py
+++ b/src/leap/baseapp/network.py
@@ -18,13 +18,17 @@ class NetworkCheckerAppMixin(object):
def __init__(self, *args, **kwargs):
provider = kwargs.pop('provider', None)
+ if provider:
+ self.init_network_checker(provider)
+
+ def init_network_checker(self, provider):
self.network_checker = NetworkCheckerThread(
error_cb=self.networkError.emit,
debug=self.debugmode,
provider=provider)
- # XXX move run_checks to slot -- this definitely
- # cannot start on init!!!
+ @QtCore.pyqtSlot(object)
+ def runNetworkChecks(self):
self.network_checker.run_checks()
@QtCore.pyqtSlot(object)
diff --git a/src/leap/crypto/certs.py b/src/leap/crypto/certs.py
index 8908865d..45d7326d 100644
--- a/src/leap/crypto/certs.py
+++ b/src/leap/crypto/certs.py
@@ -1,10 +1,14 @@
import ctypes
+from StringIO import StringIO
+import re
import socket
import gnutls.connection
import gnutls.crypto
import gnutls.library
+from leap.util.misc import null_check
+
def get_https_cert_from_domain(domain):
"""
@@ -20,12 +24,44 @@ def get_https_cert_from_domain(domain):
return cert
-def get_cert_from_file(filepath):
- with open(filepath) as f:
- cert = gnutls.crypto.X509Certificate(f.read())
+def get_cert_from_file(_file):
+ getcert = lambda f: gnutls.crypto.X509Certificate(f.read())
+ if isinstance(_file, str):
+ with open(_file) as f:
+ cert = getcert(f)
+ else:
+ cert = getcert(_file)
return cert
+def get_pkey_from_file(_file):
+ getkey = lambda f: gnutls.crypto.X509PrivateKey(f.read())
+ if isinstance(_file, str):
+ with open(_file) as f:
+ key = getkey(f)
+ else:
+ key = getkey(_file)
+ return key
+
+
+def can_load_cert_and_pkey(string):
+ try:
+ f = StringIO(string)
+ cert = get_cert_from_file(f)
+
+ f = StringIO(string)
+ key = get_pkey_from_file(f)
+
+ null_check(cert, 'certificate')
+ null_check(key, 'private key')
+ except:
+ # XXX catch GNUTLSError
+ raise
+ return False
+ else:
+ return True
+
+
def get_cert_fingerprint(domain=None, filepath=None,
hash_type="SHA256", sep=":"):
"""
diff --git a/src/leap/crypto/tests/__init__.py b/src/leap/crypto/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/leap/crypto/tests/__init__.py
diff --git a/src/leap/crypto/tests/test_certs.py b/src/leap/crypto/tests/test_certs.py
new file mode 100644
index 00000000..4d167c51
--- /dev/null
+++ b/src/leap/crypto/tests/test_certs.py
@@ -0,0 +1,11 @@
+import unittest
+
+
+class CertTestCase(unittest.TestCase):
+
+ def test_load_client_and_pkey(self):
+ self.fail('not implemented')
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py
index 8d615b94..d7f4402b 100644
--- a/src/leap/eip/checks.py
+++ b/src/leap/eip/checks.py
@@ -160,7 +160,6 @@ class ProviderCertChecker(object):
if autocacert and verify is True and self.cacert is not None:
logger.debug('verify cert: %s', self.cacert)
verify = self.cacert
- #import pdb4qt; pdb4qt.set_trace()
logger.debug('is https working?')
logger.debug('uri: %s (verify:%s)', uri, verify)
try:
@@ -242,7 +241,9 @@ class ProviderCertChecker(object):
raise
try:
pemfile_content = req.content
- self.is_valid_pemfile(pemfile_content)
+ valid = self.is_valid_pemfile(pemfile_content)
+ if not valid:
+ return False
cert_path = self._get_client_cert_path()
self.write_cert(pemfile_content, to=cert_path)
except:
@@ -276,7 +277,10 @@ class ProviderCertChecker(object):
cert = gnutls.crypto.X509Certificate(cert_s)
from_ = time.gmtime(cert.activation_time)
to_ = time.gmtime(cert.expiration_time)
- return from_ < now() < to_
+ # FIXME BUG ON LEAP_CLI, certs are not valid on gmtime
+ # See #1153
+ #return from_ < now() < to_
+ return now() < to_
def is_valid_pemfile(self, cert_s=None):
"""
@@ -290,23 +294,8 @@ class ProviderCertChecker(object):
certfile = self._get_client_cert_path()
with open(certfile) as cf:
cert_s = cf.read()
- try:
- # XXX get a real cert validation
- # so far this is only checking begin/end
- # delimiters :)
- # XXX use gnutls for get proper
- # validation.
- # crypto.X509Certificate(cert_s)
- sep = "-" * 5 + "BEGIN CERTIFICATE" + "-" * 5
- # we might have private key and cert in the same file
- certparts = cert_s.split(sep)
- if len(certparts) > 1:
- cert_s = sep + certparts[1]
- ssl.PEM_cert_to_DER_cert(cert_s)
- except:
- # XXX raise proper exception
- raise
- return True
+ valid = certs.can_load_cert_and_pkey(cert_s)
+ return valid
@property
def ca_cert_path(self):
diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py
index e40d2785..48e6e9a7 100644
--- a/src/leap/eip/config.py
+++ b/src/leap/eip/config.py
@@ -65,9 +65,12 @@ def get_eip_gateway(eipconfig=None, eipserviceconfig=None):
that matches the name defined in the eip.json config
file.
"""
+ # 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
@@ -78,26 +81,26 @@ def get_eip_gateway(eipconfig=None, eipserviceconfig=None):
return PLACEHOLDER
gateways = eipsconf.get('gateways', None)
-
if not gateways:
logger.error('missing gateways in eip service config')
return PLACEHOLDER
if len(gateways) > 0:
for gw in gateways:
- name = gw.get('name', None)
- if not name:
+ clustername = gw.get('cluster', None)
+ if not clustername:
+ logger.error('no cluster name')
return
- if name == primary_gateway:
- hosts = gw.get('hosts', None)
- if not hosts:
- logger.error('no hosts')
+ 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
- if len(hosts) > 0:
- return hosts[0]
- else:
- logger.error('no hosts')
+ return ipaddress
logger.error('could not find primary gateway in provider'
'gateway list')
diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py
index cf5d5359..c41fd29b 100644
--- a/src/leap/eip/specs.py
+++ b/src/leap/eip/specs.py
@@ -77,12 +77,12 @@ eipconfig_spec = {
},
'primary_gateway': {
'type': unicode,
- 'default': u"turkey",
+ 'default': u"location_unknown",
#'required': True
},
'secondary_gateway': {
'type': unicode,
- 'default': u"france"
+ 'default': u"location_unknown2"
},
'management_password': {
'type': unicode
@@ -100,25 +100,30 @@ eipservice_config_spec = {
'default': 1
},
'version': {
- 'type': unicode,
+ 'type': int,
'required': True,
- 'default': "0.1.0"
+ 'default': 1
},
- 'capabilities': {
- 'type': dict,
- 'default': {
- "transport": ["openvpn"],
- "ports": ["80", "53"],
- "protocols": ["udp", "tcp"],
- "static_ips": True,
- "adblock": True}
+ 'clusters': {
+ 'type': list,
+ 'default': [
+ {"label": {
+ "en": "Location Unknown"},
+ "name": "location_unknown"}]
},
'gateways': {
'type': list,
- 'default': [{"country_code": "us",
- "label": {"en":"west"},
- "capabilities": {},
- "hosts": ["1.2.3.4", "1.2.3.5"]}]
+ 'default': [
+ {"capabilities": {
+ "adblock": True,
+ "filter_dns": True,
+ "ports": ["80", "53", "443", "1194"],
+ "protocols": ["udp", "tcp"],
+ "transport": ["openvpn"],
+ "user_ips": False},
+ "cluster": "location_unknown",
+ "host": "location.example.org",
+ "ip_address": "127.0.0.1"}]
},
'openvpn_configuration': {
'type': dict,
diff --git a/src/leap/eip/tests/data.py b/src/leap/eip/tests/data.py
index cadf720e..a7fe1853 100644
--- a/src/leap/eip/tests/data.py
+++ b/src/leap/eip/tests/data.py
@@ -23,26 +23,29 @@ EIP_SAMPLE_CONFIG = {
"keys/client/openvpn.pem" % PROVIDER),
"connect_on_login": True,
"block_cleartext_traffic": True,
- "primary_gateway": "turkey",
- "secondary_gateway": "france",
+ "primary_gateway": "location_unknown",
+ "secondary_gateway": "location_unknown2",
#"management_password": "oph7Que1othahwiech6J"
}
EIP_SAMPLE_SERVICE = {
"serial": 1,
- "version": "0.1.0",
- "capabilities": {
- "transport": ["openvpn"],
- "ports": ["80", "53"],
- "protocols": ["udp", "tcp"],
- "static_ips": True,
- "adblock": True
- },
+ "version": 1,
+ "clusters": [
+ {"label": {
+ "en": "Location Unknown"},
+ "name": "location_unknown"}
+ ],
"gateways": [
- {"country_code": "tr",
- "name": "turkey",
- "label": {"en":"Ankara, Turkey"},
- "capabilities": {},
- "hosts": ["192.0.43.10"]}
+ {"capabilities": {
+ "adblock": True,
+ "filter_dns": True,
+ "ports": ["80", "53", "443", "1194"],
+ "protocols": ["udp", "tcp"],
+ "transport": ["openvpn"],
+ "user_ips": False},
+ "cluster": "location_unknown",
+ "host": "location.example.org",
+ "ip_address": "192.0.43.10"}
]
}
diff --git a/src/leap/eip/tests/test_config.py b/src/leap/eip/tests/test_config.py
index 404d543f..5977ef3c 100644
--- a/src/leap/eip/tests/test_config.py
+++ b/src/leap/eip/tests/test_config.py
@@ -15,7 +15,7 @@ except ImportError:
from leap.eip import config as eipconfig
from leap.eip.tests.data import EIP_SAMPLE_CONFIG, EIP_SAMPLE_SERVICE
from leap.testing.basetest import BaseLeapTest
-from leap.util.fileutil import mkdir_p
+from leap.util.fileutil import mkdir_p, mkdir_f
_system = platform.system()
@@ -48,11 +48,12 @@ class EIPConfigTest(BaseLeapTest):
open(tfile, 'wb').close()
os.chmod(tfile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
- def write_sample_eipservice(self, vpnciphers=False, extra_vpnopts=None):
+ def write_sample_eipservice(self, vpnciphers=False, extra_vpnopts=None,
+ gateways=None):
conf = eipconfig.EIPServiceConfig()
- folder, f = os.path.split(conf.filename)
- if not os.path.isdir(folder):
- mkdir_p(folder)
+ mkdir_f(conf.filename)
+ if gateways:
+ EIP_SAMPLE_SERVICE['gateways'] = gateways
if vpnciphers:
openvpnconfig = OrderedDict({
"auth": "SHA1",
@@ -75,6 +76,10 @@ class EIPConfigTest(BaseLeapTest):
fd.write(json.dumps(EIP_SAMPLE_CONFIG))
def get_expected_openvpn_args(self, with_openvpn_ciphers=False):
+ """
+ yeah, this is almost as duplicating the
+ code for building the command
+ """
args = []
eipconf = eipconfig.EIPConfig(domain=self.provider)
eipconf.load()
@@ -156,6 +161,55 @@ class EIPConfigTest(BaseLeapTest):
# params in the function call, to disable
# some checks.
+ def test_get_eip_gateway(self):
+ self.write_sample_eipconfig()
+ eipconf = eipconfig.EIPConfig(domain=self.provider)
+
+ # default eipservice
+ self.write_sample_eipservice()
+ eipsconf = eipconfig.EIPServiceConfig(domain=self.provider)
+
+ gateway = eipconfig.get_eip_gateway(
+ eipconfig=eipconf,
+ eipserviceconfig=eipsconf)
+
+ # in spec is local gateway by default
+ self.assertEqual(gateway, '127.0.0.1')
+
+ # change eipservice
+ # right now we only check that cluster == selected primary gw in
+ # eip.json, and pick first matching ip
+ eipconf._config.config['primary_gateway'] = "foo_provider"
+ newgateways = [{"cluster": "foo_provider",
+ "ip_address": "127.0.0.99"}]
+ self.write_sample_eipservice(gateways=newgateways)
+ eipsconf = eipconfig.EIPServiceConfig(domain=self.provider)
+ # load from disk file
+ eipsconf.load()
+
+ gateway = eipconfig.get_eip_gateway(
+ eipconfig=eipconf,
+ eipserviceconfig=eipsconf)
+ self.assertEqual(gateway, '127.0.0.99')
+
+ # change eipservice, several gateways
+ # right now we only check that cluster == selected primary gw in
+ # eip.json, and pick first matching ip
+ eipconf._config.config['primary_gateway'] = "bar_provider"
+ newgateways = [{"cluster": "foo_provider",
+ "ip_address": "127.0.0.99"},
+ {'cluster': "bar_provider",
+ "ip_address": "127.0.0.88"}]
+ self.write_sample_eipservice(gateways=newgateways)
+ eipsconf = eipconfig.EIPServiceConfig(domain=self.provider)
+ # load from disk file
+ eipsconf.load()
+
+ gateway = eipconfig.get_eip_gateway(
+ eipconfig=eipconf,
+ eipserviceconfig=eipsconf)
+ self.assertEqual(gateway, '127.0.0.88')
+
def test_build_ovpn_command_empty_config(self):
self.touch_exec()
self.write_sample_eipservice()
diff --git a/src/leap/gui/firstrun/regvalidation.py b/src/leap/gui/firstrun/regvalidation.py
index 0e67834b..aeb98204 100644
--- a/src/leap/gui/firstrun/regvalidation.py
+++ b/src/leap/gui/firstrun/regvalidation.py
@@ -100,9 +100,12 @@ class RegisterUserValidationPage(ValidationPage):
def fetcheipcert():
try:
- pCertChecker.download_new_client_cert(
+ downloaded = pCertChecker.download_new_client_cert(
credentials=credentials,
verify=verify)
+ if not downloaded:
+ logger.error('Could not download client cert.')
+ return False
except auth.SRPAuthenticationError as exc:
return self.fail(self.tr(
@@ -126,10 +129,11 @@ class RegisterUserValidationPage(ValidationPage):
"""
# this should be called CONNECT PAGE AGAIN.
# here we go! :)
- full_domain = self.field('provider_domain')
- domain, port = get_https_domain_and_port(full_domain)
- _domain = u"%s:%s" % (domain, port) if port != 443 else unicode(domain)
- self.run_eip_checks_for_provider_and_connect(_domain)
+ if self.is_done():
+ full_domain = self.field('provider_domain')
+ domain, port = get_https_domain_and_port(full_domain)
+ _domain = u"%s:%s" % (domain, port) if port != 443 else unicode(domain)
+ self.run_eip_checks_for_provider_and_connect(_domain)
def run_eip_checks_for_provider_and_connect(self, domain):
wizard = self.wizard()