From 22342664951ac32756ceb7ade59ada90f92c8793 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 4 Apr 2013 01:47:12 +0900 Subject: Several fixes in wizard Closes:#2061 o Rewording of setup steps in wizard, to make them more meaningful to the non-technical user. Closes: #2061 o Fix typo in wizard o Fix multiple drawing of services if going back o Make registration errors show in red o Add a warning if EIP service needs admin password. Addresses part of #2062 --- src/leap/config/providerconfig.py | 18 +++ src/leap/gui/mainwindow.py | 2 +- src/leap/gui/ui/wizard.ui | 265 ++++++++++++++++++++++++++++-------- src/leap/gui/wizard.py | 49 +++++-- src/leap/util/privilege_policies.py | 78 +++++++++++ 5 files changed, 344 insertions(+), 68 deletions(-) create mode 100644 src/leap/util/privilege_policies.py (limited to 'src') diff --git a/src/leap/config/providerconfig.py b/src/leap/config/providerconfig.py index 71b2856f..7651863b 100644 --- a/src/leap/config/providerconfig.py +++ b/src/leap/config/providerconfig.py @@ -65,6 +65,11 @@ class ProviderConfig(BaseConfig): return self._safe_get_value("domain") def get_enrollment_policy(self): + """ + Returns the enrollment policy + + @rtype: string + """ return self._safe_get_value("enrollment_policy") def get_languages(self): @@ -75,8 +80,21 @@ class ProviderConfig(BaseConfig): return self._safe_get_value("name") def get_services(self): + """ + Returns a list with the services supported by the + current provider + + @rtype: list + """ return self._safe_get_value("services") + def get_services_string(self): + """ + Returns a string with the services supported by the current provider, + ready to be shown to the user + """ + return ", ".join(self.get_services()) + def get_ca_cert_path(self, about_to_download=False): """ Returns the path to the certificate for the current provider diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py index 863640ef..7f529e2f 100644 --- a/src/leap/gui/mainwindow.py +++ b/src/leap/gui/mainwindow.py @@ -202,7 +202,7 @@ class MainWindow(QtGui.QMainWindow): self._wizard_firstrun = False if self._first_run(): self._wizard_firstrun = True - self._wizard = Wizard(self._checker_thread) + self._wizard = Wizard(self._checker_thread, standalone=standalone) # Give this window time to finish init and then show the wizard QtCore.QTimer.singleShot(1, self._launch_wizard) self._wizard.accepted.connect(self._finish_init) diff --git a/src/leap/gui/ui/wizard.ui b/src/leap/gui/ui/wizard.ui index b8fed183..141418db 100644 --- a/src/leap/gui/ui/wizard.ui +++ b/src/leap/gui/ui/wizard.ui @@ -100,7 +100,7 @@ Provider selection - Please enter the domain of the provider you want to user for your connection + Please enter the domain of the provider you want to use for your connection 1 @@ -158,20 +158,20 @@ - Checking provider + Checking for a valid provider - Download provider information + Getting provider information - HTTPS Connection + Can we stablish a secure connection? @@ -244,7 +244,7 @@ - Name resolution + Can we reach this provider? @@ -278,39 +278,117 @@ Provider Information - Services offered by this provider + Description of services offered by this provider 2 - - + + - Qt::Horizontal + Qt::Vertical - 40 - 0 + 20 + 40 - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + <b>Enrollment policy:</b> - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - URL + policy + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -318,20 +396,27 @@ - - + + - Qt::Horizontal + Qt::Vertical - 40 - 0 + 20 + 40 - + + + + <b>Services offered:</b> + + + + Qt::Vertical @@ -344,36 +429,81 @@ - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - policy + URL - - - - Desc + + + + Qt::Horizontal - - true + + + 40 + 20 + + + + + + + + services - - + + - Qt::Vertical + Qt::Horizontal - 20 - 40 + 40 + 20 + + + + + 0 + 0 + + + + + 200 + 0 + + + + Desc + + + true + + + @@ -386,11 +516,47 @@ 3 - - + + + + + Qt::Vertical + + + + 20 + 60 + + + + + + + + We are downloading some bits that we need to stablish a secure connection with the provider for the first time. + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - Checking provider + Setting up provider @@ -440,21 +606,21 @@ - Download CA Certificate + Getting info from the Certificate Authority - Check CA Certificate Fingerprint + Do we trust this Certificate Authority? - Check API Certificate + Establishing a trust relationship with this provider @@ -496,20 +662,7 @@ - - - - Qt::Vertical - - - - 20 - 60 - - - - - + Qt::Vertical @@ -662,7 +815,7 @@ Congratulations! - You have successfully configured the LEAP client. + You have successfully configured the LEAP Client. 6 diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index dee3b230..5742dfef 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/gui/wizard.py @@ -27,6 +27,7 @@ from functools import partial from ui_wizard import Ui_Wizard from leap.config.providerconfig import ProviderConfig from leap.crypto.srpregister import SRPRegister +from leap.util.privilege_policies import is_missing_policy_permissions from leap.services.eip.providerbootstrapper import ProviderBootstrapper logger = logging.getLogger(__name__) @@ -50,9 +51,11 @@ class Wizard(QtGui.QWizard): BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" - def __init__(self, checker): + def __init__(self, checker, standalone=False): QtGui.QWizard.__init__(self) + self.standalone = standalone + self.ui = Ui_Wizard() self.ui.setupUi(self) @@ -64,14 +67,23 @@ class Wizard(QtGui.QWizard): self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png") # Correspondence for services and their name to display + # XXX need to add a note about "requires admin pass" if + # no polkit found. + EIP_LABEL = self.tr("Encrypted Internet") + + if self._is_need_eip_password_warning(): + EIP_LABEL += " " + self.tr( + "(will need admin pass to start)") + self.SERVICE_DISPLAY = [ - self.tr("Encrypted Internet") + EIP_LABEL ] self.SERVICE_CONFIG = [ "openvpn" ] self._selected_services = set() + self._shown_services = set() self._show_register = False @@ -235,7 +247,7 @@ class Wizard(QtGui.QWizard): error_msg = req.json().get("errors").get("login")[0] if not error_msg.istitle(): error_msg = "%s %s" % (old_username, error_msg) - self._set_register_status(error_msg) + self._set_register_status(error_msg, error=True) except: logger.error("Unknown error: %r" % (req.content,)) self.ui.btnRegister.setEnabled(True) @@ -451,13 +463,15 @@ class Wizard(QtGui.QWizard): for service in self._provider_config.get_services(): try: - checkbox = QtGui.QCheckBox(self) - service_index = self.SERVICE_CONFIG.index(service) - checkbox.setText(self.SERVICE_DISPLAY[service_index]) - self.ui.serviceListLayout.addWidget(checkbox) - checkbox.stateChanged.connect( - partial(self._service_selection_changed, service)) - checkbox.setChecked(True) + if service not in self._shown_services: + checkbox = QtGui.QCheckBox(self) + service_index = self.SERVICE_CONFIG.index(service) + checkbox.setText(self.SERVICE_DISPLAY[service_index]) + self.ui.serviceListLayout.addWidget(checkbox) + checkbox.stateChanged.connect( + partial(self._service_selection_changed, service)) + checkbox.setChecked(True) + self._shown_services.add(service) except ValueError: logger.error( self.tr("Something went wrong while trying to " @@ -486,7 +500,8 @@ class Wizard(QtGui.QWizard): self._provider_config) if pageId == self.PRESENT_PROVIDER_PAGE: - self.page(pageId).setSubTitle(self.tr("Services offered by %s") % + self.page(pageId).setSubTitle(self.tr("Description of services " + "offered by %s") % (self._provider_config .get_name(),)) @@ -499,6 +514,9 @@ class Wizard(QtGui.QWizard): self.ui.lblProviderDesc.setText( "%s" % (self._provider_config.get_description(lang=lang),)) + + self.ui.lblServicesOffered.setText(self._provider_config + .get_services_string()) self.ui.lblProviderPolicy.setText(self._provider_config .get_enrollment_policy()) @@ -511,6 +529,15 @@ class Wizard(QtGui.QWizard): if pageId == self.SERVICES_PAGE: self._populate_services() + def _is_need_eip_password_warning(self): + """ + Returns True if we need to add a warning about eip needing + administrative permissions to start. That can be either + because we are running in standalone mode, or because we could + not find the needed privilege escalation mechanisms being operative. + """ + return self.standalone or is_missing_policy_permissions() + def nextId(self): """ Sets the next page id for the wizard based on wether the user diff --git a/src/leap/util/privilege_policies.py b/src/leap/util/privilege_policies.py new file mode 100644 index 00000000..5bf1b476 --- /dev/null +++ b/src/leap/util/privilege_policies.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# privilege_policies.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Helpers to determine if the needed policies for privilege escalation +are operative under this client run. +""" +import logging +import os +import platform + +from abc import ABCMeta, abstractmethod + +logger = logging.getLogger(__name__) + + +def is_missing_policy_permissions(): + """ + Returns True if we do not have implemented a policy checker for this + platform, or if the policy checker exists but it cannot find the + appropriate policy mechanisms in place. + """ + _system = platform.system() + platform_checker = _system + "PolicyChecker" + policy_checker = globals().get(platform_checker, None) + if not policy_checker: + # it is true that we miss permission to escalate + # privileges without asking for password each time. + logger.debug("we could not find a policy checker implementation " + "for %s" % (_system,)) + return True + return policy_checker().is_missing_policy_permissions() + + +class PolicyChecker: + """ + Abstract PolicyChecker class + """ + + __metaclass__ = ABCMeta + + @abstractmethod + def is_missing_policy_permissions(self): + """ + Returns True if we could not find any policy mechanisms that + are defined to be in used for this particular platform. + + @rtype: bool + """ + return True + + +class LinuxPolicyChecker(PolicyChecker): + """ + PolicyChecker for Linux + """ + LINUX_POLKIT_FILE = ("/usr/share/polkit-1/actions/" + "net.openvpn.gui.leap.policy") + + def is_missing_policy_permissions(self): + """ + Returns True if we could not find the appropriate policykit file + in place + """ + return not os.path.isfile(self.LINUX_POLKIT_FILE) -- cgit v1.2.3