diff options
| author | Tomas Touceda <chiiph@leap.se> | 2013-04-09 09:22:43 -0300 | 
|---|---|---|
| committer | Tomas Touceda <chiiph@leap.se> | 2013-04-09 09:22:43 -0300 | 
| commit | b48f78b47fd4bd0cd05cc7f588b878458e0ead6d (patch) | |
| tree | cba66690bbe1ca39927f017c7d2ee9f5b85654d3 | |
| parent | 5a3898eeb7c2ed3bb5eb1f6b72bb2d782e579f6d (diff) | |
| parent | 785bdfaceb9f3d392f162dd818fea9098d9375a4 (diff) | |
Merge remote-tracking branch 'kali/bug/wizard-text-improvements' into develop
| -rw-r--r-- | changes/bug_2061_wizard-text-improvements | 6 | ||||
| -rw-r--r-- | src/leap/config/providerconfig.py | 18 | ||||
| -rw-r--r-- | src/leap/gui/mainwindow.py | 2 | ||||
| -rw-r--r-- | src/leap/gui/ui/wizard.ui | 269 | ||||
| -rw-r--r-- | src/leap/gui/wizard.py | 56 | ||||
| -rw-r--r-- | src/leap/util/privilege_policies.py | 82 | 
6 files changed, 363 insertions, 70 deletions
| diff --git a/changes/bug_2061_wizard-text-improvements b/changes/bug_2061_wizard-text-improvements new file mode 100644 index 00000000..073a184f --- /dev/null +++ b/changes/bug_2061_wizard-text-improvements @@ -0,0 +1,6 @@ +  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 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 3fa3aad3..f359d7c1 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..ed7fe37c 100644 --- a/src/leap/gui/ui/wizard.ui +++ b/src/leap/gui/ui/wizard.ui @@ -100,7 +100,7 @@      <string>Provider selection</string>     </property>     <property name="subTitle"> -    <string>Please enter the domain of the provider you want to user for your connection</string> +    <string>Please enter the domain of the provider you want to use for your connection</string>     </property>     <attribute name="pageId">      <string notr="true">1</string> @@ -158,20 +158,20 @@      <item row="4" column="0" colspan="3">       <widget class="QGroupBox" name="grpCheckProvider">        <property name="title"> -       <string>Checking provider</string> +       <string>Checking for a valid provider</string>        </property>        <layout class="QGridLayout" name="gridLayout_3">         <item row="3" column="0">          <widget class="QLabel" name="label_5">           <property name="text"> -          <string>Download provider information</string> +          <string>Getting provider information</string>           </property>          </widget>         </item>         <item row="2" column="0">          <widget class="QLabel" name="label_4">           <property name="text"> -          <string>HTTPS Connection</string> +          <string>Can we stablish a secure connection?</string>           </property>          </widget>         </item> @@ -244,7 +244,7 @@         <item row="1" column="0">          <widget class="QLabel" name="label_2">           <property name="text"> -          <string>Name resolution</string> +          <string>Can we reach this provider?</string>           </property>          </widget>         </item> @@ -278,47 +278,118 @@      <string>Provider Information</string>     </property>     <property name="subTitle"> -    <string>Services offered by this provider</string> +    <string>Description of services offered by this provider</string>     </property>     <attribute name="pageId">      <string notr="true">2</string>     </attribute>     <layout class="QGridLayout" name="gridLayout_4"> -    <item row="0" column="1" colspan="2"> -     <spacer name="horizontalSpacer_6"> +    <item row="0" column="0"> +     <spacer name="verticalSpacer_5">        <property name="orientation"> -       <enum>Qt::Horizontal</enum> +       <enum>Qt::Vertical</enum>        </property>        <property name="sizeHint" stdset="0">         <size> -        <width>40</width> -        <height>0</height> +        <width>20</width> +        <height>40</height>         </size>        </property>       </spacer>      </item> -    <item row="5" column="0" colspan="2"> -     <widget class="QLabel" name="label_12"> +    <item row="0" column="1"> +     <spacer name="verticalSpacer_13"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="0" column="2"> +     <spacer name="verticalSpacer_17"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="0" column="3"> +     <spacer name="verticalSpacer_18"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="0" column="4"> +     <spacer name="verticalSpacer_19"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="0" column="5"> +     <spacer name="verticalSpacer_20"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="1" column="0"> +     <widget class="QLabel" name="lblProviderName">        <property name="text"> -       <string><b>Enrollment policy:</b></string> +       <string>Name</string>        </property>       </widget>      </item> -    <item row="2" column="1" colspan="2"> +    <item row="1" column="1">       <widget class="QLabel" name="lblProviderURL">        <property name="text">         <string>URL</string>        </property>       </widget>      </item> -    <item row="2" column="0"> -     <widget class="QLabel" name="lblProviderName"> -      <property name="text"> -       <string>Name</string> +    <item row="1" column="6"> +     <spacer name="horizontalSpacer_3"> +      <property name="orientation"> +       <enum>Qt::Horizontal</enum>        </property> -     </widget> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>40</width> +        <height>20</height> +       </size> +      </property> +     </spacer>      </item> -    <item row="4" column="2"> +    <item row="2" column="0">       <spacer name="horizontalSpacer_7">        <property name="orientation">         <enum>Qt::Horizontal</enum> @@ -326,42 +397,75 @@        <property name="sizeHint" stdset="0">         <size>          <width>40</width> -        <height>0</height> +        <height>20</height>         </size>        </property>       </spacer>      </item> -    <item row="1" column="1"> -     <spacer name="verticalSpacer_13"> +    <item row="2" column="1" colspan="6"> +     <widget class="QLabel" name="lblProviderDesc"> +      <property name="minimumSize"> +       <size> +        <width>0</width> +        <height>0</height> +       </size> +      </property> +      <property name="baseSize"> +       <size> +        <width>200</width> +        <height>0</height> +       </size> +      </property> +      <property name="text"> +       <string>Desc</string> +      </property> +      <property name="wordWrap"> +       <bool>true</bool> +      </property> +     </widget> +    </item> +    <item row="3" column="0"> +     <widget class="QLabel" name="lblServ"> +      <property name="text"> +       <string><b>Services offered:</b></string> +      </property> +     </widget> +    </item> +    <item row="3" column="1"> +     <widget class="QLabel" name="lblServicesOffered"> +      <property name="text"> +       <string>services</string> +      </property> +     </widget> +    </item> +    <item row="3" column="6"> +     <spacer name="horizontalSpacer_6">        <property name="orientation"> -       <enum>Qt::Vertical</enum> +       <enum>Qt::Horizontal</enum>        </property>        <property name="sizeHint" stdset="0">         <size> -        <width>20</width> -        <height>40</height> +        <width>40</width> +        <height>20</height>         </size>        </property>       </spacer>      </item> -    <item row="5" column="2"> -     <widget class="QLabel" name="lblProviderPolicy"> +    <item row="4" column="0"> +     <widget class="QLabel" name="label_12">        <property name="text"> -       <string>policy</string> +       <string><b>Enrollment policy:</b></string>        </property>       </widget>      </item> -    <item row="3" column="0" colspan="3"> -     <widget class="QLabel" name="lblProviderDesc"> +    <item row="4" column="1"> +     <widget class="QLabel" name="lblProviderPolicy">        <property name="text"> -       <string>Desc</string> -      </property> -      <property name="wordWrap"> -       <bool>true</bool> +       <string>policy</string>        </property>       </widget>      </item> -    <item row="6" column="0"> +    <item row="5" column="0">       <spacer name="verticalSpacer_14">        <property name="orientation">         <enum>Qt::Vertical</enum> @@ -374,6 +478,32 @@        </property>       </spacer>      </item> +    <item row="5" column="1"> +     <spacer name="verticalSpacer_15"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item row="5" column="6"> +     <spacer name="verticalSpacer_16"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item>     </layout>    </widget>    <widget class="WizardPage" name="setup_provider_page"> @@ -386,11 +516,47 @@     <attribute name="pageId">      <string notr="true">3</string>     </attribute> -   <layout class="QGridLayout" name="gridLayout_5"> -    <item row="1" column="0"> +   <layout class="QVBoxLayout" name="verticalLayout"> +    <item> +     <spacer name="verticalSpacer_3"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>60</height> +       </size> +      </property> +     </spacer> +    </item> +    <item> +     <widget class="QLabel" name="lblSetupProviderExpl"> +      <property name="text"> +       <string>We are downloading some bits that we need to establish a secure connection with the provider for the first time.</string> +      </property> +      <property name="wordWrap"> +       <bool>true</bool> +      </property> +     </widget> +    </item> +    <item> +     <spacer name="verticalSpacer_6"> +      <property name="orientation"> +       <enum>Qt::Vertical</enum> +      </property> +      <property name="sizeHint" stdset="0"> +       <size> +        <width>20</width> +        <height>40</height> +       </size> +      </property> +     </spacer> +    </item> +    <item>       <widget class="QGroupBox" name="groupBox_2">        <property name="title"> -       <string>Checking provider</string> +       <string>Setting up provider</string>        </property>        <layout class="QGridLayout" name="gridLayout_6">         <item row="2" column="1"> @@ -440,21 +606,21 @@         <item row="1" column="0">          <widget class="QLabel" name="label_9">           <property name="text"> -          <string>Download CA Certificate</string> +          <string>Getting info from the Certificate Authority</string>           </property>          </widget>         </item>         <item row="2" column="0">          <widget class="QLabel" name="label_10">           <property name="text"> -          <string>Check CA Certificate Fingerprint</string> +          <string>Do we trust this Certificate Authority?</string>           </property>          </widget>         </item>         <item row="3" column="0">          <widget class="QLabel" name="label_11">           <property name="text"> -          <string>Check API Certificate</string> +          <string>Establishing a trust relationship with this provider</string>           </property>          </widget>         </item> @@ -496,20 +662,7 @@        </layout>       </widget>      </item> -    <item row="0" column="0"> -     <spacer name="verticalSpacer_3"> -      <property name="orientation"> -       <enum>Qt::Vertical</enum> -      </property> -      <property name="sizeHint" stdset="0"> -       <size> -        <width>20</width> -        <height>60</height> -       </size> -      </property> -     </spacer> -    </item> -    <item row="2" column="0"> +    <item>       <spacer name="verticalSpacer_8">        <property name="orientation">         <enum>Qt::Vertical</enum> @@ -662,7 +815,7 @@      <string>Congratulations!</string>     </property>     <property name="subTitle"> -    <string>You have successfully configured the LEAP client.</string> +    <string>You have successfully configured the LEAP Client.</string>     </property>     <attribute name="pageId">      <string notr="true">6</string> diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py index dee3b230..7759b98d 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,20 @@ class Wizard(QtGui.QWizard):      BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$" -    def __init__(self, checker): +    def __init__(self, checker, standalone=False): +        """ +        Constructor for the main Wizard. + +        @param checker: Checker thread that the wizard should use. +        @type checker: CheckerThread +        @param standalone: If True, the application is running as standalone +            and the wizard should display some messages according to this. +        @type standalone: bool +        """          QtGui.QWizard.__init__(self) +        self.standalone = standalone +          self.ui = Ui_Wizard()          self.ui.setupUi(self) @@ -64,14 +76,21 @@ class Wizard(QtGui.QWizard):          self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png")          # Correspondence for services and their name to display +        EIP_LABEL = self.tr("Encrypted Internet") + +        if self._is_need_eip_password_warning(): +            EIP_LABEL += " " + self.tr( +                "(<b>will need admin password to start</b>)") +          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 +254,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 +470,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 +507,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 +521,9 @@ class Wizard(QtGui.QWizard):              self.ui.lblProviderDesc.setText(                  "<i>%s</i>" %                  (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 +536,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..e74c4d33 --- /dev/null +++ b/src/leap/util/privilege_policies.py @@ -0,0 +1,82 @@ +# -*- 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 <http://www.gnu.org/licenses/>. +""" +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. + +    @rtype: bool +    """ +    _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 + +        @rtype: bool +        """ +        return not os.path.isfile(self.LINUX_POLKIT_FILE) | 
