From 0875a3d498c30187a40a788d3bd1eefa9c5924e2 Mon Sep 17 00:00:00 2001 From: antialias Date: Fri, 12 Oct 2012 15:49:28 -0400 Subject: stopping openvpn via management interface. --- src/leap/eip/eipconnection.py | 19 ++++++++++--------- src/leap/eip/openvpnconnection.py | 30 +++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 18 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index fea830f3..f0e7861e 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -91,7 +91,8 @@ class EIPConnection(OpenVPNConnection): """ disconnects client """ - self._disconnect() + self.cleanup() + logger.debug("disconnect: clicked.") self.status.change_to(self.status.DISCONNECTED) def shutdown(self): @@ -141,14 +142,14 @@ class EIPConnection(OpenVPNConnection): # private methods # - def _disconnect(self): - """ - private method for disconnecting - """ - if self.subp is not None: - logger.debug('disconnecting...') - self.subp.terminate() - self.subp = None + #def _disconnect(self): + # """ + # private method for disconnecting + # """ + # if self.subp is not None: + # logger.debug('disconnecting...') + # self.subp.terminate() + # self.subp = None #def _is_alive(self): #""" diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 14839f6b..96df4f1d 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -174,17 +174,22 @@ to be triggered for each one of them. def cleanup(self): """ - terminates child subprocess + terminates openvpn child subprocess """ - # XXX we should send a quit process using management - # interface. if self.subp: - try: - self.subp.terminate() - except OSError: - logger.error('cannot terminate subprocess!' + self._stop() + RETCODE = self.subp.wait() + if RETCODE: + logger.error('cannot terminate subprocess! ' '(maybe openvpn still running?)') + def _stop(self): + """ + stop openvpn process + """ + logger.debug("disconnecting...") + self._send_command("signal SIGTERM\n") + # # management methods # @@ -221,9 +226,16 @@ to be triggered for each one of them. """ Read as much as available. Position seek pointer to end of stream """ - b = self.tn.read_eager() - while b: + try: b = self.tn.read_eager() + except EOFError: + logger.debug("Could not read from socket. Assuming it died.") + return + while b: + try: + b = self.tn.read_eager() + except EOFError: + logger.debug("Could not read from socket. Assuming it died.") def connected(self): """ -- cgit v1.2.3 From a6c587edad293996e4015876d7e59432d6a4e8ea Mon Sep 17 00:00:00 2001 From: antialias Date: Mon, 15 Oct 2012 12:28:54 -0400 Subject: attempts to stop exisiting instances of openvpn when discovered at start up. --- src/leap/eip/openvpnconnection.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 96df4f1d..d93bc40f 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -168,7 +168,9 @@ to be triggered for each one of them. for process in psutil.get_process_list(): if process.name == "openvpn": logger.debug('an openvpn instance is already running.') - raise eip_exceptions.OpenVPNAlreadyRunning + logger.debug('attempting to stop openvpn instance.') + if not self._stop(): + raise eip_exceptions.OpenVPNAlreadyRunning logger.debug('no openvpn instance found.') @@ -190,7 +192,34 @@ to be triggered for each one of them. logger.debug("disconnecting...") self._send_command("signal SIGTERM\n") - # + if self.subp: + return True + + #shutting openvpn failured + #try patching in old openvpn host and trying again + process = self._get_openvpn_process() + if process: + self.host = \ + process.cmdline[process.cmdline.index("--management") + 1] + self._send_command("signal SIGTERM\n") + + #make sure the process was terminated + process = self._get_openvpn_process() + if not process: + logger.debug("Exisiting OpenVPN Process Terminated") + return True + else: + logger.error("Unable to terminate exisiting OpenVPN Process.") + return False + + return True + + def _get_openvpn_process(self): + for process in psutil.get_process_list(): + if process.name == "openvpn": + return process + return None + # management methods # # XXX REVIEW-ME -- cgit v1.2.3 From e1dbfc454180a77ebb38ecae6244ac4abe6d0ac5 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 18 Oct 2012 09:30:53 +0900 Subject: catch cert verification errors and ask user for trust with a little helper function using gnutls --- src/leap/eip/checks.py | 27 ++++++++++++++++++++++----- src/leap/eip/exceptions.py | 11 +++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index f739c3e8..c704aef3 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -94,6 +94,7 @@ class ProviderCertChecker(object): raise NotImplementedError def is_there_provider_ca(self): + # XXX remove for generic build from leap import certs logger.debug('do we have provider_ca?') cacert_path = BRANDING.get('provider_ca_file', None) @@ -104,30 +105,46 @@ class ProviderCertChecker(object): logger.debug('True') return True - def is_https_working(self, uri=None, verify=True): + def is_https_working( + self, uri=None, verify=True, + autocacert=False): if uri is None: uri = self._get_root_uri() # XXX raise InsecureURI or something better - assert uri.startswith('https') - if verify is True and self.cacert is not None: + try: + assert uri.startswith('https') + except AssertionError: + raise AssertionError( + "uri passed should start with https") + if autocacert and verify is True and self.cacert is not None: logger.debug('verify cert: %s', self.cacert) verify = self.cacert logger.debug('is https working?') logger.debug('uri: %s (verify:%s)', uri, verify) try: self.fetcher.get(uri, verify=verify) + + except requests.exceptions.SSLError as exc: + logger.error("SSLError") + raise eipexceptions.HttpsBadCertError + + except requests.exceptions.ConnectionError: + logger.error('ConnectionError') + raise eipexceptions.HttpsNotSupported + except requests.exceptions.SSLError as exc: logger.warning('False! CERT VERIFICATION FAILED! ' '(this should be CRITICAL)') logger.warning('SSLError: %s', exc.message) # XXX RAISE! See #638 #raise eipexceptions.EIPBadCertError - # XXX get requests.exceptions.ConnectionError Errno 110 - # Connection timed out, and raise ours. else: logger.debug('True') return True + def get_certificate_fingerprint(self, domain): + pass + def check_new_cert_needed(self, skip_download=False, verify=True): logger.debug('is new cert needed?') if not self.is_cert_valid(do_raise=False): diff --git a/src/leap/eip/exceptions.py b/src/leap/eip/exceptions.py index 11bfd620..41eed77a 100644 --- a/src/leap/eip/exceptions.py +++ b/src/leap/eip/exceptions.py @@ -32,8 +32,10 @@ TODO: * gettext / i18n for user messages. """ +from leap.base.exceptions import LeapException +# This should inherit from LeapException class EIPClientError(Exception): """ base EIPClient exception @@ -99,6 +101,15 @@ class OpenVPNAlreadyRunning(EIPClientError): "Please close it before starting leap-client") +class HttpsNotSupported(LeapException): + message = "connection refused while accessing via https" + usermessage = "Server does not allow secure connections." + + +class HttpsBadCertError(LeapException): + message = "verification error on cert" + usermessage = "Server certificate could not be verified." + # # errors still needing some love # -- cgit v1.2.3 From 36957e9c926f4cc56cab383d99a8f82afc4b0302 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 19 Oct 2012 01:26:41 +0900 Subject: openvpn commands cleanup --- src/leap/eip/openvpnconnection.py | 81 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 37 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index d93bc40f..2ec7d08c 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -64,7 +64,7 @@ to be triggered for each one of them. #XXX workaround for signaling #the ui that we don't know how to #manage a connection error - self.with_errors = False + #self.with_errors = False self.command = None self.args = None @@ -180,41 +180,22 @@ to be triggered for each one of them. """ if self.subp: self._stop() - RETCODE = self.subp.wait() - if RETCODE: - logger.error('cannot terminate subprocess! ' - '(maybe openvpn still running?)') - def _stop(self): - """ - stop openvpn process - """ - logger.debug("disconnecting...") - self._send_command("signal SIGTERM\n") - - if self.subp: - return True + # XXX kali -- + # I think this will block if child process + # does not return. + # Maybe we can .poll() for a given + # interval and exit in any case. - #shutting openvpn failured - #try patching in old openvpn host and trying again - process = self._get_openvpn_process() - if process: - self.host = \ - process.cmdline[process.cmdline.index("--management") + 1] - self._send_command("signal SIGTERM\n") - - #make sure the process was terminated - process = self._get_openvpn_process() - if not process: - logger.debug("Exisiting OpenVPN Process Terminated") - return True - else: - logger.error("Unable to terminate exisiting OpenVPN Process.") - return False - - return True + RETCODE = self.subp.wait() + if RETCODE: + logger.error( + 'cannot terminate subprocess! ' + '(We might have left openvpn running)') def _get_openvpn_process(self): + # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] + # return plist[0] if plist else None for process in psutil.get_process_list(): if process.name == "openvpn": return process @@ -293,12 +274,7 @@ to be triggered for each one of them. self.connect_to_management() except eip_exceptions.MissingSocketError: logger.warning('missing management socket') - # This should only happen briefly during - # the first invocation. Race condition make - # the polling begin before management socket - # is ready return [] - #return self.make_error() try: if hasattr(self, 'tn'): self.tn.write(cmd + "\n") @@ -376,6 +352,37 @@ to be triggered for each one of them. """ return self._send_command("status 2") + def _stop(self): + """ + stop openvpn process + by sending SIGTERM to the management + interface + """ + logger.debug("disconnecting...") + self._send_command("signal SIGTERM\n") + + if self.subp: + return True + + #shutting openvpn failured + #try patching in old openvpn host and trying again + process = self._get_openvpn_process() + if process: + self.host = \ + process.cmdline[process.cmdline.index("--management") + 1] + self._send_command("signal SIGTERM\n") + + #make sure the process was terminated + process = self._get_openvpn_process() + if not process: + logger.debug("Existing OpenVPN Process Terminated") + return True + else: + logger.error("Unable to terminate existing OpenVPN Process.") + return False + + return True + # # parse info # -- cgit v1.2.3 From bc775969e2db31b892526b65a5037470a86b3882 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 19 Oct 2012 06:12:14 +0900 Subject: logic for cert validation widgets in wizard --- src/leap/eip/checks.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index c704aef3..560f7f53 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -142,9 +142,6 @@ class ProviderCertChecker(object): logger.debug('True') return True - def get_certificate_fingerprint(self, domain): - pass - def check_new_cert_needed(self, skip_download=False, verify=True): logger.debug('is new cert needed?') if not self.is_cert_valid(do_raise=False): @@ -347,7 +344,8 @@ class EIPConfigChecker(object): return True def fetch_definition(self, skip_download=False, - config=None, uri=None): + config=None, uri=None, + domain=None): """ fetches a definition file from server """ @@ -364,7 +362,8 @@ class EIPConfigChecker(object): if config is None: config = self.defaultprovider.config if uri is None: - domain = config.get('provider', None) + if not domain: + domain = config.get('provider', None) uri = self._get_provider_definition_uri(domain=domain) # FIXME! Pass ca path verify!!! -- cgit v1.2.3 From 2a01c969e0f8dff575007043996c3b0489e20e75 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 19 Oct 2012 08:18:34 +0900 Subject: download ca cert from provider --- src/leap/eip/checks.py | 53 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 560f7f53..e925e11c 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -4,13 +4,14 @@ import ssl import time import os -from gnutls import crypto +import gnutls.crypto #import netifaces #import ping import requests from leap import __branding as BRANDING from leap import certs +from leap.base import config as baseconfig from leap.base import constants as baseconstants from leap.base import providers from leap.eip import config as eipconfig @@ -54,18 +55,25 @@ class ProviderCertChecker(object): client certs and checking tls connection with provider. """ - def __init__(self, fetcher=requests): + def __init__(self, fetcher=requests, + domain=None): + self.fetcher = fetcher + self.domain = domain self.cacert = get_ca_cert() - def run_all(self, checker=None, skip_download=False, skip_verify=False): + def run_all( + self, checker=None, + skip_download=False, skip_verify=False): + if not checker: checker = self do_verify = not skip_verify logger.debug('do_verify: %s', do_verify) - # For MVS+ # checker.download_ca_cert() + + # For MVS+ # checker.download_ca_signature() # checker.get_ca_signatures() # checker.is_there_trust_path() @@ -77,9 +85,19 @@ class ProviderCertChecker(object): checker.is_https_working(verify=do_verify) checker.check_new_cert_needed(verify=do_verify) - def download_ca_cert(self): - # MVS+ - raise NotImplementedError + def download_ca_cert(self, uri=None, verify=True): + req = self.fetcher.get(uri, verify=verify) + req.raise_for_status() + + # should check domain exists + capath = self._get_ca_cert_path(self.domain) + with open(capath, 'w') as f: + f.write(req.content) + + def check_ca_cert_fingerprint( + self, hash_type="SHA256", + fingerprint=None): + pass def download_ca_signature(self): # MVS+ @@ -94,11 +112,12 @@ class ProviderCertChecker(object): raise NotImplementedError def is_there_provider_ca(self): - # XXX remove for generic build + # XXX modify for generic build from leap import certs logger.debug('do we have provider_ca?') cacert_path = BRANDING.get('provider_ca_file', None) if not cacert_path: + # XXX look from the domain logger.debug('False') return False self.cacert = certs.where(cacert_path) @@ -212,7 +231,7 @@ class ProviderCertChecker(object): certfile = self._get_client_cert_path() with open(certfile) as cf: cert_s = cf.read() - cert = crypto.X509Certificate(cert_s) + cert = gnutls.crypto.X509Certificate(cert_s) from_ = time.gmtime(cert.activation_time) to_ = time.gmtime(cert.expiration_time) return from_ < now() < to_ @@ -247,6 +266,10 @@ class ProviderCertChecker(object): raise return True + @property + def ca_cert_path(self): + return self._get_ca_cert_path() + def _get_root_uri(self): return u"https://%s/" % baseconstants.DEFAULT_PROVIDER @@ -258,6 +281,18 @@ class ProviderCertChecker(object): # MVS+ : get provider path return eipspecs.client_cert_path() + def _get_ca_cert_path(self, domain): + # XXX this folder path will be broken for win + # and this should be moved to eipspecs.ca_path + + capath = baseconfig.get_config_file( + 'cacert.pem', + folder='providers/%s/certs/ca' % domain) + folder, fname = os.path.split(capath) + if not os.path.isdir(folder): + mkdir_p(folder) + return capath + def write_cert(self, pemfile_content, to=None): folder, filename = os.path.split(to) if not os.path.isdir(folder): -- cgit v1.2.3 From 634030e5bba3fe7c2ea3632fff252a60b471487a Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 19 Oct 2012 09:05:14 +0900 Subject: ca cert fingerprint check + api cert verification --- src/leap/eip/checks.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index e925e11c..1c29dab1 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -10,10 +10,11 @@ import gnutls.crypto import requests from leap import __branding as BRANDING -from leap import certs +from leap import certs as leapcerts from leap.base import config as baseconfig from leap.base import constants as baseconstants from leap.base import providers +from leap.crypto import certs from leap.eip import config as eipconfig from leap.eip import constants as eipconstants from leap.eip import exceptions as eipexceptions @@ -46,7 +47,7 @@ reachable and testable as a whole. def get_ca_cert(): ca_file = BRANDING.get('provider_ca_file') if ca_file: - return certs.where(ca_file) + return leapcerts.where(ca_file) class ProviderCertChecker(object): @@ -97,7 +98,18 @@ class ProviderCertChecker(object): def check_ca_cert_fingerprint( self, hash_type="SHA256", fingerprint=None): - pass + ca_cert_path = self.ca_cert_path + ca_cert_fpr = certs.get_cert_fingerprint( + filepath=ca_cert_path) + return ca_cert_fpr == fingerprint + + def verify_api_https(self, uri): + assert uri.startswith('https://') + cacert = self.ca_cert_path + verify = cacert and cacert or True + req = self.fetcher.get(uri, verify=verify) + req.raise_for_status() + return True def download_ca_signature(self): # MVS+ @@ -268,7 +280,7 @@ class ProviderCertChecker(object): @property def ca_cert_path(self): - return self._get_ca_cert_path() + return self._get_ca_cert_path(self.domain) def _get_root_uri(self): return u"https://%s/" % baseconstants.DEFAULT_PROVIDER -- cgit v1.2.3 From b0be517ed8b2fb9dd0a38dad5b5c06741b6b9b09 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 19 Oct 2012 11:02:44 +0900 Subject: add bug number in log for #638 cases (domain name mismatch) --- src/leap/eip/checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 1c29dab1..74afd677 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -164,7 +164,7 @@ class ProviderCertChecker(object): raise eipexceptions.HttpsNotSupported except requests.exceptions.SSLError as exc: - logger.warning('False! CERT VERIFICATION FAILED! ' + logger.warning('BUG #638 CERT VERIFICATION FAILED! ' '(this should be CRITICAL)') logger.warning('SSLError: %s', exc.message) # XXX RAISE! See #638 -- cgit v1.2.3 From f791a83ce57cef7010da819d61e7f5132fa4611e Mon Sep 17 00:00:00 2001 From: kali Date: Sat, 20 Oct 2012 06:30:16 +0900 Subject: connecting page and changes to functions having to do with the default path to certs. --- src/leap/eip/checks.py | 67 +++++++++++++++++++++++++++++++++++++++----------- src/leap/eip/specs.py | 21 +++++++++++++--- 2 files changed, 69 insertions(+), 19 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 74afd677..635308bb 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -11,6 +11,7 @@ import requests from leap import __branding as BRANDING from leap import certs as leapcerts +from leap.base.auth import srpauth_protected from leap.base import config as baseconfig from leap.base import constants as baseconstants from leap.base import providers @@ -98,6 +99,17 @@ class ProviderCertChecker(object): def check_ca_cert_fingerprint( self, hash_type="SHA256", fingerprint=None): + """ + compares the fingerprint in + the ca cert with a string + we are passed + returns True if they are equal, False if not. + @param hash_type: digest function + @type hash_type: str + @param fingerprint: the fingerprint to compare with. + @type fingerprint: str (with : separator) + @rtype bool + """ ca_cert_path = self.ca_cert_path ca_cert_fpr = certs.get_cert_fingerprint( filepath=ca_cert_path) @@ -185,7 +197,8 @@ class ProviderCertChecker(object): return False def download_new_client_cert(self, uri=None, verify=True, - skip_download=False): + skip_download=False, + credentials=None): logger.debug('download new client cert') if skip_download: return True @@ -193,18 +206,34 @@ class ProviderCertChecker(object): uri = self._get_client_cert_uri() # XXX raise InsecureURI or something better assert uri.startswith('https') + if verify is True and self.cacert is not None: verify = self.cacert + + fgetfn = self.fetcher.get + + if credentials: + user, passwd = credentials + + @srpauth_protected(user, passwd) + def getfn(*args, **kwargs): + return fgetfn(*args, **kwargs) + + else: + # XXX use magic_srpauth decorator instead, + # merge with the branch above + def getfn(*args, **kwargs): + return fgetfn(*args, **kwargs) try: + # XXX FIXME!!!! # verify=verify # Workaround for #638. return to verification # when That's done!!! - - # XXX HOOK SRP here... - # will have to be more generic in the future. - req = self.fetcher.get(uri, verify=False) + #req = self.fetcher.get(uri, verify=False) + req = getfn(uri, verify=False) req.raise_for_status() + except requests.exceptions.SSLError: logger.warning('SSLError while fetching cert. ' 'Look below for stack trace.') @@ -283,23 +312,26 @@ class ProviderCertChecker(object): return self._get_ca_cert_path(self.domain) def _get_root_uri(self): - return u"https://%s/" % baseconstants.DEFAULT_PROVIDER + return u"https://%s/" % self.domain def _get_client_cert_uri(self): # XXX get the whole thing from constants - return "https://%s/1/cert" % (baseconstants.DEFAULT_PROVIDER) + return "https://%s/1/cert" % self.domain def _get_client_cert_path(self): # MVS+ : get provider path - return eipspecs.client_cert_path() + return eipspecs.client_cert_path(domain=self.domain) def _get_ca_cert_path(self, domain): # XXX this folder path will be broken for win # and this should be moved to eipspecs.ca_path + # XXX use baseconfig.get_provider_path(folder=Foo) + # !!! + capath = baseconfig.get_config_file( 'cacert.pem', - folder='providers/%s/certs/ca' % domain) + folder='providers/%s/keys/ca' % domain) folder, fname = os.path.split(capath) if not os.path.isdir(folder): mkdir_p(folder) @@ -321,16 +353,20 @@ class EIPConfigChecker(object): use run_all to run all checks. """ - def __init__(self, fetcher=requests): + def __init__(self, fetcher=requests, domain=None): # we do not want to accept too many # argument on init. # we want tests # to be explicitely run. + self.fetcher = fetcher - self.eipconfig = eipconfig.EIPConfig() - self.defaultprovider = providers.LeapProviderDefinition() - self.eipserviceconfig = eipconfig.EIPServiceConfig() + # if not domain, get from config + self.domain = domain + + self.eipconfig = eipconfig.EIPConfig(domain=domain) + self.defaultprovider = providers.LeapProviderDefinition(domain=domain) + self.eipserviceconfig = eipconfig.EIPServiceConfig(domain=domain) def run_all(self, checker=None, skip_download=False): """ @@ -421,13 +457,14 @@ class EIPConfigChecker(object): self.defaultprovider.save() def fetch_eip_service_config(self, skip_download=False, - config=None, uri=None): + config=None, uri=None, domain=None): if skip_download: return True if config is None: config = self.eipserviceconfig.config if uri is None: - domain = config.get('provider', None) + if not domain: + domain = config.get('provider', None) uri = self._get_eip_service_uri(domain=domain) self.eipserviceconfig.load(from_uri=uri, fetcher=self.fetcher) diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py index 1a670b0e..4014b7c9 100644 --- a/src/leap/eip/specs.py +++ b/src/leap/eip/specs.py @@ -8,7 +8,14 @@ PROVIDER_CA_CERT = __branding.get( 'provider_ca_file', 'testprovider-ca-cert.pem') -provider_ca_path = lambda: str(os.path.join( +provider_ca_path = lambda domain: str(os.path.join( + #baseconfig.get_default_provider_path(), + baseconfig.get_provider_path(domain), + 'keys', 'ca', + 'cacert.pem' +)) + +default_provider_ca_path = lambda: str(os.path.join( baseconfig.get_default_provider_path(), 'keys', 'ca', PROVIDER_CA_CERT @@ -17,7 +24,13 @@ provider_ca_path = lambda: str(os.path.join( PROVIDER_DOMAIN = __branding.get('provider_domain', 'testprovider.example.org') -client_cert_path = lambda: unicode(os.path.join( +client_cert_path = lambda domain: unicode(os.path.join( + baseconfig.get_provider_path(domain), + 'keys', 'client', + 'openvpn.pem' +)) + +default_client_cert_path = lambda: unicode(os.path.join( baseconfig.get_default_provider_path(), 'keys', 'client', 'openvpn.pem' @@ -46,11 +59,11 @@ eipconfig_spec = { }, 'openvpn_ca_certificate': { 'type': unicode, # path - 'default': provider_ca_path + 'default': default_provider_ca_path }, 'openvpn_client_certificate': { 'type': unicode, # path - 'default': client_cert_path + 'default': default_client_cert_path }, 'connect_on_login': { 'type': bool, -- cgit v1.2.3 From a85e488ed323ba35b9d12c5cc344bf06337a9a00 Mon Sep 17 00:00:00 2001 From: kali Date: Sat, 20 Oct 2012 07:13:22 +0900 Subject: add bypass for already trusted fingerprints --- src/leap/eip/checks.py | 1 - src/leap/eip/config.py | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 635308bb..b335b857 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -319,7 +319,6 @@ class ProviderCertChecker(object): return "https://%s/1/cert" % self.domain def _get_client_cert_path(self): - # MVS+ : get provider path return eipspecs.client_cert_path(domain=self.domain) def _get_ca_cert_path(self, domain): diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index ef0f52b4..1ce4a54e 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -78,8 +78,15 @@ def get_eip_gateway(): return placeholder if len(gateways) > 0: for gw in gateways: - if gw['name'] == primary_gateway: - hosts = gw['hosts'] + name = gw.get('name', None) + if not name: + return + + if name == primary_gateway: + hosts = gw.get('hosts', None) + if not hosts: + logger.error('no hosts') + return if len(hosts) > 0: return hosts[0] else: -- cgit v1.2.3 From 0060d3c74adce19fab7215b3788c5197cc05a9ae Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 24 Oct 2012 04:05:19 +0900 Subject: sign up branch ends by triggering eip connection still need to bind signals properly, and block on the validation process until we receive the "connected" signal. but the basic flow is working again, i.e, user should be able to remove the .config/leap folder and get all the needed info from the provider. --- src/leap/eip/checks.py | 37 +++++++++++++++++-------------------- src/leap/eip/config.py | 19 +++++++++++++------ src/leap/eip/eipconnection.py | 15 +++++++++++++-- src/leap/eip/openvpnconnection.py | 4 ++-- src/leap/eip/specs.py | 6 ++++-- 5 files changed, 49 insertions(+), 32 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index b335b857..44c8f234 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -45,7 +45,8 @@ reachable and testable as a whole. """ -def get_ca_cert(): +def get_branding_ca_cert(domain): + # XXX deprecated ca_file = BRANDING.get('provider_ca_file') if ca_file: return leapcerts.where(ca_file) @@ -62,7 +63,7 @@ class ProviderCertChecker(object): self.fetcher = fetcher self.domain = domain - self.cacert = get_ca_cert() + self.cacert = eipspecs.provider_ca_path(domain) def run_all( self, checker=None, @@ -84,7 +85,7 @@ class ProviderCertChecker(object): checker.is_there_provider_ca() # XXX FAKE IT!!! - checker.is_https_working(verify=do_verify) + checker.is_https_working(verify=do_verify, autocacert=True) checker.check_new_cert_needed(verify=do_verify) def download_ca_cert(self, uri=None, verify=True): @@ -136,17 +137,14 @@ class ProviderCertChecker(object): raise NotImplementedError def is_there_provider_ca(self): - # XXX modify for generic build - from leap import certs - logger.debug('do we have provider_ca?') - cacert_path = BRANDING.get('provider_ca_file', None) - if not cacert_path: - # XXX look from the domain - logger.debug('False') + if not self.cacert: return False - self.cacert = certs.where(cacert_path) - logger.debug('True') - return True + cacert_exists = os.path.isfile(self.cacert) + if cacert_exists: + logger.debug('True') + return True + logger.debug('False!') + return False def is_https_working( self, uri=None, verify=True, @@ -162,6 +160,7 @@ 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: @@ -169,18 +168,16 @@ class ProviderCertChecker(object): except requests.exceptions.SSLError as exc: logger.error("SSLError") - raise eipexceptions.HttpsBadCertError + # XXX RAISE! See #638 + #raise eipexceptions.HttpsBadCertError + logger.warning('BUG #638 CERT VERIFICATION FAILED! ' + '(this should be CRITICAL)') + logger.warning('SSLError: %s', exc.message) except requests.exceptions.ConnectionError: logger.error('ConnectionError') raise eipexceptions.HttpsNotSupported - except requests.exceptions.SSLError as exc: - logger.warning('BUG #638 CERT VERIFICATION FAILED! ' - '(this should be CRITICAL)') - logger.warning('SSLError: %s', exc.message) - # XXX RAISE! See #638 - #raise eipexceptions.EIPBadCertError else: logger.debug('True') return True diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 1ce4a54e..57e15c9e 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -110,6 +110,8 @@ 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) + # get user/group name # also from config. user = baseconfig.get_username() @@ -136,6 +138,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): logger.debug('setting eip gateway to %s', gw) opts.append(str(gw)) opts.append('1194') + #opts.append('80') opts.append('udp') opts.append('--tls-client') @@ -172,12 +175,15 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): opts.append('7777') # certs + client_cert_path = eipspecs.client_cert_path(provider) + ca_cert_path = eipspecs.provider_ca_path(provider) + 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. @@ -245,7 +251,7 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None, 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. @@ -253,8 +259,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) diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index f0e7861e..d4aeddf6 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -29,6 +29,7 @@ class EIPConnection(OpenVPNConnection): *args, **kwargs): self.settingsfile = kwargs.get('settingsfile', None) self.logfile = kwargs.get('logfile', None) + self.provider = kwargs.pop('provider', None) self.error_queue = Queue.Queue() @@ -38,8 +39,10 @@ class EIPConnection(OpenVPNConnection): checker_signals = kwargs.pop('checker_signals', None) self.checker_signals = checker_signals - self.provider_cert_checker = provider_cert_checker() - self.config_checker = config_checker() + # initialize checkers + self.provider_cert_checker = provider_cert_checker( + domain=self.provider) + self.config_checker = config_checker(domain=self.provider) host = eipconfig.get_socket_path() kwargs['host'] = host @@ -49,6 +52,14 @@ class EIPConnection(OpenVPNConnection): def has_errors(self): return True if self.error_queue.qsize() != 0 else False + def set_provider_domain(self, domain): + """ + sets the provider domain. + used from the first run wizard when we launch the run_checks + and connect process after having initialized the conductor. + """ + self.provider = domain + def run_checks(self, skip_download=False, skip_verify=False): """ run all eip checks previous to attempting a connection diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 2ec7d08c..d7c571bc 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -25,7 +25,6 @@ class OpenVPNConnection(Connection): """ def __init__(self, - #config_file=None, watcher_cb=None, debug=False, host=None, @@ -96,6 +95,7 @@ to be triggered for each one of them. # XXX check also for command-line --command flag try: command, args = eip_config.build_ovpn_command( + provider=self.provider, debug=self.debug, socket_path=self.host, ovpn_verbosity=self.ovpn_verbosity) @@ -115,7 +115,7 @@ to be triggered for each one of them. checks for correct permissions on vpn keys """ try: - eip_config.check_vpn_keys() + eip_config.check_vpn_keys(provider=self.provider) except eip_exceptions.EIPInitBadKeyFilePermError: logger.error('Bad VPN Keys permission!') # do nothing now diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py index 4014b7c9..84b2597d 100644 --- a/src/leap/eip/specs.py +++ b/src/leap/eip/specs.py @@ -4,6 +4,8 @@ import os from leap import __branding from leap.base import config as baseconfig +# XXX move provider stuff to base config + PROVIDER_CA_CERT = __branding.get( 'provider_ca_file', 'testprovider-ca-cert.pem') @@ -13,7 +15,7 @@ provider_ca_path = lambda domain: str(os.path.join( baseconfig.get_provider_path(domain), 'keys', 'ca', 'cacert.pem' -)) +)) if domain else None default_provider_ca_path = lambda: str(os.path.join( baseconfig.get_default_provider_path(), @@ -28,7 +30,7 @@ client_cert_path = lambda domain: unicode(os.path.join( baseconfig.get_provider_path(domain), 'keys', 'client', 'openvpn.pem' -)) +)) if domain else None default_client_cert_path = lambda: unicode(os.path.join( baseconfig.get_default_provider_path(), -- cgit v1.2.3 From ec888610b0a76cf5d0659e51f36265a4de42b8d7 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 24 Oct 2012 07:41:21 +0900 Subject: fix checks that were getting default provider domain var still --- src/leap/eip/checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 44c8f234..cd9d9972 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -495,7 +495,7 @@ class EIPConfigChecker(object): def _get_provider_definition_uri(self, domain=None, path=None): if domain is None: - domain = baseconstants.DEFAULT_PROVIDER + domain = self.domain or baseconstants.DEFAULT_PROVIDER if path is None: path = baseconstants.DEFINITION_EXPECTED_PATH uri = u"https://%s/%s" % (domain, path) @@ -504,7 +504,7 @@ class EIPConfigChecker(object): def _get_eip_service_uri(self, domain=None, path=None): if domain is None: - domain = baseconstants.DEFAULT_PROVIDER + domain = self.domain or baseconstants.DEFAULT_PROVIDER if path is None: path = eipconstants.EIP_SERVICE_EXPECTED_PATH uri = "https://%s/%s" % (domain, path) -- cgit v1.2.3 From 0590991d7777de473a7df21ed32e1fa7caa9cf4b Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 26 Oct 2012 00:12:08 +0900 Subject: user credentials saved on login/signup branches. cert request is using magick decorator that retrieves the certificates using srp. --- src/leap/eip/checks.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index cd9d9972..ae3634bc 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -11,7 +11,7 @@ import requests from leap import __branding as BRANDING from leap import certs as leapcerts -from leap.base.auth import srpauth_protected +from leap.base.auth import srpauth_protected, magick_srpauth from leap.base import config as baseconfig from leap.base import constants as baseconstants from leap.base import providers @@ -217,8 +217,7 @@ class ProviderCertChecker(object): return fgetfn(*args, **kwargs) else: - # XXX use magic_srpauth decorator instead, - # merge with the branch above + @magick_srpauth def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) try: -- cgit v1.2.3 From 593e4ba1ddf185d14f27c96ffb970fde7a3271fa Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 26 Oct 2012 02:04:34 +0900 Subject: fix systray context menu. Closes #761 --- src/leap/eip/eipconnection.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index d4aeddf6..acd40beb 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -106,11 +106,11 @@ class EIPConnection(OpenVPNConnection): logger.debug("disconnect: clicked.") self.status.change_to(self.status.DISCONNECTED) - def shutdown(self): - """ - shutdown and quit - """ - self.desired_con_state = self.status.DISCONNECTED + #def shutdown(self): + #""" + #shutdown and quit + #""" + #self.desired_con_state = self.status.DISCONNECTED def connection_state(self): """ @@ -121,10 +121,6 @@ class EIPConnection(OpenVPNConnection): def poll_connection_state(self): """ """ - # XXX this separation does not - # make sense anymore after having - # merged Connection and Manager classes. - # XXX GET RID OF THIS FUNCTION HERE! try: state = self.get_connection_state() except eip_exceptions.ConnectionRefusedError: @@ -132,7 +128,7 @@ class EIPConnection(OpenVPNConnection): logger.warning('connection refused') return if not state: - #logger.debug('no state') + logger.debug('no state') return (ts, status_step, ok, ip, remote) = state @@ -258,6 +254,7 @@ class EIPConnectionStatus(object): def get_leap_status(self): # XXX improve nomenclature leap_status = { + 0: 'disconnected', 1: 'connecting to gateway', 2: 'connecting to gateway', 3: 'authenticating', -- cgit v1.2.3 From b84007d8fec8c949ba4ac1d26695c710a210d797 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 8 Nov 2012 08:37:24 +0900 Subject: more careful error catching during registration. added a twisted server that fakes some of the provider interaction. --- src/leap/eip/checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index ae3634bc..9bd96a1c 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -212,12 +212,12 @@ class ProviderCertChecker(object): if credentials: user, passwd = credentials - @srpauth_protected(user, passwd) + @srpauth_protected(user, passwd, verify) def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) else: - @magick_srpauth + @magick_srpauth(verify) def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) try: -- cgit v1.2.3 From fc857d25025ea07d46a8c8f5ffd4fb2902a76c13 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 12 Nov 2012 10:04:09 +0900 Subject: fix cert fetching over https --- src/leap/eip/checks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 9bd96a1c..caaef2ea 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -212,11 +212,16 @@ class ProviderCertChecker(object): if credentials: user, passwd = credentials - @srpauth_protected(user, passwd, verify) + logger.debug('domain = %s', self.domain) + + @srpauth_protected(user, passwd, + server="https://%s" % self.domain, + verify=verify) def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) else: + # XXX FIXME fix decorated args @magick_srpauth(verify) def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) -- cgit v1.2.3 From 50ae1a415698af8aaa2fbed186a9f05037a9bfd9 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 12 Nov 2012 22:00:58 +0900 Subject: catch error when management interface is missing during shutdown --- src/leap/eip/openvpnconnection.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index d7c571bc..34f1e18b 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -179,7 +179,12 @@ to be triggered for each one of them. terminates openvpn child subprocess """ if self.subp: - self._stop() + try: + self._stop() + except eip_exceptions.ConnectionRefusedError: + logger.warning( + 'unable to send sigterm signal to openvpn: ' + 'connection refused.') # XXX kali -- # I think this will block if child process @@ -190,8 +195,8 @@ to be triggered for each one of them. RETCODE = self.subp.wait() if RETCODE: logger.error( - 'cannot terminate subprocess! ' - '(We might have left openvpn running)') + 'cannot terminate subprocess! Retcode %s' + '(We might have left openvpn running)' % RETCODE) def _get_openvpn_process(self): # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] -- cgit v1.2.3 From d2d2bbd96a44c347c248a7abb2ee72d7d728d79f Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 13 Nov 2012 20:51:22 +0900 Subject: remove sample service Ip for example.org --- src/leap/eip/tests/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/tests/data.py b/src/leap/eip/tests/data.py index 43df2013..f1d3b0bc 100644 --- a/src/leap/eip/tests/data.py +++ b/src/leap/eip/tests/data.py @@ -42,6 +42,6 @@ EIP_SAMPLE_SERVICE = { "name": "turkey", "label": {"en":"Ankara, Turkey"}, "capabilities": {}, - "hosts": ["94.103.43.4"]} + "hosts": ["192.0.43.10"]} ] } -- cgit v1.2.3 From d2dcf5a1060d60c451570349a6a06ad102d6924c Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 13 Nov 2012 21:54:04 +0900 Subject: fix missing provider parameter in leapconfig objects chain --- src/leap/eip/checks.py | 4 +++- src/leap/eip/config.py | 19 ++++++++++++------- src/leap/eip/eipconnection.py | 18 ++++++++++++++---- 3 files changed, 29 insertions(+), 12 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index caaef2ea..116c535e 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -450,6 +450,8 @@ class EIPConfigChecker(object): uri = self._get_provider_definition_uri(domain=domain) # FIXME! Pass ca path verify!!! + # BUG #638 + # FIXME FIXME FIXME self.defaultprovider.load( from_uri=uri, fetcher=self.fetcher, @@ -464,7 +466,7 @@ class EIPConfigChecker(object): config = self.eipserviceconfig.config if uri is None: if not domain: - domain = config.get('provider', None) + domain = self.domain or config.get('provider', None) uri = self._get_eip_service_uri(domain=domain) self.eipserviceconfig.load(from_uri=uri, fetcher=self.fetcher) diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 57e15c9e..42c00380 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -35,9 +35,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") @@ -53,15 +57,16 @@ def get_socket_path(): return socket_path -def get_eip_gateway(): +def get_eip_gateway(provider=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() + # XXX check for null on provider?? + + eipconfig = EIPConfig(domain=provider) eipconfig.load() conf = eipconfig.config @@ -69,7 +74,7 @@ def get_eip_gateway(): if not primary_gateway: return placeholder - eipserviceconfig = EIPServiceConfig() + eipserviceconfig = EIPServiceConfig(domain=provider) eipserviceconfig.load() eipsconf = eipserviceconfig.get_config() gateways = eipsconf.get('gateways', None) @@ -134,7 +139,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): # remote opts.append('--remote') - gw = get_eip_gateway() + gw = get_eip_gateway(provider=provider) logger.debug('setting eip gateway to %s', gw) opts.append(str(gw)) opts.append('1194') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index acd40beb..7828c864 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -30,6 +30,8 @@ class EIPConnection(OpenVPNConnection): self.settingsfile = kwargs.get('settingsfile', None) self.logfile = kwargs.get('logfile', None) self.provider = kwargs.pop('provider', None) + self._providercertchecker = provider_cert_checker + self._configchecker = config_checker self.error_queue = Queue.Queue() @@ -39,10 +41,7 @@ class EIPConnection(OpenVPNConnection): checker_signals = kwargs.pop('checker_signals', None) self.checker_signals = checker_signals - # initialize checkers - self.provider_cert_checker = provider_cert_checker( - domain=self.provider) - self.config_checker = config_checker(domain=self.provider) + self.init_checkers() host = eipconfig.get_socket_path() kwargs['host'] = host @@ -52,13 +51,24 @@ class EIPConnection(OpenVPNConnection): def has_errors(self): return True if self.error_queue.qsize() != 0 else False + def init_checkers(self): + # initialize checkers + self.provider_cert_checker = self._providercertchecker( + domain=self.provider) + self.config_checker = self._configchecker(domain=self.provider) + def set_provider_domain(self, domain): """ sets the provider domain. used from the first run wizard when we launch the run_checks and connect process after having initialized the conductor. """ + # This looks convoluted, right. + # We have to reinstantiate checkers cause we're passing + # the domain param that we did not know at the beginning + # (only for the firstrunwizard case) self.provider = domain + self.init_checkers() def run_checks(self, skip_download=False, skip_verify=False): """ -- cgit v1.2.3 From d24c7328fa845737dbb83d512e4b3f287634c4cc Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 14 Nov 2012 00:33:05 +0900 Subject: make tests pass + pep8 They were breaking mainly because I did not bother to have a pass over them to change the PROVIDER settings from the branding case. All good now, although much testing is yet needed and some refactor could be used. long live green tests! --- src/leap/eip/openvpnconnection.py | 17 ++++++++----- src/leap/eip/specs.py | 2 +- src/leap/eip/tests/data.py | 7 +++--- src/leap/eip/tests/test_checks.py | 37 ++++++++++++++++++++-------- src/leap/eip/tests/test_config.py | 19 ++++++++------ src/leap/eip/tests/test_eipconnection.py | 12 ++++++--- src/leap/eip/tests/test_openvpnconnection.py | 10 +++++--- 7 files changed, 70 insertions(+), 34 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 34f1e18b..4104bd0e 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -233,8 +233,8 @@ to be triggered for each one of them. #self.tn.read_until('ENTER PASSWORD:', 2) #self.tn.write(self.password + '\n') #self.tn.read_until('SUCCESS:', 2) - - self._seek_to_eof() + if self.tn: + self._seek_to_eof() return True def _seek_to_eof(self): @@ -364,7 +364,8 @@ to be triggered for each one of them. interface """ logger.debug("disconnecting...") - self._send_command("signal SIGTERM\n") + if self.connected(): + self._send_command("signal SIGTERM\n") if self.subp: return True @@ -373,9 +374,13 @@ to be triggered for each one of them. #try patching in old openvpn host and trying again process = self._get_openvpn_process() if process: - self.host = \ - process.cmdline[process.cmdline.index("--management") + 1] - self._send_command("signal SIGTERM\n") + logger.debug('process :%s' % process) + cmdline = process.cmdline + + if isinstance(cmdline, list): + _index = cmdline.index("--management") + self.host = cmdline[_index + 1] + self._send_command("signal SIGTERM\n") #make sure the process was terminated process = self._get_openvpn_process() diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py index 84b2597d..57e7537b 100644 --- a/src/leap/eip/specs.py +++ b/src/leap/eip/specs.py @@ -8,7 +8,7 @@ from leap.base import config as baseconfig PROVIDER_CA_CERT = __branding.get( 'provider_ca_file', - 'testprovider-ca-cert.pem') + 'cacert.pem') provider_ca_path = lambda domain: str(os.path.join( #baseconfig.get_default_provider_path(), diff --git a/src/leap/eip/tests/data.py b/src/leap/eip/tests/data.py index f1d3b0bc..cadf720e 100644 --- a/src/leap/eip/tests/data.py +++ b/src/leap/eip/tests/data.py @@ -1,11 +1,12 @@ from __future__ import unicode_literals import os -from leap import __branding +#from leap import __branding # sample data used in tests -PROVIDER = __branding.get('provider_domain') +#PROVIDER = __branding.get('provider_domain') +PROVIDER = "testprovider.example.org" EIP_SAMPLE_CONFIG = { "provider": "%s" % PROVIDER, @@ -15,7 +16,7 @@ EIP_SAMPLE_CONFIG = { "openvpn_ca_certificate": os.path.expanduser( "~/.config/leap/providers/" "%s/" - "keys/ca/testprovider-ca-cert.pem" % PROVIDER), + "keys/ca/cacert.pem" % PROVIDER), "openvpn_client_certificate": os.path.expanduser( "~/.config/leap/providers/" "%s/" diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py index 58ce473f..1d7bfc17 100644 --- a/src/leap/eip/tests/test_checks.py +++ b/src/leap/eip/tests/test_checks.py @@ -39,6 +39,8 @@ class NoLogRequestHandler: class EIPCheckTest(BaseLeapTest): __name__ = "eip_check_tests" + provider = "testprovider.example.org" + maxDiff = None def setUp(self): pass @@ -49,7 +51,7 @@ class EIPCheckTest(BaseLeapTest): # test methods are there, and can be called from run_all def test_checker_should_implement_check_methods(self): - checker = eipchecks.EIPConfigChecker() + checker = eipchecks.EIPConfigChecker(domain=self.provider) self.assertTrue(hasattr(checker, "check_default_eipconfig"), "missing meth") @@ -62,7 +64,7 @@ class EIPCheckTest(BaseLeapTest): "missing meth") def test_checker_should_actually_call_all_tests(self): - checker = eipchecks.EIPConfigChecker() + checker = eipchecks.EIPConfigChecker(domain=self.provider) mc = Mock() checker.run_all(checker=mc) @@ -79,7 +81,7 @@ class EIPCheckTest(BaseLeapTest): # test individual check methods def test_check_default_eipconfig(self): - checker = eipchecks.EIPConfigChecker() + checker = eipchecks.EIPConfigChecker(domain=self.provider) # no eip config (empty home) eipconfig_path = checker.eipconfig.filename self.assertFalse(os.path.isfile(eipconfig_path)) @@ -93,15 +95,15 @@ class EIPCheckTest(BaseLeapTest): # small workaround for evaluating home dirs correctly EIP_SAMPLE_CONFIG = copy.copy(testdata.EIP_SAMPLE_CONFIG) EIP_SAMPLE_CONFIG['openvpn_client_certificate'] = \ - eipspecs.client_cert_path() + eipspecs.client_cert_path(self.provider) EIP_SAMPLE_CONFIG['openvpn_ca_certificate'] = \ - eipspecs.provider_ca_path() + eipspecs.provider_ca_path(self.provider) self.assertEqual(deserialized, EIP_SAMPLE_CONFIG) # TODO: shold ALSO run validation methods. def test_check_is_there_default_provider(self): - checker = eipchecks.EIPConfigChecker() + checker = eipchecks.EIPConfigChecker(domain=self.provider) # we do dump a sample eip config, but lacking a # default provider entry. # This error will be possible catched in a different @@ -178,6 +180,7 @@ class EIPCheckTest(BaseLeapTest): class ProviderCertCheckerTest(BaseLeapTest): __name__ = "provider_cert_checker_tests" + provider = "testprovider.example.org" def setUp(self): pass @@ -226,13 +229,20 @@ class ProviderCertCheckerTest(BaseLeapTest): # test individual check methods + @unittest.skip def test_is_there_provider_ca(self): + # XXX commenting out this test. + # With the generic client this does not make sense, + # we should dump one there. + # or test conductor logic. checker = eipchecks.ProviderCertChecker() self.assertTrue( checker.is_there_provider_ca()) class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase, BaseLeapTest): + provider = "testprovider.example.org" + class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler): responses = { '/': ['OK', ''], @@ -292,12 +302,19 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase, BaseLeapTest): # same, but get cacert from leap.custom # XXX TODO! + @unittest.skip def test_download_new_client_cert(self): + # FIXME + # Magick srp decorator broken right now... + # Have to mock the decorator and inject something that + # can bypass the authentication + uri = "https://%s/client.cert" % (self.get_server()) cacert = where_cert('cacert.pem') - checker = eipchecks.ProviderCertChecker() + checker = eipchecks.ProviderCertChecker(domain=self.provider) + credentials = "testuser", "testpassword" self.assertTrue(checker.download_new_client_cert( - uri=uri, verify=cacert)) + credentials=credentials, uri=uri, verify=cacert)) # now download a malformed cert uri = "https://%s/badclient.cert" % (self.get_server()) @@ -305,7 +322,7 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase, BaseLeapTest): checker = eipchecks.ProviderCertChecker() with self.assertRaises(ValueError): self.assertTrue(checker.download_new_client_cert( - uri=uri, verify=cacert)) + credentials=credentials, uri=uri, verify=cacert)) # did we write cert to its path? clientcertfile = eipspecs.client_cert_path() @@ -339,7 +356,7 @@ class ProviderCertCheckerHTTPSTests(BaseHTTPSServerTestCase, BaseLeapTest): def test_check_new_cert_needed(self): # check: missing cert - checker = eipchecks.ProviderCertChecker() + checker = eipchecks.ProviderCertChecker(domain=self.provider) self.assertTrue(checker.check_new_cert_needed(skip_download=True)) # TODO check: malformed cert # TODO check: expired cert diff --git a/src/leap/eip/tests/test_config.py b/src/leap/eip/tests/test_config.py index 6759b522..50538240 100644 --- a/src/leap/eip/tests/test_config.py +++ b/src/leap/eip/tests/test_config.py @@ -18,13 +18,14 @@ from leap.util.fileutil import mkdir_p _system = platform.system() -PROVIDER = BRANDING.get('provider_domain') -PROVIDER_SHORTNAME = BRANDING.get('short_name') +#PROVIDER = BRANDING.get('provider_domain') +#PROVIDER_SHORTNAME = BRANDING.get('short_name') class EIPConfigTest(BaseLeapTest): __name__ = "eip_config_tests" + provider = "testprovider.example.org" def setUp(self): pass @@ -74,7 +75,8 @@ class EIPConfigTest(BaseLeapTest): args.append('--persist-tun') args.append('--persist-key') args.append('--remote') - args.append('%s' % eipconfig.get_eip_gateway()) + args.append('%s' % eipconfig.get_eip_gateway( + provider=self.provider)) # XXX get port!? args.append('1194') # XXX get proto @@ -103,23 +105,23 @@ class EIPConfigTest(BaseLeapTest): args.append(os.path.join( self.home, '.config', 'leap', 'providers', - '%s' % PROVIDER, + '%s' % self.provider, 'keys', 'client', 'openvpn.pem')) args.append('--key') args.append(os.path.join( self.home, '.config', 'leap', 'providers', - '%s' % PROVIDER, + '%s' % self.provider, 'keys', 'client', 'openvpn.pem')) args.append('--ca') args.append(os.path.join( self.home, '.config', 'leap', 'providers', - '%s' % PROVIDER, + '%s' % self.provider, 'keys', 'ca', - '%s-cacert.pem' % PROVIDER_SHORTNAME)) + 'cacert.pem')) return args # build command string @@ -141,7 +143,8 @@ class EIPConfigTest(BaseLeapTest): print 'vpnbin = ', vpnbin command, args = eipconfig.build_ovpn_command( do_pkexec_check=False, vpnbin=vpnbin, - socket_path="/tmp/test.socket") + socket_path="/tmp/test.socket", + provider=self.provider) self.assertEqual(command, self.home + '/bin/openvpn') self.assertEqual(args, self.get_expected_openvpn_args()) diff --git a/src/leap/eip/tests/test_eipconnection.py b/src/leap/eip/tests/test_eipconnection.py index bb643ae0..aefca36f 100644 --- a/src/leap/eip/tests/test_eipconnection.py +++ b/src/leap/eip/tests/test_eipconnection.py @@ -19,6 +19,8 @@ from leap.testing.basetest import BaseLeapTest _system = platform.system() +PROVIDER = "testprovider.example.org" + class NotImplementedError(Exception): pass @@ -27,6 +29,7 @@ class NotImplementedError(Exception): @patch('OpenVPNConnection._get_or_create_config') @patch('OpenVPNConnection._set_ovpn_command') class MockedEIPConnection(EIPConnection): + def _set_ovpn_command(self): self.command = "mock_command" self.args = [1, 2, 3] @@ -35,6 +38,7 @@ class MockedEIPConnection(EIPConnection): class EIPConductorTest(BaseLeapTest): __name__ = "eip_conductor_tests" + provider = PROVIDER def setUp(self): # XXX there's a conceptual/design @@ -51,8 +55,8 @@ class EIPConductorTest(BaseLeapTest): # XXX change to keys_checker invocation # (see config_checker) - keyfiles = (eipspecs.provider_ca_path(), - eipspecs.client_cert_path()) + keyfiles = (eipspecs.provider_ca_path(domain=self.provider), + eipspecs.client_cert_path(domain=self.provider)) for filepath in keyfiles: self.touch(filepath) self.chmod600(filepath) @@ -61,6 +65,7 @@ class EIPConductorTest(BaseLeapTest): # some methods mocked self.manager = Mock(name="openvpnmanager_mock") self.con = MockedEIPConnection() + self.con.provider = self.provider self.con.run_openvpn_checks() def tearDown(self): @@ -118,8 +123,9 @@ class EIPConductorTest(BaseLeapTest): self.con.status.CONNECTED) # disconnect + self.con.cleanup = Mock() self.con.disconnect() - self.con._disconnect.assert_called_once_with() + self.con.cleanup.assert_called_once_with() # new status should be disconnected # XXX this should evolve and check no errors diff --git a/src/leap/eip/tests/test_openvpnconnection.py b/src/leap/eip/tests/test_openvpnconnection.py index 61769f04..0f27facf 100644 --- a/src/leap/eip/tests/test_openvpnconnection.py +++ b/src/leap/eip/tests/test_openvpnconnection.py @@ -76,13 +76,17 @@ class OpenVPNConnectionTest(BaseLeapTest): # def test_detect_vpn(self): + # XXX review, not sure if captured all the logic + # while fixing. kali. openvpn_connection = openvpnconnection.OpenVPNConnection() + with patch.object(psutil, "get_process_list") as mocked_psutil: + mocked_process = Mock() + mocked_process.name = "openvpn" + mocked_psutil.return_value = [mocked_process] with self.assertRaises(eipexceptions.OpenVPNAlreadyRunning): - mocked_process = Mock() - mocked_process.name = "openvpn" - mocked_psutil.return_value = [mocked_process] openvpn_connection._check_if_running_instance() + openvpn_connection._check_if_running_instance() @unittest.skipIf(_system == "Windows", "lin/mac only") -- cgit v1.2.3 From 834b04317535cb6d18c02e3aa4d37b09fcf99868 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 14 Nov 2012 03:39:14 +0900 Subject: delete temp folder for management socket after client shutdown Close #742 --- src/leap/eip/openvpnconnection.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 4104bd0e..45a1847c 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -3,7 +3,9 @@ OpenVPN Connection """ from __future__ import (print_function) import logging +import os import psutil +import shutil import socket import time from functools import partial @@ -187,6 +189,7 @@ to be triggered for each one of them. 'connection refused.') # XXX kali -- + # XXX review-me # I think this will block if child process # does not return. # Maybe we can .poll() for a given @@ -198,6 +201,26 @@ to be triggered for each one of them. 'cannot terminate subprocess! Retcode %s' '(We might have left openvpn running)' % RETCODE) + self.cleanup_tempfiles() + + def cleanup_tempfiles(self): + """ + remove all temporal files + we might have left behind + """ + # if self.port is 'unix', we have + # created a temporal socket path that, under + # normal circumstances, we should be able to + # delete + + if self.port == "unix": + # I'm tempted to catch a generic exception here, + # but I prefer to let it crash so we can catch + # specific errors that right now I'm not able + # to think of. + logger.debug('cleaning socket file temp folder') + shutil.rmtree(os.path.split(self.host)[0]) + def _get_openvpn_process(self): # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] # return plist[0] if plist else None -- cgit v1.2.3 From 862014f68fce37318f77309a8f8f9782dabc60d2 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 19 Nov 2012 14:09:24 +0900 Subject: fix delete temporal files --- src/leap/eip/openvpnconnection.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 45a1847c..85874cfd 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -214,12 +214,14 @@ to be triggered for each one of them. # delete if self.port == "unix": - # I'm tempted to catch a generic exception here, - # but I prefer to let it crash so we can catch - # specific errors that right now I'm not able - # to think of. logger.debug('cleaning socket file temp folder') - shutil.rmtree(os.path.split(self.host)[0]) + + tempfolder = os.path.split(self.host)[0] + if os.path.isdir(tempfolder): + try: + shutil.rmtree(tempfolder) + except OSError: + logger.error('could not delete tmpfolder %s' % tempfolder) def _get_openvpn_process(self): # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] -- cgit v1.2.3 From a3ce61ea54b0b0f5c1ecd5904379e27cfec885b5 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 28 Nov 2012 02:43:25 +0900 Subject: call shutdown signal from sigint_handler --- src/leap/eip/openvpnconnection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 85874cfd..859378c0 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -390,9 +390,14 @@ to be triggered for each one of them. """ logger.debug("disconnecting...") if self.connected(): - self._send_command("signal SIGTERM\n") + try: + self._send_command("signal SIGTERM\n") + except socket.error: + logger.warning('management socket died') + return if self.subp: + # ??? return True #shutting openvpn failured -- cgit v1.2.3 From cd78d9d552977e8f8fb12b6a2ff56fda9c37bf35 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 7 Dec 2012 05:32:50 +0900 Subject: only remove management socket when shutting down Closes #1090 --- src/leap/eip/openvpnconnection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 859378c0..07bc628a 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -176,7 +176,7 @@ to be triggered for each one of them. logger.debug('no openvpn instance found.') - def cleanup(self): + def cleanup(self, shutdown=False): """ terminates openvpn child subprocess """ @@ -201,7 +201,8 @@ to be triggered for each one of them. 'cannot terminate subprocess! Retcode %s' '(We might have left openvpn running)' % RETCODE) - self.cleanup_tempfiles() + if shutdown: + self.cleanup_tempfiles() def cleanup_tempfiles(self): """ -- cgit v1.2.3 From 38cc1758240a3c64db387b0437dcf1517b52da15 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 10 Dec 2012 19:51:53 +0900 Subject: cleanup and rewrite eipconnection/openvpnconnection classes --- src/leap/eip/config.py | 2 +- src/leap/eip/eipconnection.py | 238 ++++++++++------ src/leap/eip/openvpnconnection.py | 472 +++++++++++++------------------ src/leap/eip/tests/test_eipconnection.py | 9 +- 4 files changed, 355 insertions(+), 366 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 42c00380..8e687bda 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -53,7 +53,7 @@ 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 diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index 7828c864..8751f643 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -5,6 +5,7 @@ from __future__ import (absolute_import,) import logging import Queue import sys +import time from leap.eip.checks import ProviderCertChecker from leap.eip.checks import EIPConfigChecker @@ -15,20 +16,143 @@ from leap.eip.openvpnconnection import OpenVPNConnection logger = logging.getLogger(name=__name__) -class EIPConnection(OpenVPNConnection): +class StatusMixIn(object): + + # a bunch of methods related with querying the connection + # state/status and displaying useful info. + # Needs to get clear on what is what, and + # separate functions. + # Should separate EIPConnectionStatus (self.status) + # from the OpenVPN state/status command and parsing. + + def connection_state(self): + """ + returns the current connection state + """ + return self.status.current + + def get_icon_name(self): + """ + get icon name from status object + """ + return self.status.get_state_icon() + + def get_leap_status(self): + return self.status.get_leap_status() + + def poll_connection_state(self): + """ + """ + try: + state = self.get_connection_state() + except eip_exceptions.ConnectionRefusedError: + # connection refused. might be not ready yet. + logger.warning('connection refused') + return + if not state: + logger.debug('no state') + return + (ts, status_step, + ok, ip, remote) = state + self.status.set_vpn_state(status_step) + status_step = self.status.get_readable_status() + return (ts, status_step, ok, ip, remote) + + def make_error(self): + """ + capture error and wrap it in an + understandable format + """ + # mostly a hack to display errors in the debug UI + # w/o breaking the polling. + #XXX get helpful error codes + self.with_errors = True + now = int(time.time()) + return '%s,LAUNCHER ERROR,ERROR,-,-' % now + + def state(self): + """ + Sends OpenVPN command: state + """ + state = self._send_command("state") + if not state: + return None + if isinstance(state, str): + return state + if isinstance(state, list): + if len(state) == 1: + return state[0] + else: + return state[-1] + + def vpn_status(self): + """ + OpenVPN command: status + """ + status = self._send_command("status") + return status + + def vpn_status2(self): + """ + OpenVPN command: last 2 statuses + """ + return self._send_command("status 2") + + # + # parse info as the UI expects + # + + def get_status_io(self): + status = self.vpn_status() + if isinstance(status, str): + lines = status.split('\n') + if isinstance(status, list): + lines = status + try: + (header, when, tun_read, tun_write, + tcp_read, tcp_write, auth_read) = tuple(lines) + except ValueError: + return None + + # XXX this will break with different locales I assume... + when_ts = time.strptime(when.split(',')[1], "%a %b %d %H:%M:%S %Y") + sep = ',' + # XXX clean up this! + tun_read = tun_read.split(sep)[1] + tun_write = tun_write.split(sep)[1] + tcp_read = tcp_read.split(sep)[1] + tcp_write = tcp_write.split(sep)[1] + auth_read = auth_read.split(sep)[1] + + # XXX this could be a named tuple. prettier. + return when_ts, (tun_read, tun_write, tcp_read, tcp_write, auth_read) + + def get_connection_state(self): + state = self.state() + if state is not None: + ts, status_step, ok, ip, remote = state.split(',') + ts = time.gmtime(float(ts)) + # XXX this could be a named tuple. prettier. + return ts, status_step, ok, ip, remote + + +class EIPConnection(OpenVPNConnection, StatusMixIn): """ + Aka conductor. Manages the execution of the OpenVPN process, auto starts, monitors the network connection, handles configuration, fixes leaky hosts, handles errors, etc. Status updates (connected, bandwidth, etc) are signaled to the GUI. """ + # XXX change name to EIPConductor ?? + def __init__(self, provider_cert_checker=ProviderCertChecker, config_checker=EIPConfigChecker, *args, **kwargs): - self.settingsfile = kwargs.get('settingsfile', None) - self.logfile = kwargs.get('logfile', None) + #self.settingsfile = kwargs.get('settingsfile', None) + #self.logfile = kwargs.get('logfile', None) self.provider = kwargs.pop('provider', None) self._providercertchecker = provider_cert_checker self._configchecker = config_checker @@ -48,11 +172,27 @@ class EIPConnection(OpenVPNConnection): super(EIPConnection, self).__init__(*args, **kwargs) + def connect(self): + """ + entry point for connection process + """ + # in OpenVPNConnection + self.try_openvpn_connection() + + def disconnect(self, shutdown=False): + """ + disconnects client + """ + self.terminate_openvpn_connection(shutdown=shutdown) + self.status.change_to(self.status.DISCONNECTED) + def has_errors(self): return True if self.error_queue.qsize() != 0 else False def init_checkers(self): - # initialize checkers + """ + initialize checkers + """ self.provider_cert_checker = self._providercertchecker( domain=self.provider) self.config_checker = self._configchecker(domain=self.provider) @@ -101,96 +241,6 @@ class EIPConnection(OpenVPNConnection): except Exception as exc: push_err(exc) - def connect(self): - """ - entry point for connection process - """ - #self.forget_errors() - self._try_connection() - - def disconnect(self): - """ - disconnects client - """ - self.cleanup() - logger.debug("disconnect: clicked.") - self.status.change_to(self.status.DISCONNECTED) - - #def shutdown(self): - #""" - #shutdown and quit - #""" - #self.desired_con_state = self.status.DISCONNECTED - - def connection_state(self): - """ - returns the current connection state - """ - return self.status.current - - def poll_connection_state(self): - """ - """ - try: - state = self.get_connection_state() - except eip_exceptions.ConnectionRefusedError: - # connection refused. might be not ready yet. - logger.warning('connection refused') - return - if not state: - logger.debug('no state') - return - (ts, status_step, - ok, ip, remote) = state - self.status.set_vpn_state(status_step) - status_step = self.status.get_readable_status() - return (ts, status_step, ok, ip, remote) - - def get_icon_name(self): - """ - get icon name from status object - """ - return self.status.get_state_icon() - - def get_leap_status(self): - return self.status.get_leap_status() - - # - # private methods - # - - #def _disconnect(self): - # """ - # private method for disconnecting - # """ - # if self.subp is not None: - # logger.debug('disconnecting...') - # self.subp.terminate() - # self.subp = None - - #def _is_alive(self): - #""" - #don't know yet - #""" - #pass - - def _connect(self): - """ - entry point for connection cascade methods. - """ - try: - conn_result = self._try_connection() - except eip_exceptions.UnrecoverableError as except_msg: - logger.error("FATAL: %s" % unicode(except_msg)) - conn_result = self.status.UNRECOVERABLE - - # XXX enqueue exceptions themselves instead? - except Exception as except_msg: - self.error_queue.append(except_msg) - logger.error("Failed Connection: %s" % - unicode(except_msg)) - return conn_result - class EIPConnectionStatus(object): """ diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 07bc628a..253f5056 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -7,7 +7,6 @@ import os import psutil import shutil import socket -import time from functools import partial logger = logging.getLogger(name=__name__) @@ -20,12 +19,123 @@ from leap.eip import config as eip_config from leap.eip import exceptions as eip_exceptions -class OpenVPNConnection(Connection): +class OpenVPNManagement(object): + + # TODO explain a little bit how management interface works + # and our telnet interface with support for unix sockets. + + """ + for more information, read openvpn management notes. + zcat `dpkg -L openvpn | grep management` + """ + + def _connect_to_management(self): + """ + Connect to openvpn management interface + """ + if hasattr(self, 'tn'): + self._close_management_socket() + self.tn = UDSTelnet(self.host, self.port) + + # XXX make password optional + # specially for win. we should generate + # the pass on the fly when invoking manager + # from conductor + + #self.tn.read_until('ENTER PASSWORD:', 2) + #self.tn.write(self.password + '\n') + #self.tn.read_until('SUCCESS:', 2) + if self.tn: + self._seek_to_eof() + return True + + def _close_management_socket(self, announce=True): + """ + Close connection to openvpn management interface + """ + logger.debug('closing socket') + if announce: + self.tn.write("quit\n") + self.tn.read_all() + self.tn.get_socket().close() + del self.tn + + def _seek_to_eof(self): + """ + Read as much as available. Position seek pointer to end of stream + """ + try: + b = self.tn.read_eager() + except EOFError: + logger.debug("Could not read from socket. Assuming it died.") + return + while b: + try: + b = self.tn.read_eager() + except EOFError: + logger.debug("Could not read from socket. Assuming it died.") + + def _send_command(self, cmd): + """ + Send a command to openvpn and return response as list + """ + if not self.connected(): + try: + self._connect_to_management() + except eip_exceptions.MissingSocketError: + logger.warning('missing management socket') + return [] + try: + if hasattr(self, 'tn'): + self.tn.write(cmd + "\n") + except socket.error: + logger.error('socket error') + self._close_management_socket(announce=False) + return [] + buf = self.tn.read_until(b"END", 2) + self._seek_to_eof() + blist = buf.split('\r\n') + if blist[-1].startswith('END'): + del blist[-1] + return blist + else: + return [] + + def _send_short_command(self, cmd): + """ + parse output from commands that are + delimited by "success" instead + """ + if not self.connected(): + self.connect() + self.tn.write(cmd + "\n") + # XXX not working? + buf = self.tn.read_until(b"SUCCESS", 2) + self._seek_to_eof() + blist = buf.split('\r\n') + return blist + + # + # random maybe useful vpn commands + # + + def pid(self): + #XXX broken + return self._send_short_command("pid") + + +class OpenVPNConnection(Connection, OpenVPNManagement): """ All related to invocation - of the openvpn binary + of the openvpn binary. + It's extended by EIPConnection. """ + # XXX Inheriting from Connection was an early design idea + # but currently that's an empty class. + # We can get rid of that if we don't use it for sharing + # state with other leap modules. + def __init__(self, watcher_cb=None, debug=False, @@ -34,24 +144,21 @@ class OpenVPNConnection(Connection): password=None, *args, **kwargs): """ - :param config_file: configuration file to read from :param watcher_cb: callback to be \ called for each line in watched stdout :param signal_map: dictionary of signal names and callables \ to be triggered for each one of them. - :type config_file: str :type watcher_cb: function :type signal_map: dict """ #XXX FIXME #change watcher_cb to line_observer + # XXX if not host: raise ImproperlyConfigured logger.debug('init openvpn connection') self.debug = debug - # XXX if not host: raise ImproperlyConfigured self.ovpn_verbosity = kwargs.get('ovpn_verbosity', None) - #self.config_file = config_file self.watcher_cb = watcher_cb #self.signal_maps = signal_maps @@ -62,21 +169,13 @@ to be triggered for each one of them. self.port = None self.proto = None - #XXX workaround for signaling - #the ui that we don't know how to - #manage a connection error - #self.with_errors = False - self.command = None self.args = None # XXX get autostart from config self.autostart = True - # - # management init methods - # - + # management interface init self.host = host if isinstance(port, str) and port.isdigit(): port = int(port) @@ -88,101 +187,47 @@ to be triggered for each one of them. self.password = password def run_openvpn_checks(self): + """ + runs check needed before launching + openvpn subprocess. will raise if errors found. + """ logger.debug('running openvpn checks') + # XXX I think that "check_if_running" should be called + # from try openvpn connection instead. -- kali. + # let's prepare tests for that before changing it... self._check_if_running_instance() self._set_ovpn_command() self._check_vpn_keys() - def _set_ovpn_command(self): - # XXX check also for command-line --command flag - try: - command, args = eip_config.build_ovpn_command( - provider=self.provider, - debug=self.debug, - socket_path=self.host, - ovpn_verbosity=self.ovpn_verbosity) - except eip_exceptions.EIPNoPolkitAuthAgentAvailable: - command = args = None - raise - except eip_exceptions.EIPNoPkexecAvailable: - command = args = None - raise - - # XXX if not command, signal error. - self.command = command - self.args = args - - def _check_vpn_keys(self): - """ - checks for correct permissions on vpn keys - """ - try: - eip_config.check_vpn_keys(provider=self.provider) - except eip_exceptions.EIPInitBadKeyFilePermError: - logger.error('Bad VPN Keys permission!') - # do nothing now - # and raise the rest ... - - def _launch_openvpn(self): - """ - invocation of openvpn binaries in a subprocess. - """ - #XXX TODO: - #deprecate watcher_cb, - #use _only_ signal_maps instead - - logger.debug('_launch_openvpn called') - if self.watcher_cb is not None: - linewrite_callback = self.watcher_cb - else: - #XXX get logger instead - linewrite_callback = lambda line: print('watcher: %s' % line) - - # the partial is not - # being applied now because we're not observing the process - # stdout like we did in the early stages. but I leave it - # here since it will be handy for observing patterns in the - # thru-the-manager updates (with regex) - observers = (linewrite_callback, - partial(lambda con_status, line: None, self.status)) - subp, watcher = spawn_and_watch_process( - self.command, - self.args, - observers=observers) - self.subp = subp - self.watcher = watcher - - def _try_connection(self): + def try_openvpn_connection(self): """ attempts to connect """ + # XXX should make public method if self.command is None: raise eip_exceptions.EIPNoCommandError if self.subp is not None: logger.debug('cowardly refusing to launch subprocess again') + # XXX this is not returning ???!! + # FIXME -- so it's calling it all the same!! self._launch_openvpn() - def _check_if_running_instance(self): + def connected(self): """ - check if openvpn is already running + Returns True if connected + rtype: bool """ - for process in psutil.get_process_list(): - if process.name == "openvpn": - logger.debug('an openvpn instance is already running.') - logger.debug('attempting to stop openvpn instance.') - if not self._stop(): - raise eip_exceptions.OpenVPNAlreadyRunning - - logger.debug('no openvpn instance found.') + # XXX make a property + return hasattr(self, 'tn') - def cleanup(self, shutdown=False): + def terminate_openvpn_connection(self, shutdown=False): """ terminates openvpn child subprocess """ if self.subp: try: - self._stop() + self._stop_openvpn() except eip_exceptions.ConnectionRefusedError: logger.warning( 'unable to send sigterm signal to openvpn: ' @@ -202,9 +247,9 @@ to be triggered for each one of them. '(We might have left openvpn running)' % RETCODE) if shutdown: - self.cleanup_tempfiles() + self._cleanup_tempfiles() - def cleanup_tempfiles(self): + def _cleanup_tempfiles(self): """ remove all temporal files we might have left behind @@ -224,172 +269,89 @@ to be triggered for each one of them. except OSError: logger.error('could not delete tmpfolder %s' % tempfolder) - def _get_openvpn_process(self): - # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] - # return plist[0] if plist else None + # checks + + def _check_if_running_instance(self): + """ + check if openvpn is already running + """ for process in psutil.get_process_list(): if process.name == "openvpn": - return process - return None - - # management methods - # - # XXX REVIEW-ME - # REFACTOR INFO: (former "manager". - # Can we move to another - # base class to test independently?) - # - - #def forget_errors(self): - #logger.debug('forgetting errors') - #self.with_errors = False - - def connect_to_management(self): - """Connect to openvpn management interface""" - #logger.debug('connecting socket') - if hasattr(self, 'tn'): - self.close() - self.tn = UDSTelnet(self.host, self.port) - - # XXX make password optional - # specially for win. we should generate - # the pass on the fly when invoking manager - # from conductor + logger.debug('an openvpn instance is already running.') + logger.debug('attempting to stop openvpn instance.') + if not self._stop_openvpn(): + raise eip_exceptions.OpenVPNAlreadyRunning - #self.tn.read_until('ENTER PASSWORD:', 2) - #self.tn.write(self.password + '\n') - #self.tn.read_until('SUCCESS:', 2) - if self.tn: - self._seek_to_eof() - return True + logger.debug('no openvpn instance found.') - def _seek_to_eof(self): - """ - Read as much as available. Position seek pointer to end of stream - """ + def _set_ovpn_command(self): try: - b = self.tn.read_eager() - except EOFError: - logger.debug("Could not read from socket. Assuming it died.") - return - while b: - try: - b = self.tn.read_eager() - except EOFError: - logger.debug("Could not read from socket. Assuming it died.") - - def connected(self): - """ - Returns True if connected - rtype: bool - """ - return hasattr(self, 'tn') + command, args = eip_config.build_ovpn_command( + provider=self.provider, + debug=self.debug, + socket_path=self.host, + ovpn_verbosity=self.ovpn_verbosity) + except eip_exceptions.EIPNoPolkitAuthAgentAvailable: + command = args = None + raise + except eip_exceptions.EIPNoPkexecAvailable: + command = args = None + raise - def close(self, announce=True): - """ - Close connection to openvpn management interface - """ - logger.debug('closing socket') - if announce: - self.tn.write("quit\n") - self.tn.read_all() - self.tn.get_socket().close() - del self.tn + # XXX if not command, signal error. + self.command = command + self.args = args - def _send_command(self, cmd): + def _check_vpn_keys(self): """ - Send a command to openvpn and return response as list + checks for correct permissions on vpn keys """ - if not self.connected(): - try: - self.connect_to_management() - except eip_exceptions.MissingSocketError: - logger.warning('missing management socket') - return [] try: - if hasattr(self, 'tn'): - self.tn.write(cmd + "\n") - except socket.error: - logger.error('socket error') - self.close(announce=False) - return [] - buf = self.tn.read_until(b"END", 2) - self._seek_to_eof() - blist = buf.split('\r\n') - if blist[-1].startswith('END'): - del blist[-1] - return blist - else: - return [] - - def _send_short_command(self, cmd): - """ - parse output from commands that are - delimited by "success" instead - """ - if not self.connected(): - self.connect() - self.tn.write(cmd + "\n") - # XXX not working? - buf = self.tn.read_until(b"SUCCESS", 2) - self._seek_to_eof() - blist = buf.split('\r\n') - return blist - - # - # useful vpn commands - # - - def pid(self): - #XXX broken - return self._send_short_command("pid") + eip_config.check_vpn_keys(provider=self.provider) + except eip_exceptions.EIPInitBadKeyFilePermError: + logger.error('Bad VPN Keys permission!') + # do nothing now + # and raise the rest ... - def make_error(self): - """ - capture error and wrap it in an - understandable format - """ - #XXX get helpful error codes - self.with_errors = True - now = int(time.time()) - return '%s,LAUNCHER ERROR,ERROR,-,-' % now + # starting and stopping openvpn subprocess - def state(self): + def _launch_openvpn(self): """ - OpenVPN command: state + invocation of openvpn binaries in a subprocess. """ - state = self._send_command("state") - if not state: - return None - if isinstance(state, str): - return state - if isinstance(state, list): - if len(state) == 1: - return state[0] - else: - return state[-1] + #XXX TODO: + #deprecate watcher_cb, + #use _only_ signal_maps instead - def vpn_status(self): - """ - OpenVPN command: status - """ - #logger.debug('status called') - status = self._send_command("status") - return status + logger.debug('_launch_openvpn called') + if self.watcher_cb is not None: + linewrite_callback = self.watcher_cb + else: + #XXX get logger instead + linewrite_callback = lambda line: print('watcher: %s' % line) - def vpn_status2(self): - """ - OpenVPN command: last 2 statuses - """ - return self._send_command("status 2") + # the partial is not + # being applied now because we're not observing the process + # stdout like we did in the early stages. but I leave it + # here since it will be handy for observing patterns in the + # thru-the-manager updates (with regex) + observers = (linewrite_callback, + partial(lambda con_status, line: None, self.status)) + subp, watcher = spawn_and_watch_process( + self.command, + self.args, + observers=observers) + self.subp = subp + self.watcher = watcher - def _stop(self): + def _stop_openvpn(self): """ stop openvpn process by sending SIGTERM to the management interface """ - logger.debug("disconnecting...") + # XXX method a bit too long, split + logger.debug("terminating openvpn process...") if self.connected(): try: self._send_command("signal SIGTERM\n") @@ -424,38 +386,10 @@ to be triggered for each one of them. return True - # - # parse info - # - - def get_status_io(self): - status = self.vpn_status() - if isinstance(status, str): - lines = status.split('\n') - if isinstance(status, list): - lines = status - try: - (header, when, tun_read, tun_write, - tcp_read, tcp_write, auth_read) = tuple(lines) - except ValueError: - return None - - when_ts = time.strptime(when.split(',')[1], "%a %b %d %H:%M:%S %Y") - sep = ',' - # XXX cleanup! - tun_read = tun_read.split(sep)[1] - tun_write = tun_write.split(sep)[1] - tcp_read = tcp_read.split(sep)[1] - tcp_write = tcp_write.split(sep)[1] - auth_read = auth_read.split(sep)[1] - - # XXX this could be a named tuple. prettier. - return when_ts, (tun_read, tun_write, tcp_read, tcp_write, auth_read) - - def get_connection_state(self): - state = self.state() - if state is not None: - ts, status_step, ok, ip, remote = state.split(',') - ts = time.gmtime(float(ts)) - # XXX this could be a named tuple. prettier. - return ts, status_step, ok, ip, remote + def _get_openvpn_process(self): + # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] + # return plist[0] if plist else None + for process in psutil.get_process_list(): + if process.name == "openvpn": + return process + return None diff --git a/src/leap/eip/tests/test_eipconnection.py b/src/leap/eip/tests/test_eipconnection.py index aefca36f..4ee5ae30 100644 --- a/src/leap/eip/tests/test_eipconnection.py +++ b/src/leap/eip/tests/test_eipconnection.py @@ -123,9 +123,14 @@ class EIPConductorTest(BaseLeapTest): self.con.status.CONNECTED) # disconnect - self.con.cleanup = Mock() + self.con.terminate_openvpn_connection = Mock() self.con.disconnect() - self.con.cleanup.assert_called_once_with() + self.con.terminate_openvpn_connection.assert_called_once_with( + shutdown=False) + self.con.terminate_openvpn_connection = Mock() + self.con.disconnect(shutdown=True) + self.con.terminate_openvpn_connection.assert_called_once_with( + shutdown=True) # new status should be disconnected # XXX this should evolve and check no errors -- cgit v1.2.3 From 53fa2c134ab2c96376276aa1c0ed74db0aaba218 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 10 Dec 2012 23:20:09 +0900 Subject: get cipher config from eip-service --- src/leap/eip/checks.py | 7 ++++++- src/leap/eip/config.py | 57 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 12 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 116c535e..a876eea1 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -427,6 +427,7 @@ class EIPConfigChecker(object): return True def fetch_definition(self, skip_download=False, + force_download=False, config=None, uri=None, domain=None): """ @@ -459,6 +460,7 @@ class EIPConfigChecker(object): self.defaultprovider.save() def fetch_eip_service_config(self, skip_download=False, + force_download=False, config=None, uri=None, domain=None): if skip_download: return True @@ -469,7 +471,10 @@ class EIPConfigChecker(object): domain = self.domain or config.get('provider', None) uri = self._get_eip_service_uri(domain=domain) - self.eipserviceconfig.load(from_uri=uri, fetcher=self.fetcher) + self.eipserviceconfig.load( + from_uri=uri, + fetcher=self.fetcher, + force_download=force_download) self.eipserviceconfig.save() def check_complete_eip_config(self, config=None): diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 8e687bda..1fe0530a 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -5,6 +5,7 @@ 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 @@ -57,30 +58,30 @@ def get_socket_path(): return socket_path -def get_eip_gateway(provider=None): +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" - # XXX check for null on provider?? + null_check(eipconfig, "eipconfig") + null_check(eipserviceconfig, "eipserviceconfig") + + PLACEHOLDER = "testprovider.example.org" - eipconfig = EIPConfig(domain=provider) - eipconfig.load() conf = eipconfig.config + eipsconf = eipserviceconfig.config primary_gateway = conf.get('primary_gateway', None) if not primary_gateway: - return placeholder + return PLACEHOLDER - eipserviceconfig = EIPServiceConfig(domain=provider) - 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: name = gw.get('name', None) @@ -100,6 +101,26 @@ def get_eip_gateway(provider=None): '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") + opts = [] + if 'openvpn_configuration' in eipsconf: + config = eipserviceconfig.openvpn_configuration + for key, value in config.items(): + if key in ALLOWED_KEYS and value is not None: + # I humbly think we should sanitize this + # input against `valid` openvpn settings. -- kali. + opts.append(['--%s' % key, value]) + return opts + + def build_ovpn_options(daemon=False, socket_path=None, **kwargs): """ build a list of options @@ -116,6 +137,10 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): # 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. @@ -139,9 +164,19 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): # remote opts.append('--remote') - gw = get_eip_gateway(provider=provider) + + gw = get_eip_gateway(eipconfig=eipconfig, + eipserviceconfig=eipserviceconfig) logger.debug('setting eip gateway to %s', gw) opts.append(str(gw)) + + # get ciphers + ciphers = get_cipher_options( + eipserviceconfig=eipserviceconfig) + for cipheropt in ciphers: + opts.append(str(cipheropt)) + + # get port/protocol from eipservice too opts.append('1194') #opts.append('80') opts.append('udp') -- cgit v1.2.3 From 04d423e2a89034dfb86fe305108162fd2a696079 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 12 Dec 2012 03:29:31 +0900 Subject: tests for openvpn options and make the rest of tests pass after some changes in this branch (dirtyness in config files) --- src/leap/eip/checks.py | 2 +- src/leap/eip/config.py | 30 ++++++++----- src/leap/eip/specs.py | 7 +++ src/leap/eip/tests/test_checks.py | 6 +++ src/leap/eip/tests/test_config.py | 93 +++++++++++++++++++++++++++++++++++---- 5 files changed, 117 insertions(+), 21 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index a876eea1..8d615b94 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -502,7 +502,7 @@ class EIPConfigChecker(object): return self.eipconfig.exists() def _dump_default_eipconfig(self): - self.eipconfig.save() + self.eipconfig.save(force=True) def _get_provider_definition_uri(self, domain=None, path=None): if domain is None: diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 1fe0530a..e40d2785 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -1,6 +1,7 @@ import logging import os import platform +import re import tempfile from leap import __branding as BRANDING @@ -110,14 +111,18 @@ def get_cipher_options(eipserviceconfig=None): 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.openvpn_configuration + config = eipserviceconfig.config.get( + "openvpn_configuration", {}) for key, value in config.items(): if key in ALLOWED_KEYS and value is not None: - # I humbly think we should sanitize this - # input against `valid` openvpn settings. -- kali. - opts.append(['--%s' % key, value]) + 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 @@ -162,7 +167,9 @@ 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(eipconfig=eipconfig, @@ -170,12 +177,6 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): logger.debug('setting eip gateway to %s', gw) opts.append(str(gw)) - # get ciphers - ciphers = get_cipher_options( - eipserviceconfig=eipserviceconfig) - for cipheropt in ciphers: - opts.append(str(cipheropt)) - # get port/protocol from eipservice too opts.append('1194') #opts.append('80') @@ -185,6 +186,13 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): 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) diff --git a/src/leap/eip/specs.py b/src/leap/eip/specs.py index 57e7537b..cf5d5359 100644 --- a/src/leap/eip/specs.py +++ b/src/leap/eip/specs.py @@ -119,6 +119,13 @@ eipservice_config_spec = { "label": {"en":"west"}, "capabilities": {}, "hosts": ["1.2.3.4", "1.2.3.5"]}] + }, + 'openvpn_configuration': { + 'type': dict, + 'default': { + "auth": None, + "cipher": None, + "tls-cipher": None} } } } diff --git a/src/leap/eip/tests/test_checks.py b/src/leap/eip/tests/test_checks.py index 1d7bfc17..ab11037a 100644 --- a/src/leap/eip/tests/test_checks.py +++ b/src/leap/eip/tests/test_checks.py @@ -25,6 +25,7 @@ from leap.eip.tests import data as testdata from leap.testing.basetest import BaseLeapTest from leap.testing.https_server import BaseHTTPSServerTestCase from leap.testing.https_server import where as where_cert +from leap.util.fileutil import mkdir_f class NoLogRequestHandler: @@ -118,6 +119,7 @@ class EIPCheckTest(BaseLeapTest): sampleconfig = copy.copy(testdata.EIP_SAMPLE_CONFIG) sampleconfig['provider'] = None eipcfg_path = checker.eipconfig.filename + mkdir_f(eipcfg_path) with open(eipcfg_path, 'w') as fp: json.dump(sampleconfig, fp) #with self.assertRaises(eipexceptions.EIPMissingDefaultProvider): @@ -138,6 +140,8 @@ class EIPCheckTest(BaseLeapTest): def test_fetch_definition(self): with patch.object(requests, "get") as mocked_get: mocked_get.return_value.status_code = 200 + mocked_get.return_value.headers = { + 'last-modified': "Wed Dec 12 12:12:12 GMT 2012"} mocked_get.return_value.json = DEFAULT_PROVIDER_DEFINITION checker = eipchecks.EIPConfigChecker(fetcher=requests) sampleconfig = testdata.EIP_SAMPLE_CONFIG @@ -156,6 +160,8 @@ class EIPCheckTest(BaseLeapTest): def test_fetch_eip_service_config(self): with patch.object(requests, "get") as mocked_get: mocked_get.return_value.status_code = 200 + mocked_get.return_value.headers = { + 'last-modified': "Wed Dec 12 12:12:12 GMT 2012"} mocked_get.return_value.json = testdata.EIP_SAMPLE_SERVICE checker = eipchecks.EIPConfigChecker(fetcher=requests) sampleconfig = testdata.EIP_SAMPLE_CONFIG diff --git a/src/leap/eip/tests/test_config.py b/src/leap/eip/tests/test_config.py index 50538240..404d543f 100644 --- a/src/leap/eip/tests/test_config.py +++ b/src/leap/eip/tests/test_config.py @@ -1,3 +1,4 @@ +from collections import OrderedDict import json import os import platform @@ -10,7 +11,7 @@ except ImportError: #from leap.base import constants #from leap.eip import config as eip_config -from leap import __branding as BRANDING +#from leap import __branding as BRANDING 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 @@ -47,11 +48,21 @@ class EIPConfigTest(BaseLeapTest): open(tfile, 'wb').close() os.chmod(tfile, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) - def write_sample_eipservice(self): + def write_sample_eipservice(self, vpnciphers=False, extra_vpnopts=None): conf = eipconfig.EIPServiceConfig() folder, f = os.path.split(conf.filename) if not os.path.isdir(folder): mkdir_p(folder) + if vpnciphers: + openvpnconfig = OrderedDict({ + "auth": "SHA1", + "cipher": "AES-128-CBC", + "tls-cipher": "DHE-RSA-AES128-SHA"}) + if extra_vpnopts: + for k, v in extra_vpnopts.items(): + openvpnconfig[k] = v + EIP_SAMPLE_SERVICE['openvpn_configuration'] = openvpnconfig + with open(conf.filename, 'w') as fd: fd.write(json.dumps(EIP_SAMPLE_SERVICE)) @@ -63,8 +74,13 @@ class EIPConfigTest(BaseLeapTest): with open(conf.filename, 'w') as fd: fd.write(json.dumps(EIP_SAMPLE_CONFIG)) - def get_expected_openvpn_args(self): + def get_expected_openvpn_args(self, with_openvpn_ciphers=False): args = [] + eipconf = eipconfig.EIPConfig(domain=self.provider) + eipconf.load() + eipsconf = eipconfig.EIPServiceConfig(domain=self.provider) + eipsconf.load() + username = self.get_username() groupname = self.get_groupname() @@ -75,8 +91,10 @@ class EIPConfigTest(BaseLeapTest): args.append('--persist-tun') args.append('--persist-key') args.append('--remote') + args.append('%s' % eipconfig.get_eip_gateway( - provider=self.provider)) + eipconfig=eipconf, + eipserviceconfig=eipsconf)) # XXX get port!? args.append('1194') # XXX get proto @@ -85,6 +103,14 @@ class EIPConfigTest(BaseLeapTest): args.append('--remote-cert-tls') args.append('server') + if with_openvpn_ciphers: + CIPHERS = [ + "--tls-cipher", "DHE-RSA-AES128-SHA", + "--cipher", "AES-128-CBC", + "--auth", "SHA1"] + for opt in CIPHERS: + args.append(opt) + args.append('--user') args.append(username) args.append('--group') @@ -139,14 +165,63 @@ class EIPConfigTest(BaseLeapTest): from leap.util.fileutil import which path = os.environ['PATH'] vpnbin = which('openvpn', path=path) - print 'path =', path - print 'vpnbin = ', vpnbin - command, args = eipconfig.build_ovpn_command( + #print 'path =', path + #print 'vpnbin = ', vpnbin + vpncommand, vpnargs = eipconfig.build_ovpn_command( + do_pkexec_check=False, vpnbin=vpnbin, + socket_path="/tmp/test.socket", + provider=self.provider) + self.assertEqual(vpncommand, self.home + '/bin/openvpn') + self.assertEqual(vpnargs, self.get_expected_openvpn_args()) + + def test_build_ovpn_command_openvpnoptions(self): + self.touch_exec() + + from leap.eip import config as eipconfig + from leap.util.fileutil import which + path = os.environ['PATH'] + vpnbin = which('openvpn', path=path) + + self.write_sample_eipconfig() + + # regular run, everything normal + self.write_sample_eipservice(vpnciphers=True) + vpncommand, vpnargs = eipconfig.build_ovpn_command( + do_pkexec_check=False, vpnbin=vpnbin, + socket_path="/tmp/test.socket", + provider=self.provider) + self.assertEqual(vpncommand, self.home + '/bin/openvpn') + expected = self.get_expected_openvpn_args( + with_openvpn_ciphers=True) + self.assertEqual(vpnargs, expected) + + # bad options -- illegal options + self.write_sample_eipservice( + vpnciphers=True, + # WE ONLY ALLOW vpn options in auth, cipher, tls-cipher + extra_vpnopts={"notallowedconfig": "badvalue"}) + vpncommand, vpnargs = eipconfig.build_ovpn_command( + do_pkexec_check=False, vpnbin=vpnbin, + socket_path="/tmp/test.socket", + provider=self.provider) + self.assertEqual(vpncommand, self.home + '/bin/openvpn') + expected = self.get_expected_openvpn_args( + with_openvpn_ciphers=True) + self.assertEqual(vpnargs, expected) + + # bad options -- illegal chars + self.write_sample_eipservice( + vpnciphers=True, + # WE ONLY ALLOW A-Z09\- + extra_vpnopts={"cipher": "AES-128-CBC;FOOTHING"}) + vpncommand, vpnargs = eipconfig.build_ovpn_command( do_pkexec_check=False, vpnbin=vpnbin, socket_path="/tmp/test.socket", provider=self.provider) - self.assertEqual(command, self.home + '/bin/openvpn') - self.assertEqual(args, self.get_expected_openvpn_args()) + self.assertEqual(vpncommand, self.home + '/bin/openvpn') + expected = self.get_expected_openvpn_args( + with_openvpn_ciphers=True) + self.assertEqual(vpnargs, expected) if __name__ == "__main__": -- cgit v1.2.3 From 490cde9c33039c2c5b16d929d6f8bb8e8f06f430 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 5 Dec 2012 23:50:08 +0900 Subject: tests for firstrun/wizard --- src/leap/eip/tests/test_eipconnection.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/leap/eip') diff --git a/src/leap/eip/tests/test_eipconnection.py b/src/leap/eip/tests/test_eipconnection.py index 4ee5ae30..1f1605ed 100644 --- a/src/leap/eip/tests/test_eipconnection.py +++ b/src/leap/eip/tests/test_eipconnection.py @@ -66,6 +66,11 @@ class EIPConductorTest(BaseLeapTest): self.manager = Mock(name="openvpnmanager_mock") self.con = MockedEIPConnection() self.con.provider = self.provider + + # XXX watch out. This sometimes is throwing the following error: + # NoSuchProcess: process no longer exists (pid=6571) + # because of a bad implementation of _check_if_running_instance + self.con.run_openvpn_checks() def tearDown(self): -- cgit v1.2.3 From 52aa909c23bff688e2a164dca546e4a493e72fe4 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 6 Dec 2012 00:55:07 +0900 Subject: cleanup lingering temporal files --- src/leap/eip/tests/test_eipconnection.py | 17 ++++++++++++++++- src/leap/eip/tests/test_openvpnconnection.py | 21 +++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/tests/test_eipconnection.py b/src/leap/eip/tests/test_eipconnection.py index 1f1605ed..163f8d45 100644 --- a/src/leap/eip/tests/test_eipconnection.py +++ b/src/leap/eip/tests/test_eipconnection.py @@ -1,6 +1,8 @@ +import glob import logging import platform -import os +#import os +import shutil logging.basicConfig() logger = logging.getLogger(name=__name__) @@ -74,8 +76,18 @@ class EIPConductorTest(BaseLeapTest): self.con.run_openvpn_checks() def tearDown(self): + pass + + def doCleanups(self): + super(BaseLeapTest, self).doCleanups() + self.cleanupSocketDir() del self.con + def cleanupSocketDir(self): + ptt = ('/tmp/leap-tmp*') + for tmpdir in glob.glob(ptt): + shutil.rmtree(tmpdir) + # # tests # @@ -86,6 +98,7 @@ class EIPConductorTest(BaseLeapTest): """ con = self.con self.assertEqual(con.autostart, True) + # XXX moar! def test_ovpn_command(self): """ @@ -103,6 +116,7 @@ class EIPConductorTest(BaseLeapTest): # needed to run tests. (roughly 3 secs for this only) # We should modularize and inject Mocks on more places. + oldcon = self.con del(self.con) config_checker = Mock() self.con = MockedEIPConnection(config_checker=config_checker) @@ -112,6 +126,7 @@ class EIPConductorTest(BaseLeapTest): skip_download=False) # XXX test for cert_checker also + self.con = oldcon # connect/disconnect calls diff --git a/src/leap/eip/tests/test_openvpnconnection.py b/src/leap/eip/tests/test_openvpnconnection.py index 0f27facf..f7493567 100644 --- a/src/leap/eip/tests/test_openvpnconnection.py +++ b/src/leap/eip/tests/test_openvpnconnection.py @@ -58,16 +58,27 @@ class OpenVPNConnectionTest(BaseLeapTest): def setUp(self): # XXX this will have to change for win, host=localhost host = eipconfig.get_socket_path() + self.host = host self.manager = MockedOpenVPNConnection(host=host) def tearDown(self): + pass + + def doCleanups(self): + super(BaseLeapTest, self).doCleanups() + self.cleanupSocketDir() + + def cleanupSocketDir(self): # remove the socket folder. # XXX only if posix. in win, host is localhost, so nothing # has to be done. - if self.manager.host: - folder, fpath = os.path.split(self.manager.host) - assert folder.startswith('/tmp/leap-tmp') # safety check - shutil.rmtree(folder) + if self.host: + folder, fpath = os.path.split(self.host) + try: + assert folder.startswith('/tmp/leap-tmp') # safety check + shutil.rmtree(folder) + except: + self.fail("could not remove temp file") del self.manager @@ -108,12 +119,14 @@ class OpenVPNConnectionTest(BaseLeapTest): self.assertEqual(self.manager.port, 7777) def test_port_types_init(self): + oldmanager = self.manager self.manager = MockedOpenVPNConnection(port="42") self.assertEqual(self.manager.port, 42) self.manager = MockedOpenVPNConnection() self.assertEqual(self.manager.port, "unix") self.manager = MockedOpenVPNConnection(port="bad") self.assertEqual(self.manager.port, None) + self.manager = oldmanager def test_uds_telnet_called_on_connect(self): self.manager.connect_to_management() -- cgit v1.2.3 From f671412ebd4f2ce0dd9948cb8821f1d6d8ac7d9b Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 12 Dec 2012 07:21:51 +0900 Subject: parse new service format --- src/leap/eip/config.py | 27 +++++++++-------- src/leap/eip/specs.py | 37 ++++++++++++---------- src/leap/eip/tests/data.py | 33 +++++++++++--------- src/leap/eip/tests/test_config.py | 64 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 113 insertions(+), 48 deletions(-) (limited to 'src/leap/eip') 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() -- cgit v1.2.3 From 4984f2c966d11f529a2a8b722814b748b6a524d2 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 12 Dec 2012 09:16:53 +0900 Subject: changed some values in new style eipconfig --- src/leap/eip/checks.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 8d615b94..92964a9d 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -242,7 +242,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: @@ -303,6 +305,10 @@ class ProviderCertChecker(object): if len(certparts) > 1: cert_s = sep + certparts[1] ssl.PEM_cert_to_DER_cert(cert_s) + except ValueError: + # valid_pemfile raises a value error if not BEGIN_CERTIFICATE in + # there... + return False except: # XXX raise proper exception raise -- cgit v1.2.3 From d71e05fdefa7cb9699804bc93adba97921ca923f Mon Sep 17 00:00:00 2001 From: kali Date: Sat, 15 Dec 2012 02:23:36 +0900 Subject: workaround for not-yet-valid certs skipping valid_from ts on cert --- src/leap/eip/checks.py | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 92964a9d..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: @@ -278,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): """ @@ -292,27 +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 ValueError: - # valid_pemfile raises a value error if not BEGIN_CERTIFICATE in - # there... - return False - 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): -- cgit v1.2.3 From f104e834c96c9ec10a465bda46ef05e87ea32516 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 18 Dec 2012 03:45:23 +0900 Subject: Fix parsing of timestamps in a locate independent way Close #772 --- src/leap/eip/eipconnection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index 8751f643..27734f80 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -7,6 +7,8 @@ import Queue import sys import time +from dateutil.parser import parse as dateparse + from leap.eip.checks import ProviderCertChecker from leap.eip.checks import EIPConfigChecker from leap.eip import config as eipconfig @@ -114,8 +116,7 @@ class StatusMixIn(object): except ValueError: return None - # XXX this will break with different locales I assume... - when_ts = time.strptime(when.split(',')[1], "%a %b %d %H:%M:%S %Y") + when_ts = dateparse(when.split(',')[1]).timetuple() sep = ',' # XXX clean up this! tun_read = tun_read.split(sep)[1] -- cgit v1.2.3 From 75057e55828accb62beef1f73364edd82a75ed30 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 18 Dec 2012 05:54:50 +0900 Subject: do not pass CA.crt to checks for https also skip temporary errors when previous openvpn process vanishes. --- src/leap/eip/checks.py | 3 +-- src/leap/eip/openvpnconnection.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index d7f4402b..4afba8b6 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -84,8 +84,7 @@ class ProviderCertChecker(object): # For MVS checker.is_there_provider_ca() - # XXX FAKE IT!!! - checker.is_https_working(verify=do_verify, autocacert=True) + checker.is_https_working(verify=do_verify, autocacert=False) checker.check_new_cert_needed(verify=do_verify) def download_ca_cert(self, uri=None, verify=True): diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 253f5056..59ba44f0 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -275,12 +275,16 @@ to be triggered for each one of them. """ check if openvpn is already running """ - for process in psutil.get_process_list(): - if process.name == "openvpn": - logger.debug('an openvpn instance is already running.') - logger.debug('attempting to stop openvpn instance.') - if not self._stop_openvpn(): - raise eip_exceptions.OpenVPNAlreadyRunning + try: + for process in psutil.get_process_list(): + if process.name == "openvpn": + logger.debug('an openvpn instance is already running.') + logger.debug('attempting to stop openvpn instance.') + if not self._stop_openvpn(): + raise eip_exceptions.OpenVPNAlreadyRunning + + except psutil.error.NoSuchProcess: + logger.debug('detected a process which died. passing.') logger.debug('no openvpn instance found.') -- cgit v1.2.3 From 8808c0e2cba1660515fab4a2931221c3bda7e093 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 18 Dec 2012 20:59:51 +0900 Subject: do not assume that we were the only ones launching openvpn --- src/leap/eip/openvpnconnection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 59ba44f0..c2dc71a6 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -374,8 +374,9 @@ to be triggered for each one of them. logger.debug('process :%s' % process) cmdline = process.cmdline - if isinstance(cmdline, list): - _index = cmdline.index("--management") + manag_flag = "--management" + if isinstance(cmdline, list) and manag_flag in cmdline: + _index = cmdline.index(manag_flag) self.host = cmdline[_index + 1] self._send_command("signal SIGTERM\n") -- cgit v1.2.3 From 20f779b644a551bf56cb735868c55cd50d7c3610 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 18 Dec 2012 21:07:06 +0900 Subject: catch gnutls error while validating pemfile --- src/leap/eip/checks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 4afba8b6..65596d1c 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -293,7 +293,11 @@ class ProviderCertChecker(object): certfile = self._get_client_cert_path() with open(certfile) as cf: cert_s = cf.read() - valid = certs.can_load_cert_and_pkey(cert_s) + try: + valid = certs.can_load_cert_and_pkey(cert_s) + except certs.BadCertError: + logger.warning("Not valid pemfile") + valid = False return valid @property -- cgit v1.2.3 From e98c3cc5fad75bea038dc67238e5ce85d701b1e1 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 20 Dec 2012 02:50:52 +0900 Subject: fix broken tests --- src/leap/eip/checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 65596d1c..9ae6e5f5 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -278,8 +278,8 @@ class ProviderCertChecker(object): to_ = time.gmtime(cert.expiration_time) # FIXME BUG ON LEAP_CLI, certs are not valid on gmtime # See #1153 - #return from_ < now() < to_ - return now() < to_ + return from_ < now() < to_ + #return now() < to_ def is_valid_pemfile(self, cert_s=None): """ -- cgit v1.2.3 From 656419216f15bfb1859ba850d2d9c9d143034e23 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 8 Jan 2013 00:32:21 +0900 Subject: doc polishing --- src/leap/eip/openvpnconnection.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index c2dc71a6..eb3b5ec0 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -276,6 +276,7 @@ to be triggered for each one of them. check if openvpn is already running """ try: + #FIXME this gives DeprecationWarning for process in psutil.get_process_list(): if process.name == "openvpn": logger.debug('an openvpn instance is already running.') -- cgit v1.2.3 From e35eb606faef1ccd06201a0b38a462375426cedd Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 7 Jan 2013 21:10:41 +0900 Subject: Working OSX installer workflow. Using platypus for installer. Working installer at 17.6MB compressed. --- src/leap/eip/config.py | 31 +++++++++++++++++++++++++++---- src/leap/eip/eipconnection.py | 2 +- src/leap/eip/openvpnconnection.py | 7 ++++--- 3 files changed, 32 insertions(+), 8 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 48e6e9a7..f82049d3 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -211,7 +211,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): # XXX take them from the config object. ourplatform = platform.system() - if ourplatform in ("Linux", "Mac"): + if ourplatform in ("Linux", "Darwin"): opts.append('--management') if socket_path is None: @@ -229,6 +229,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): 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(client_cert_path) opts.append('--key') @@ -260,9 +261,11 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None, use_pkexec = True ovpn = None + _plat = platform.system() + # XXX get use_pkexec from config instead. - if platform.system() == "Linux" and use_pkexec and do_pkexec_check: + if _plat == "Linux" and use_pkexec and do_pkexec_check: # check for both pkexec # AND a suitable authentication @@ -282,8 +285,17 @@ 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 _plat == "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: @@ -299,7 +311,18 @@ 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 _plat == "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! + #import ipdb;ipdb.set_trace() + #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(provider=None): diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index 27734f80..540e7558 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -52,7 +52,7 @@ class StatusMixIn(object): logger.warning('connection refused') return if not state: - logger.debug('no state') + #logger.debug('no state') return (ts, status_step, ok, ip, remote) = state diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index eb3b5ec0..b36b0b16 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -83,7 +83,7 @@ class OpenVPNManagement(object): try: self._connect_to_management() except eip_exceptions.MissingSocketError: - logger.warning('missing management socket') + #logger.warning('missing management socket') return [] try: if hasattr(self, 'tn'): @@ -329,11 +329,12 @@ to be triggered for each one of them. #use _only_ signal_maps instead logger.debug('_launch_openvpn called') + logger.debug('watcher_cb: %s' % self.watcher_cb) if self.watcher_cb is not None: linewrite_callback = self.watcher_cb else: #XXX get logger instead - linewrite_callback = lambda line: print('watcher: %s' % line) + linewrite_callback = lambda line: logger.debug('watcher: %s' % line) # the partial is not # being applied now because we're not observing the process @@ -341,7 +342,7 @@ to be triggered for each one of them. # here since it will be handy for observing patterns in the # thru-the-manager updates (with regex) observers = (linewrite_callback, - partial(lambda con_status, line: None, self.status)) + partial(lambda con_status, line: linewrite_callback, self.status)) subp, watcher = spawn_and_watch_process( self.command, self.args, -- cgit v1.2.3 From 460dd7c20408958dda1ca8e77050e9af334b558f Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 9 Jan 2013 05:02:21 +0900 Subject: fix from_login --- src/leap/eip/checks.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 9ae6e5f5..a002e2d9 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -276,10 +276,7 @@ class ProviderCertChecker(object): cert = gnutls.crypto.X509Certificate(cert_s) from_ = time.gmtime(cert.activation_time) to_ = time.gmtime(cert.expiration_time) - # 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): """ -- cgit v1.2.3 From 289722fe0eda46c8f5fbbecb84c8a0fbbe36a15f Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 9 Jan 2013 05:41:12 +0900 Subject: add resolvconf option --- src/leap/eip/config.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index f82049d3..6a19633d 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -18,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 @@ -210,8 +212,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", "Darwin"): + 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: @@ -219,11 +226,14 @@ 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": + opts.append("--up") + opts.append("/etc/openvpn/update-resolv-conf") + opts.append("--down") + opts.append("/etc/openvpn/update-resolv-conf") # certs client_cert_path = eipspecs.client_cert_path(provider) @@ -261,11 +271,9 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None, use_pkexec = True ovpn = None - _plat = platform.system() - # XXX get use_pkexec from config instead. - if _plat == "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 @@ -286,9 +294,8 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None, command.append('pkexec') - if vpnbin is None: - if _plat == "Darwin": + if _platform == "Darwin": # XXX Should hardcode our installed path # /Applications/LEAPClient.app/Contents/Resources/openvpn.leap openvpn_bin = "openvpn.leap" @@ -311,13 +318,12 @@ def build_ovpn_command(debug=False, do_pkexec_check=True, vpnbin=None, # XXX check len and raise proper error - if _plat == "Darwin": + 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! - #import ipdb;ipdb.set_trace() - #XXX get openvpn log path from debug flags + # XXX get openvpn log path from debug flags _command.append('--log') _command.append('/tmp/leap_openvpn.log') return ["osascript", ["-e", OSX_ASADMIN % ' '.join(_command)]] -- cgit v1.2.3 From a5b4b7020daebbcb25c016cf1821818b71a2e457 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 9 Jan 2013 06:23:45 +0900 Subject: more missed strings to be translated plus initial translation. --- src/leap/eip/exceptions.py | 55 +++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/exceptions.py b/src/leap/eip/exceptions.py index 41eed77a..c127a58f 100644 --- a/src/leap/eip/exceptions.py +++ b/src/leap/eip/exceptions.py @@ -33,6 +33,7 @@ TODO: """ from leap.base.exceptions import LeapException +from leap.util.translations import translate # This should inherit from LeapException @@ -62,53 +63,69 @@ class Warning(EIPClientError): class EIPNoPolkitAuthAgentAvailable(CriticalError): message = "No polkit authentication agent could be found" - usermessage = ("We could not find any authentication " - "agent in your system.
" - "Make sure you have " - "polkit-gnome-authentication-agent-1 " - "running and try again.") + usermessage = translate( + "EIPErrors", + "We could not find any authentication " + "agent in your system.
" + "Make sure you have " + "polkit-gnome-authentication-agent-1 " + "running and try again.") class EIPNoPkexecAvailable(Warning): message = "No pkexec binary found" - usermessage = ("We could not find pkexec in your " - "system.
Do you want to try " - "setuid workaround? " - "(DOES NOTHING YET)") + usermessage = translate( + "EIPErrors", + "We could not find pkexec in your " + "system.
Do you want to try " + "setuid workaround? " + "(DOES NOTHING YET)") failfirst = True class EIPNoCommandError(EIPClientError): message = "no suitable openvpn command found" - usermessage = ("No suitable openvpn command found. " - "
(Might be a permissions problem)") + usermessage = translate( + "EIPErrors", + "No suitable openvpn command found. " + "
(Might be a permissions problem)") class EIPBadCertError(Warning): # XXX this should be critical and fail close message = "cert verification failed" - usermessage = "there is a problem with provider certificate" + usermessage = translate( + "EIPErrors", + "there is a problem with provider certificate") class LeapBadConfigFetchedError(Warning): message = "provider sent a malformed json file" - usermessage = "an error occurred during configuratio of leap services" + usermessage = translate( + "EIPErrors", + "an error occurred during configuratio of leap services") class OpenVPNAlreadyRunning(EIPClientError): message = "Another OpenVPN Process is already running." - usermessage = ("Another OpenVPN Process has been detected." - "Please close it before starting leap-client") + usermessage = translate( + "EIPErrors", + "Another OpenVPN Process has been detected." + "Please close it before starting leap-client") class HttpsNotSupported(LeapException): message = "connection refused while accessing via https" - usermessage = "Server does not allow secure connections." + usermessage = translate( + "EIPErrors", + "Server does not allow secure connections") class HttpsBadCertError(LeapException): message = "verification error on cert" - usermessage = "Server certificate could not be verified." + usermessage = translate( + "EIPErrors", + "Server certificate could not be verified") # # errors still needing some love @@ -117,7 +134,9 @@ class HttpsBadCertError(LeapException): class EIPInitNoKeyFileError(CriticalError): message = "No vpn keys found in the expected path" - usermessage = "We could not find your eip certs in the expected path" + usermessage = translate( + "EIPErrors", + "We could not find your eip certs in the expected path") class EIPInitBadKeyFilePermError(Warning): -- cgit v1.2.3 From f55dcd717a946651492142ed198853b1c667254b Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 10 Jan 2013 02:00:21 +0900 Subject: renamed connection page --- src/leap/eip/checks.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index a002e2d9..b14e5dd3 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -164,13 +164,12 @@ class ProviderCertChecker(object): try: self.fetcher.get(uri, verify=verify) - except requests.exceptions.SSLError as exc: + except requests.exceptions.SSLError: # as exc: logger.error("SSLError") - # XXX RAISE! See #638 - #raise eipexceptions.HttpsBadCertError - logger.warning('BUG #638 CERT VERIFICATION FAILED! ' - '(this should be CRITICAL)') - logger.warning('SSLError: %s', exc.message) + raise eipexceptions.HttpsBadCertError + #logger.warning('BUG #638 CERT VERIFICATION FAILED! ' + #'(this should be CRITICAL)') + #logger.warning('SSLError: %s', exc.message) except requests.exceptions.ConnectionError: logger.error('ConnectionError') @@ -225,12 +224,7 @@ class ProviderCertChecker(object): return fgetfn(*args, **kwargs) try: - # XXX FIXME!!!! - # verify=verify - # Workaround for #638. return to verification - # when That's done!!! - #req = self.fetcher.get(uri, verify=False) - req = getfn(uri, verify=False) + req = getfn(uri, verify=verify) req.raise_for_status() except requests.exceptions.SSLError: @@ -444,8 +438,8 @@ class EIPConfigChecker(object): # FIXME FIXME FIXME self.defaultprovider.load( from_uri=uri, - fetcher=self.fetcher, - verify=False) + fetcher=self.fetcher) + #verify=False) self.defaultprovider.save() def fetch_eip_service_config(self, skip_download=False, -- cgit v1.2.3 From 6d85c97ddcc8a151b157919e9a7322fba151a551 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 11 Jan 2013 03:00:41 +0900 Subject: all calls except the first one are made to api uri we also parse the port number --- src/leap/eip/checks.py | 85 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 27 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index b14e5dd3..bd158e1e 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -1,5 +1,5 @@ import logging -import ssl +#import ssl #import platform import time import os @@ -21,6 +21,8 @@ from leap.eip import constants as eipconstants from leap.eip import exceptions as eipexceptions from leap.eip import specs as eipspecs from leap.util.fileutil import mkdir_p +from leap.util.web import get_https_domain_and_port +from leap.util.misc import null_check logger = logging.getLogger(name=__name__) @@ -46,7 +48,7 @@ reachable and testable as a whole. def get_branding_ca_cert(domain): - # XXX deprecated + # deprecated ca_file = BRANDING.get('provider_ca_file') if ca_file: return leapcerts.where(ca_file) @@ -63,6 +65,10 @@ class ProviderCertChecker(object): self.fetcher = fetcher self.domain = domain + #XXX needs some kind of autoinit + #right now we set by hand + #by loading and reading provider config + self.apidomain = None self.cacert = eipspecs.provider_ca_path(domain) def run_all( @@ -159,7 +165,7 @@ 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 - logger.debug('is https working?') + logger.debug('checking https connection') logger.debug('uri: %s (verify:%s)', uri, verify) try: self.fetcher.get(uri, verify=verify) @@ -167,27 +173,24 @@ class ProviderCertChecker(object): except requests.exceptions.SSLError: # as exc: logger.error("SSLError") raise eipexceptions.HttpsBadCertError - #logger.warning('BUG #638 CERT VERIFICATION FAILED! ' - #'(this should be CRITICAL)') - #logger.warning('SSLError: %s', exc.message) except requests.exceptions.ConnectionError: logger.error('ConnectionError') raise eipexceptions.HttpsNotSupported else: - logger.debug('True') return True def check_new_cert_needed(self, skip_download=False, verify=True): + # XXX add autocacert logger.debug('is new cert needed?') if not self.is_cert_valid(do_raise=False): - logger.debug('True') + logger.debug('cert needed: true') self.download_new_client_cert( skip_download=skip_download, verify=verify) return True - logger.debug('False') + logger.debug('cert needed: false') return False def download_new_client_cert(self, uri=None, verify=True, @@ -199,20 +202,20 @@ class ProviderCertChecker(object): if uri is None: uri = self._get_client_cert_uri() # XXX raise InsecureURI or something better - assert uri.startswith('https') + #assert uri.startswith('https') if verify is True and self.cacert is not None: verify = self.cacert + logger.debug('verify = %s', verify) fgetfn = self.fetcher.get if credentials: user, passwd = credentials - - logger.debug('domain = %s', self.domain) + logger.debug('apidomain = %s', self.apidomain) @srpauth_protected(user, passwd, - server="https://%s" % self.domain, + server="https://%s" % self.apidomain, verify=verify) def getfn(*args, **kwargs): return fgetfn(*args, **kwargs) @@ -231,11 +234,16 @@ class ProviderCertChecker(object): logger.warning('SSLError while fetching cert. ' 'Look below for stack trace.') # XXX raise better exception - raise + return self.fail("SSLError") + except Exception as exc: + return self.fail(exc.message) + try: + logger.debug('validating cert...') pemfile_content = req.content valid = self.is_valid_pemfile(pemfile_content) if not valid: + logger.warning('invalid cert') return False cert_path = self._get_client_cert_path() self.write_cert(pemfile_content, to=cert_path) @@ -299,8 +307,7 @@ class ProviderCertChecker(object): return u"https://%s/" % self.domain def _get_client_cert_uri(self): - # XXX get the whole thing from constants - return "https://%s/1/cert" % self.domain + return "https://%s/1/cert" % self.apidomain def _get_client_cert_path(self): return eipspecs.client_cert_path(domain=self.domain) @@ -327,6 +334,9 @@ class ProviderCertChecker(object): with open(to, 'w') as cert_f: cert_f.write(pemfile_content) + def set_api_domain(self, domain): + self.apidomain = domain + class EIPConfigChecker(object): """ @@ -346,10 +356,15 @@ class EIPConfigChecker(object): # if not domain, get from config self.domain = domain + self.apidomain = None + self.cacert = eipspecs.provider_ca_path(domain) - self.eipconfig = eipconfig.EIPConfig(domain=domain) self.defaultprovider = providers.LeapProviderDefinition(domain=domain) + self.defaultprovider.load() + self.eipconfig = eipconfig.EIPConfig(domain=domain) + self.set_api_domain() self.eipserviceconfig = eipconfig.EIPServiceConfig(domain=domain) + self.eipserviceconfig.load() def run_all(self, checker=None, skip_download=False): """ @@ -433,31 +448,35 @@ class EIPConfigChecker(object): domain = config.get('provider', None) uri = self._get_provider_definition_uri(domain=domain) - # FIXME! Pass ca path verify!!! - # BUG #638 - # FIXME FIXME FIXME self.defaultprovider.load( from_uri=uri, fetcher=self.fetcher) - #verify=False) self.defaultprovider.save() def fetch_eip_service_config(self, skip_download=False, force_download=False, - config=None, uri=None, domain=None): + config=None, uri=None, # domain=None, + autocacert=True): if skip_download: return True if config is None: + self.eipserviceconfig.load() config = self.eipserviceconfig.config if uri is None: - if not domain: - domain = self.domain or config.get('provider', None) - uri = self._get_eip_service_uri(domain=domain) + #XXX + #if not domain: + #domain = self.domain or config.get('provider', None) + uri = self._get_eip_service_uri( + domain=self.apidomain) + + if autocacert and self.cacert is not None: + verify = self.cacert self.eipserviceconfig.load( from_uri=uri, fetcher=self.fetcher, - force_download=force_download) + force_download=force_download, + verify=verify) self.eipserviceconfig.save() def check_complete_eip_config(self, config=None): @@ -465,7 +484,6 @@ class EIPConfigChecker(object): if config is None: config = self.eipconfig.config try: - 'trying assertions' assert 'provider' in config assert config['provider'] is not None # XXX assert there is gateway !! @@ -504,3 +522,16 @@ class EIPConfigChecker(object): uri = "https://%s/%s" % (domain, path) logger.debug('getting eip service file from %s', uri) return uri + + def set_api_domain(self): + """sets api domain from defaultprovider config object""" + api = self.defaultprovider.config.get('api_uri', None) + # the caller is responsible for having loaded the config + # object at this point + if api: + api_dom = get_https_domain_and_port(api) + self.apidomain = "%s:%s" % api_dom + + def get_api_domain(self): + """gets api domain""" + return self.apidomain -- cgit v1.2.3 From ade0eded09176fd687d1ee30724468c048d15065 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 11 Jan 2013 09:16:49 +0900 Subject: fix for missing cacert bundle frozen app cannot find requests cacert bundle. added to Resources to get us going. --- src/leap/eip/checks.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index bd158e1e..cc395bcb 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -3,6 +3,7 @@ import logging #import platform import time import os +import sys import gnutls.crypto #import netifaces @@ -20,6 +21,7 @@ from leap.eip import config as eipconfig from leap.eip import constants as eipconstants from leap.eip import exceptions as eipexceptions from leap.eip import specs as eipspecs +from leap.util.certs import get_mac_cabundle from leap.util.fileutil import mkdir_p from leap.util.web import get_https_domain_and_port from leap.util.misc import null_check @@ -165,13 +167,15 @@ 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 + if sys.platform == "darwin": + verify = get_mac_cabundle() logger.debug('checking https connection') logger.debug('uri: %s (verify:%s)', uri, verify) + try: self.fetcher.get(uri, verify=verify) - except requests.exceptions.SSLError: # as exc: - logger.error("SSLError") + except requests.exceptions.SSLError as exc: raise eipexceptions.HttpsBadCertError except requests.exceptions.ConnectionError: @@ -448,9 +452,15 @@ class EIPConfigChecker(object): domain = config.get('provider', None) uri = self._get_provider_definition_uri(domain=domain) + if sys.platform == "darwin": + verify = get_mac_cabundle() + else: + verify = True + self.defaultprovider.load( from_uri=uri, - fetcher=self.fetcher) + fetcher=self.fetcher, + verify=verify) self.defaultprovider.save() def fetch_eip_service_config(self, skip_download=False, -- cgit v1.2.3 From 348eb0852d6f1b8b2b72baba8a236bc30a6f2a4e Mon Sep 17 00:00:00 2001 From: antialias Date: Fri, 16 Nov 2012 17:38:46 -0800 Subject: reads and searches for strings from openvpn logs via the management interface. --- src/leap/eip/openvpnconnection.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/leap/eip') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index b36b0b16..233b9da3 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -400,3 +400,7 @@ to be triggered for each one of them. if process.name == "openvpn": return process return None + + def get_log(self, lines=1): + log = self._send_command("log %s" % lines) + return log -- cgit v1.2.3 From bf39c45eddc62733fdb72b4f46cdb81ec649cb30 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 16 Jan 2013 00:58:22 +0900 Subject: handle loss of tun iface trigger only one dialog and disconnect. additional cleanup of log handling. --- src/leap/eip/eipconnection.py | 6 +++++- src/leap/eip/openvpnconnection.py | 26 +++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index 540e7558..20b45e36 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -27,6 +27,8 @@ class StatusMixIn(object): # Should separate EIPConnectionStatus (self.status) # from the OpenVPN state/status command and parsing. + ERR_CONNREFUSED = False + def connection_state(self): """ returns the current connection state @@ -49,7 +51,9 @@ class StatusMixIn(object): state = self.get_connection_state() except eip_exceptions.ConnectionRefusedError: # connection refused. might be not ready yet. - logger.warning('connection refused') + if not self.ERR_CONNREFUSED: + logger.warning('connection refused') + self.ERR_CONNREFUSED = True return if not state: #logger.debug('no state') diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 233b9da3..a36d99de 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -92,14 +92,17 @@ class OpenVPNManagement(object): logger.error('socket error') self._close_management_socket(announce=False) return [] - buf = self.tn.read_until(b"END", 2) - self._seek_to_eof() - blist = buf.split('\r\n') - if blist[-1].startswith('END'): - del blist[-1] - return blist - else: - return [] + try: + buf = self.tn.read_until(b"END", 2) + self._seek_to_eof() + blist = buf.split('\r\n') + if blist[-1].startswith('END'): + del blist[-1] + return blist + else: + return [] + except socket.error as exc: + logger.debug('socket error: %s' % exc.message) def _send_short_command(self, cmd): """ @@ -329,12 +332,12 @@ to be triggered for each one of them. #use _only_ signal_maps instead logger.debug('_launch_openvpn called') - logger.debug('watcher_cb: %s' % self.watcher_cb) if self.watcher_cb is not None: linewrite_callback = self.watcher_cb else: #XXX get logger instead - linewrite_callback = lambda line: logger.debug('watcher: %s' % line) + linewrite_callback = lambda line: logger.debug( + 'watcher: %s' % line) # the partial is not # being applied now because we're not observing the process @@ -342,7 +345,8 @@ to be triggered for each one of them. # here since it will be handy for observing patterns in the # thru-the-manager updates (with regex) observers = (linewrite_callback, - partial(lambda con_status, line: linewrite_callback, self.status)) + partial(lambda con_status, + line: linewrite_callback, self.status)) subp, watcher = spawn_and_watch_process( self.command, self.args, -- cgit v1.2.3 From d72b5d9057bcea884c2e828f5e3045920d4c2205 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 16 Jan 2013 23:31:49 +0900 Subject: pass cacert bundle only in frozen apps --- src/leap/eip/checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index cc395bcb..9fb13c74 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -167,7 +167,7 @@ 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 - if sys.platform == "darwin": + if sys.platform == "darwin": verify = get_mac_cabundle() logger.debug('checking https connection') logger.debug('uri: %s (verify:%s)', uri, verify) -- cgit v1.2.3 From d6c8cb0f12e8924820c296a8114a7899f61e5180 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 17 Jan 2013 05:54:16 +0900 Subject: (osx) detect which interface is traffic going thru --- src/leap/eip/checks.py | 1 - src/leap/eip/config.py | 2 +- src/leap/eip/openvpnconnection.py | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 9fb13c74..0d07ef08 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -187,7 +187,6 @@ class ProviderCertChecker(object): def check_new_cert_needed(self, skip_download=False, verify=True): # XXX add autocacert - logger.debug('is new cert needed?') if not self.is_cert_valid(do_raise=False): logger.debug('cert needed: true') self.download_new_client_cert( diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 6a19633d..a60d7ed5 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -253,7 +253,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 diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index a36d99de..e5169465 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -6,6 +6,7 @@ import logging import os import psutil import shutil +import select import socket from functools import partial @@ -103,6 +104,8 @@ class OpenVPNManagement(object): return [] except socket.error as exc: logger.debug('socket error: %s' % exc.message) + except select.error as exc: + logger.debug('select error: %s' % exc.message) def _send_short_command(self, cmd): """ -- cgit v1.2.3 From 6e9c63f47b98fbfcd3a5104fbfa5cc9d9ffe5143 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 17 Jan 2013 07:31:59 +0900 Subject: osx fixed already running instance check --- src/leap/eip/exceptions.py | 4 ++-- src/leap/eip/openvpnconnection.py | 47 +++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/exceptions.py b/src/leap/eip/exceptions.py index c127a58f..b7d398c3 100644 --- a/src/leap/eip/exceptions.py +++ b/src/leap/eip/exceptions.py @@ -106,11 +106,11 @@ class LeapBadConfigFetchedError(Warning): "an error occurred during configuratio of leap services") -class OpenVPNAlreadyRunning(EIPClientError): +class OpenVPNAlreadyRunning(CriticalError): message = "Another OpenVPN Process is already running." usermessage = translate( "EIPErrors", - "Another OpenVPN Process has been detected." + "Another OpenVPN Process has been detected. " "Please close it before starting leap-client") diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index e5169465..05979ff7 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -2,18 +2,21 @@ OpenVPN Connection """ from __future__ import (print_function) +from functools import partial import logging import os import psutil import shutil import select import socket -from functools import partial +from time import sleep logger = logging.getLogger(name=__name__) from leap.base.connection import Connection +from leap.base.constants import OPENVPN_BIN from leap.util.coroutines import spawn_and_watch_process +from leap.util.misc import get_openvpn_pids from leap.eip.udstelnet import UDSTelnet from leap.eip import config as eip_config @@ -277,23 +280,20 @@ to be triggered for each one of them. # checks + def _check_if_running_instance(self): """ check if openvpn is already running """ - try: - #FIXME this gives DeprecationWarning - for process in psutil.get_process_list(): - if process.name == "openvpn": - logger.debug('an openvpn instance is already running.') - logger.debug('attempting to stop openvpn instance.') - if not self._stop_openvpn(): - raise eip_exceptions.OpenVPNAlreadyRunning - - except psutil.error.NoSuchProcess: - logger.debug('detected a process which died. passing.') - - logger.debug('no openvpn instance found.') + openvpn_pids = get_openvpn_pids() + if openvpn_pids: + logger.debug('an openvpn instance is already running.') + logger.debug('attempting to stop openvpn instance.') + if not self._stop_openvpn(): + raise eip_exceptions.OpenVPNAlreadyRunning + return + else: + logger.debug('no openvpn instance found.') def _set_ovpn_command(self): try: @@ -334,7 +334,7 @@ to be triggered for each one of them. #deprecate watcher_cb, #use _only_ signal_maps instead - logger.debug('_launch_openvpn called') + #logger.debug('_launch_openvpn called') if self.watcher_cb is not None: linewrite_callback = self.watcher_cb else: @@ -364,23 +364,24 @@ to be triggered for each one of them. interface """ # XXX method a bit too long, split - logger.debug("terminating openvpn process...") + logger.debug("atempting to terminate openvpn process...") if self.connected(): try: self._send_command("signal SIGTERM\n") + sleep(1) + if not self.subp: # XXX ??? + return True except socket.error: logger.warning('management socket died') return - if self.subp: - # ??? - return True #shutting openvpn failured #try patching in old openvpn host and trying again + # XXX could be more than one! process = self._get_openvpn_process() if process: - logger.debug('process :%s' % process) + logger.debug('process: %s' % process.name) cmdline = process.cmdline manag_flag = "--management" @@ -401,10 +402,8 @@ to be triggered for each one of them. return True def _get_openvpn_process(self): - # plist = [p for p in psutil.get_process_list() if p.name == "openvpn"] - # return plist[0] if plist else None - for process in psutil.get_process_list(): - if process.name == "openvpn": + for process in psutil.process_iter(): + if OPENVPN_BIN in process.name: return process return None -- cgit v1.2.3 From 8226d6032b6db0c15ff70e377f87f4acfdd21787 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 23 Jan 2013 07:02:58 +0900 Subject: working up/down resolv-conf script --- src/leap/eip/config.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index a60d7ed5..917871da 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -130,6 +130,22 @@ def get_cipher_options(eipserviceconfig=None): 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): """ @@ -230,10 +246,14 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): opts.append('2') if _platform == "Linux": - opts.append("--up") - opts.append("/etc/openvpn/update-resolv-conf") - opts.append("--down") - opts.append("/etc/openvpn/update-resolv-conf") + 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) -- cgit v1.2.3 From 407b030bb7d27b797fb27254710a358c9c69f8be Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 24 Jan 2013 01:57:28 +0900 Subject: catch missing messages on last page of wizard --- src/leap/eip/eipconnection.py | 2 +- src/leap/eip/openvpnconnection.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/eipconnection.py b/src/leap/eip/eipconnection.py index 20b45e36..d012c567 100644 --- a/src/leap/eip/eipconnection.py +++ b/src/leap/eip/eipconnection.py @@ -177,7 +177,7 @@ class EIPConnection(OpenVPNConnection, StatusMixIn): super(EIPConnection, self).__init__(*args, **kwargs) - def connect(self): + def connect(self, **kwargs): """ entry point for connection process """ diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 05979ff7..4953db11 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -280,7 +280,6 @@ to be triggered for each one of them. # checks - def _check_if_running_instance(self): """ check if openvpn is already running -- cgit v1.2.3 From 9cdc193c587631986e579c1ba37a8b982be01238 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 24 Jan 2013 18:47:41 +0900 Subject: all tests green again plus: * added soledad test requirements * removed soledad from run_tests run (+1K tests failing) * added option to run All tests to run_tests script * pep8 cleanup --- src/leap/eip/checks.py | 4 ++-- src/leap/eip/openvpnconnection.py | 3 +-- src/leap/eip/tests/test_config.py | 14 ++++++++++++++ src/leap/eip/tests/test_openvpnconnection.py | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 0d07ef08..de738de6 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -451,7 +451,7 @@ class EIPConfigChecker(object): domain = config.get('provider', None) uri = self._get_provider_definition_uri(domain=domain) - if sys.platform == "darwin": + if sys.platform == "darwin": verify = get_mac_cabundle() else: verify = True @@ -465,7 +465,7 @@ class EIPConfigChecker(object): def fetch_eip_service_config(self, skip_download=False, force_download=False, config=None, uri=None, # domain=None, - autocacert=True): + autocacert=True, verify=True): if skip_download: return True if config is None: diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index 4953db11..455735c8 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -107,7 +107,7 @@ class OpenVPNManagement(object): return [] except socket.error as exc: logger.debug('socket error: %s' % exc.message) - except select.error as exc: + except select.error as exc: logger.debug('select error: %s' % exc.message) def _send_short_command(self, cmd): @@ -374,7 +374,6 @@ to be triggered for each one of them. logger.warning('management socket died') return - #shutting openvpn failured #try patching in old openvpn host and trying again # XXX could be more than one! diff --git a/src/leap/eip/tests/test_config.py b/src/leap/eip/tests/test_config.py index 5977ef3c..05e78de4 100644 --- a/src/leap/eip/tests/test_config.py +++ b/src/leap/eip/tests/test_config.py @@ -28,6 +28,8 @@ class EIPConfigTest(BaseLeapTest): __name__ = "eip_config_tests" provider = "testprovider.example.org" + maxDiff = None + def setUp(self): pass @@ -130,6 +132,18 @@ class EIPConfigTest(BaseLeapTest): args.append('/tmp/test.socket') args.append('unix') + args.append('--script-security') + args.append('2') + + if _system == "Linux": + args.append('--up') + args.append('/etc/leap/resolv-update') + args.append('--down') + args.append('/etc/leap/resolv-update') + args.append('--plugin') + args.append('/usr/lib/openvpn/openvpn-down-root.so') + args.append("'script_type=down /etc/leap/resolv-update'") + # certs # XXX get values from specs? args.append('--cert') diff --git a/src/leap/eip/tests/test_openvpnconnection.py b/src/leap/eip/tests/test_openvpnconnection.py index f7493567..95bfb2f0 100644 --- a/src/leap/eip/tests/test_openvpnconnection.py +++ b/src/leap/eip/tests/test_openvpnconnection.py @@ -91,9 +91,10 @@ class OpenVPNConnectionTest(BaseLeapTest): # while fixing. kali. openvpn_connection = openvpnconnection.OpenVPNConnection() - with patch.object(psutil, "get_process_list") as mocked_psutil: + with patch.object(psutil, "process_iter") as mocked_psutil: mocked_process = Mock() mocked_process.name = "openvpn" + mocked_process.cmdline = ["openvpn", "-foo", "-bar", "-gaaz"] mocked_psutil.return_value = [mocked_process] with self.assertRaises(eipexceptions.OpenVPNAlreadyRunning): openvpn_connection._check_if_running_instance() -- cgit v1.2.3 From 19da34c598ce6db172c1e1a8978bf031fc6db89b Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 24 Jan 2013 20:07:06 +0900 Subject: check cert time_boundaries uses pyOpenSSL I had missed this one while deprecating gnutls --- src/leap/eip/checks.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index de738de6..9a34a428 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -1,13 +1,8 @@ import logging -#import ssl -#import platform import time import os import sys -import gnutls.crypto -#import netifaces -#import ping import requests from leap import __branding as BRANDING @@ -24,7 +19,6 @@ from leap.eip import specs as eipspecs from leap.util.certs import get_mac_cabundle from leap.util.fileutil import mkdir_p from leap.util.web import get_https_domain_and_port -from leap.util.misc import null_check logger = logging.getLogger(name=__name__) @@ -276,11 +270,8 @@ class ProviderCertChecker(object): def is_cert_not_expired(self, certfile=None, now=time.gmtime): if certfile is None: certfile = self._get_client_cert_path() - with open(certfile) as cf: - cert_s = cf.read() - cert = gnutls.crypto.X509Certificate(cert_s) - from_ = time.gmtime(cert.activation_time) - to_ = time.gmtime(cert.expiration_time) + from_, to_ = certs.get_time_boundaries(certfile) + return from_ < now() < to_ def is_valid_pemfile(self, cert_s=None): -- cgit v1.2.3 From 05b407b6c74b939a02c3d97ffe4a92faf0325284 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 25 Jan 2013 02:36:08 +0900 Subject: fix test when missing system updown script --- src/leap/eip/tests/test_config.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/leap/eip') diff --git a/src/leap/eip/tests/test_config.py b/src/leap/eip/tests/test_config.py index 05e78de4..72ab3c8e 100644 --- a/src/leap/eip/tests/test_config.py +++ b/src/leap/eip/tests/test_config.py @@ -136,13 +136,15 @@ class EIPConfigTest(BaseLeapTest): args.append('2') if _system == "Linux": - args.append('--up') - args.append('/etc/leap/resolv-update') - args.append('--down') - args.append('/etc/leap/resolv-update') - args.append('--plugin') - args.append('/usr/lib/openvpn/openvpn-down-root.so') - args.append("'script_type=down /etc/leap/resolv-update'") + UPDOWN_SCRIPT = "/etc/leap/resolv-update" + if os.path.isfile(UPDOWN_SCRIPT): + args.append('--up') + args.append('/etc/leap/resolv-update') + args.append('--down') + args.append('/etc/leap/resolv-update') + args.append('--plugin') + args.append('/usr/lib/openvpn/openvpn-down-root.so') + args.append("'script_type=down /etc/leap/resolv-update'") # certs # XXX get values from specs? -- cgit v1.2.3