diff options
author | kali <kali@leap.se> | 2012-10-24 04:05:19 +0900 |
---|---|---|
committer | kali <kali@leap.se> | 2012-10-24 04:05:19 +0900 |
commit | 0060d3c74adce19fab7215b3788c5197cc05a9ae (patch) | |
tree | 30de33e139ebcd5126f553409df4b2efac9df374 | |
parent | ac67079632fb96d9da463e0cc9f2367b0ba6886e (diff) |
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.
-rw-r--r-- | src/leap/baseapp/eip.py | 4 | ||||
-rw-r--r-- | src/leap/baseapp/mainwindow.py | 52 | ||||
-rw-r--r-- | src/leap/eip/checks.py | 37 | ||||
-rw-r--r-- | src/leap/eip/config.py | 19 | ||||
-rw-r--r-- | src/leap/eip/eipconnection.py | 15 | ||||
-rw-r--r-- | src/leap/eip/openvpnconnection.py | 4 | ||||
-rw-r--r-- | src/leap/eip/specs.py | 6 | ||||
-rwxr-xr-x | src/leap/gui/firstrunwizard.py | 82 |
8 files changed, 154 insertions, 65 deletions
diff --git a/src/leap/baseapp/eip.py b/src/leap/baseapp/eip.py index ca2e03c3..26a2a1fb 100644 --- a/src/leap/baseapp/eip.py +++ b/src/leap/baseapp/eip.py @@ -25,6 +25,7 @@ class EIPConductorAppMixin(object): def __init__(self, *args, **kwargs): opts = kwargs.pop('opts') config_file = getattr(opts, 'config_file', None) + provider = kwargs.pop('provider') self.eip_service_started = False @@ -39,7 +40,8 @@ class EIPConductorAppMixin(object): checker_signals=(self.changeLeapStatus.emit, ), status_signals=(self.statusChange.emit, ), debug=self.debugmode, - ovpn_verbosity=opts.openvpn_verb) + ovpn_verbosity=opts.openvpn_verb, + provider=provider) self.skip_download = opts.no_provider_checks self.skip_verify = opts.no_ca_verify diff --git a/src/leap/baseapp/mainwindow.py b/src/leap/baseapp/mainwindow.py index df7159ce..752dba51 100644 --- a/src/leap/baseapp/mainwindow.py +++ b/src/leap/baseapp/mainwindow.py @@ -35,7 +35,8 @@ class LeapWindow(QtGui.QMainWindow, triggerEIPError = QtCore.pyqtSignal([object]) start_eipconnection = QtCore.pyqtSignal([]) - # XXX fix nomenclature here + # XXX fix nomenclature here: + # eipStatusChange vs. leapStatusChange # this is eip status change got from vpn management statusChange = QtCore.pyqtSignal([object]) # this is global leap status @@ -49,11 +50,14 @@ class LeapWindow(QtGui.QMainWindow, self.createLogBrowser() settings = QtCore.QSettings() - provider_domain = settings.value("provider_domain", None) - logger.debug('provider: %s', provider_domain) + self.provider_domain = settings.value("provider_domain", None) + self.eip_username = settings.value("eip_username", None) + + logger.debug('provider: %s', self.provider_domain) + logger.debug('eip_username: %s', self.eip_username) EIPConductorAppMixin.__init__( - self, opts=opts, provider=provider_domain) + self, opts=opts, provider=self.provider_domain) StatusAwareTrayIconMixin.__init__(self) NetworkCheckerAppMixin.__init__(self) MainWindowMixin.__init__(self) @@ -62,13 +66,15 @@ class LeapWindow(QtGui.QMainWindow, geom = settings.value(geom_key) if geom: self.restoreGeometry(geom) + + # XXX check for wizard self.wizard_done = settings.value("FirstRunWizardDone") self.initchecks = InitChecksThread(self.run_eip_checks) # bind signals self.initchecks.finished.connect( - lambda: logger.debug('Initial checks finished')) + lambda: logger.debug('Initial checks thread finished')) self.trayIcon.activated.connect(self.iconActivated) self.newLogLine.connect( lambda line: self.onLoggerNewLine(line)) @@ -92,32 +98,52 @@ class LeapWindow(QtGui.QMainWindow, self.changeLeapStatus.connect( lambda newstatus: self.onChangeLeapConnStatus(newstatus)) - # do frwizard and init signals + # do first run wizard and init signals self.mainappReady.connect(self.do_first_run_wizard_check) self.initReady.connect(self.runchecks_and_eipconnect) # ... all ready. go! - # calls do_first_run_wizard_check + # connected to do_first_run_wizard_check self.mainappReady.emit() def do_first_run_wizard_check(self): + """ + checks whether first run wizard needs to be run + launches it if needed (with initReady signal as a success callback) + and emits initReady signal if not. + """ + # XXX change DOC string after I remove the success callbac!!! + logger.debug('first run wizard check...') - if self.wizard_done: - self.initReady.emit() - else: - # need to run first-run-wizard - logger.debug('running first run wizard') + need_wizard = False + + # do checks (can overlap if wizard was interrupted) + if not self.wizard_done: + need_wizard = True + if not self.provider_domain: + need_wizard = True + + # launch wizard if needed + if need_wizard: from leap.gui.firstrunwizard import FirstRunWizard wizard = FirstRunWizard( + self.conductor, parent=self, - success_cb=self.initReady.emit) + eip_username=self.eip_username, + start_eipconnection_signal=self.start_eipconnection) wizard.show() + else: # no wizard needed + logger.debug('running first run wizard') + self.initReady.emit() + return def runchecks_and_eipconnect(self): self.initchecks.begin() class InitChecksThread(QtCore.QThread): + # XXX rename as a generic QThread class, + # has nothing specific to initchecks def __init__(self, fun, parent=None): QtCore.QThread.__init__(self, parent) 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(), diff --git a/src/leap/gui/firstrunwizard.py b/src/leap/gui/firstrunwizard.py index d9e33f7e..c7531d16 100755 --- a/src/leap/gui/firstrunwizard.py +++ b/src/leap/gui/firstrunwizard.py @@ -44,20 +44,28 @@ QLabel { color: red; class FirstRunWizard(QtGui.QWizard): def __init__( - self, parent=None, providers=None, + self, + conductor_instance, + parent=None, + eip_username=None, + providers=None, success_cb=None, is_provider_setup=False, is_previously_registered=False, trusted_certs=None, netchecker=basechecks.LeapNetworkChecker, providercertchecker=eipchecks.ProviderCertChecker, - eipconfigchecker=eipchecks.EIPConfigChecker): + eipconfigchecker=eipchecks.EIPConfigChecker, + start_eipconnection_signal=None): super(FirstRunWizard, self).__init__( parent, QtCore.Qt.WindowStaysOnTopHint) - # XXX hardcoded for tests - #if not providers: - #providers = ('springbok',) + # we keep a reference to the conductor + # to be able to launch eip checks and connection + # in the connection page, before the wizard has ended. + self.conductor = conductor_instance + + self.eip_username = eip_username self.providers = providers # success callback @@ -79,10 +87,13 @@ class FirstRunWizard(QtGui.QWizard): self.providercertchecker = providercertchecker self.eipconfigchecker = eipconfigchecker + # signal for starting eip connection + # will be emitted in connecting page + self.start_eipconnection_signal = start_eipconnection_signal + self.providerconfig = None - # FIXME add param for previously_registered - # should start at login page. + is_previously_registered = bool(self.eip_username) pages_dict = OrderedDict(( # (name, WizardPage) @@ -150,11 +161,11 @@ class FirstRunWizard(QtGui.QWizard): """ final step in the wizard. gather the info, update settings - and call the success callback. + and call the success callback if any has been passed. """ provider = self.field('provider_domain') username = self.field('userName') - #password = self.field('userPassword') + password = self.field('userPassword') remember_pass = self.field('rememberPassword') logger.debug('chosen provider: %s', provider) @@ -163,19 +174,25 @@ class FirstRunWizard(QtGui.QWizard): super(FirstRunWizard, self).accept() settings = QtCore.QSettings() + # we are assuming here that we only remember one username + # in the form username@provider.domain + # We probably could extend this to support some form of + # profiles. + settings.setValue("FirstRunWizardDone", True) - settings.setValue( - "eip_%s_username" % provider, - username) - settings.setValue("%s_remember_pass" % provider, remember_pass) + settings.setValue("provider_domain", provider) + full_username = "%s@%s" % (username, provider) + + settings.setValue("eip_username", full_username) + settings.setValue("remember_user_and_pass", remember_pass) seed = self.get_random_str(10) settings.setValue("%s_seed" % provider, seed) - # Commenting out for 0.2.0 release - # since we did not fix #744 on time. - - #leapkeyring.leap_set_password(username, password, seed=seed) + # XXX #744: comment out for 0.2.0 release + # if we need to have a version of python-keyring < 0.9 + leapkeyring.leap_set_password( + full_username, password, seed=seed) logger.debug('First Run Wizard Done.') cb = self.success_cb @@ -863,7 +880,7 @@ class RegisterUserPage(QtGui.QWizardPage, UserFormMixIn): return False if password == "123456": - # XD + # joking self.set_validation_status('Password too obvious.') return False @@ -970,6 +987,30 @@ class ConnectingPage(QtGui.QWizardPage): def get_donemsg(self, msg): return "%s ... done" % msg + def run_eip_checks_for_provider(self, domain): + wizard = self.wizard() + conductor = wizard.conductor + start_eip_signal = getattr( + wizard, + 'start_eipconnection_signal', None) + conductor.set_provider_domain(domain) + conductor.run_checks() + self.conductor = conductor + errors = self.eip_error_check() + if not errors and start_eip_signal: + start_eip_signal.emit() + + def eip_error_check(self): + """ + a version of the main app error checker, + but integrated within the connecting page of the wizard. + consumes the conductor error queue. + pops errors, and add those to the wizard page + """ + logger.debug('eip error check from connecting page') + errq = self.conductor.error_queue + # XXX missing! + def fetch_and_validate(self): # Fake... till you make it... import time @@ -1023,6 +1064,9 @@ class ConnectingPage(QtGui.QWizardPage): self.progress.setValue(100) time.sleep(3) + # here we go! :) + self.run_eip_checks_for_provider(domain) + return True # pagewizard methods @@ -1092,6 +1136,6 @@ if __name__ == '__main__': "18C62B941192CC1A" "49AE62218B2A4B7C": ['springbok']} - wizard = FirstRunWizard(trusted_certs=trusted_certs) + wizard = FirstRunWizard(None, trusted_certs=trusted_certs) wizard.show() sys.exit(app.exec_()) |