From 855e96cefe975e50d140e6c8aa7d3407931b25d7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 1 Oct 2014 16:19:58 -0300 Subject: Quit Bitmask if there is no polkit agent running. Closes #6150. --- changes/bug-6150_better-missing-polkit-msg | 1 + src/leap/bitmask/backend/components.py | 5 +++ src/leap/bitmask/gui/mainwindow.py | 6 ++- src/leap/bitmask/platform_init/initializers.py | 56 +++++++++++++++++++++++--- src/leap/bitmask/services/mail/conductor.py | 8 ++++ src/leap/bitmask/util/polkit_agent.py | 46 +++++++++++++++++---- 6 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 changes/bug-6150_better-missing-polkit-msg diff --git a/changes/bug-6150_better-missing-polkit-msg b/changes/bug-6150_better-missing-polkit-msg new file mode 100644 index 00000000..ee317135 --- /dev/null +++ b/changes/bug-6150_better-missing-polkit-msg @@ -0,0 +1 @@ +- Do not allow Bitmask to start if there is no polkit agent running. Closes #6150. diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py index 50f723cb..87950072 100644 --- a/src/leap/bitmask/backend/components.py +++ b/src/leap/bitmask/backend/components.py @@ -54,6 +54,7 @@ from leap.bitmask.services.mail.smtpconfig import SMTPConfig from leap.bitmask.services.soledad.soledadbootstrapper import \ SoledadBootstrapper from leap.bitmask.util import force_eval +from leap.bitmask.util.privilege_policies import LinuxPolicyChecker from leap.common import certs as leap_certs @@ -638,6 +639,10 @@ class EIP(object): :param domain: the domain for the provider to check :type domain: str """ + if not LinuxPolicyChecker.is_up(): + logger.error("No polkit agent running.") + return False + eip_config = eipconfig.EIPConfig() provider_config = ProviderConfig.get_provider_config(domain) diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 1b61de87..6f44ff01 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -263,8 +263,6 @@ class MainWindow(QtGui.QMainWindow): self.soledad_ready.connect(self._start_mail_service) # ################################ end Qt Signals connection ######## - init_platform() - self._wizard = None self._wizard_firstrun = False @@ -276,6 +274,10 @@ class MainWindow(QtGui.QMainWindow): self.logout.connect(self._mail_conductor.stop_mail_services) + if not init_platform(): + self.quit() + return + # start event machines from within the eip and mail conductors # TODO should encapsulate all actions into one object diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py index 1d6bb1d0..086927dd 100644 --- a/src/leap/bitmask/platform_init/initializers.py +++ b/src/leap/bitmask/platform_init/initializers.py @@ -56,19 +56,24 @@ init_signals = InitSignals() def init_platform(): """ - Return the right initializer for the platform we are running in, or - None if no proper initializer is found + Run the right initializer for the platform we are running in. + + :return: whether the initializacion succeeded or not. + :rtype: bool """ initializer = None + ok = False try: initializer = globals()[_system + "Initializer"] except: pass if initializer: - logger.debug("Running initializer for %s" % (platform.system(),)) - initializer() + logger.debug("Running initializer for %s" % (_system, )) + ok = initializer() else: - logger.debug("Initializer not found for %s" % (platform.system(),)) + logger.debug("Initializer not found for %s" % (_system, )) + + return ok # @@ -181,6 +186,38 @@ def check_missing(): if missing_some and not alert_missing and not complain_missing: init_signals.eip_missing_helpers.emit() + +def check_polkit(): + """ + Check if we have a running polkit agent and tries to launch an agent if + needed. + Show an error message if there is no agent and we couldn't run one. + + :return: True if we have a polkit running (or if we started one), False + otherwise + :rtype: bool + """ + if LinuxPolicyChecker.is_up(): + return True + + try: + LinuxPolicyChecker.maybe_pkexec() + except Exception: + logger.error("No polkit agent running.") + + msg = QtGui.QMessageBox() + msg.setWindowTitle(msg.tr("No polkit agent running")) + msg.setText( + msg.tr('There is no polkit agent running and it is needed to run ' + 'the Bitmask services.
Take a look at the ' + '' + 'known issues page')) + msg.setIcon(QtGui.QMessageBox.Critical) + msg.exec_() + + return False + + # # windows initializers # @@ -377,6 +414,7 @@ def DarwinInitializer(): # Second check, for missing scripts. check_missing() + return True # @@ -483,5 +521,13 @@ def LinuxInitializer(): Missing files can be either bitmask-root policykit file. The dialog will also be raised if some of those files are found to have incorrect permissions. + + :return: whether the operations went ok or not, if False, it's recommended + not to continue with the app run. + :rtype: bool """ + if not check_polkit(): + return False + check_missing() + return True diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 416aff34..0fb9f4fa 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -207,6 +207,8 @@ class MailConductor(IMAPControl, SMTPControl): IMAPControl.__init__(self) SMTPControl.__init__(self) + self._mail_services_started = False + self._backend = backend self._mail_machine = None self._mail_connection = mail_connection.MailConnection() @@ -264,10 +266,16 @@ class MailConductor(IMAPControl, SMTPControl): self.start_smtp_service(download_if_needed=download_if_needed) self.start_imap_service() + self._mail_services_started = True + def stop_mail_services(self): """ Stop the IMAP and SMTP services. """ + if not self._mail_services_started: + logger.debug("Mail services not started.") + return + self.stop_imap_service() self.stop_smtp_service() if self._firewall is not None: diff --git a/src/leap/bitmask/util/polkit_agent.py b/src/leap/bitmask/util/polkit_agent.py index 7764f571..af5e431c 100644 --- a/src/leap/bitmask/util/polkit_agent.py +++ b/src/leap/bitmask/util/polkit_agent.py @@ -18,6 +18,7 @@ Daemonizes polkit authentication agent. """ import logging +import os import subprocess import daemon @@ -30,21 +31,52 @@ BASE_PATH_KDE = "/usr/lib/kde4/libexec/" GNO_PATH = BASE_PATH_GNO + AUTH_FILE % ("gnome",) KDE_PATH = BASE_PATH_KDE + AUTH_FILE % ("kde",) +POLKIT_PATHS = { + '/usr/lib/lxpolkit/lxpolkit', + '/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1', + '/usr/lib/mate-polkit/polkit-mate-authentication-agent-1', + '/usr/lib/kde4/libexec/polkit-kde-authentication-agent-1', +} + + +def _get_polkit_agent(): + """ + Return a valid polkit agent to use. + + :rtype: str or None + """ + # TODO: in caso of having more than one polkit agent we may want to + # stablish priorities. E.g.: lxpolkit over gnome-polkit for minimalistic + # desktops. + for polkit in POLKIT_PATHS: + if os.path.isfile(polkit): + return polkit + + return None + def _launch_agent(): + """ + Launch a polkit authentication agent on a subprocess. + """ + polkit_agent = _get_polkit_agent() + + if polkit_agent is None: + logger.erro("No usable polkit was found.") + return + logger.debug('Launching polkit auth agent') try: - subprocess.call(GNO_PATH) - except Exception as exc: - logger.error('Exception while running polkit authentication agent ' - '%s' % (exc,)) # XXX fix KDE launch. See: #3755 - # try: - # subprocess.call(KDE_PATH) - # except Exception as exc: + subprocess.call(polkit_agent) + except Exception as e: + logger.error('Error launching polkit authentication agent %r' % (e, )) def launch(): + """ + Launch a polkit authentication agent as a daemon. + """ with daemon.DaemonContext(): _launch_agent() -- cgit v1.2.3