From 3d0708ad3e20aa8dddf6894b7536be3cd59cfbca Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 8 Sep 2014 14:22:29 -0500 Subject: Add email firewall --- src/leap/bitmask/services/mail/conductor.py | 19 ++++ src/leap/bitmask/services/mail/emailfirewall.py | 115 ++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/leap/bitmask/services/mail/emailfirewall.py (limited to 'src/leap/bitmask/services/mail') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 5e85368f..416aff34 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -22,6 +22,7 @@ import logging from leap.bitmask.config import flags from leap.bitmask.gui import statemachines from leap.bitmask.services.mail import connection as mail_connection +from leap.bitmask.services.mail.emailfirewall import get_email_firewall from leap.common.events import events_pb2 as leap_events from leap.common.events import register as leap_register @@ -211,6 +212,11 @@ class MailConductor(IMAPControl, SMTPControl): self._mail_connection = mail_connection.MailConnection() self._userid = None + try: + self._firewall = get_email_firewall() + except NotImplementedError: + self._firewall = None + logger.info("Email firewall is not implemented in this platform") @property def userid(self): @@ -247,12 +253,25 @@ class MailConductor(IMAPControl, SMTPControl): self._smtp_machine = smtp self._smtp_machine.start() + def start_mail_service(self, download_if_needed=False, offline=False): + """ + Start the IMAP and SMTP servcies. + """ + if self._firewall is not None: + self._firewall.start() + if not offline: + logger.debug("not starting smtp in offline mode") + self.start_smtp_service(download_if_needed=download_if_needed) + self.start_imap_service() + def stop_mail_services(self): """ Stop the IMAP and SMTP services. """ self.stop_imap_service() self.stop_smtp_service() + if self._firewall is not None: + self._firewall.stop() def connect_mail_signals(self, widget): """ diff --git a/src/leap/bitmask/services/mail/emailfirewall.py b/src/leap/bitmask/services/mail/emailfirewall.py new file mode 100644 index 00000000..2cd2ec31 --- /dev/null +++ b/src/leap/bitmask/services/mail/emailfirewall.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# emailfirewall.py +# Copyright (C) 2014 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 . +""" +Email firewall implementation. +""" + +import os +import subprocess + +from abc import ABCMeta, abstractmethod + +from leap.bitmask.config import flags +from leap.bitmask.platform_init import IS_LINUX +from leap.bitmask.util import first, force_eval +from leap.bitmask.util.privilege_policies import LinuxPolicyChecker +from leap.common.check import leap_assert + + +def get_email_firewall(): + """ + Return the email firewall handler for the current platform. + """ + if not (IS_LINUX): + error_msg = "Email firewall not implemented for this platform." + raise NotImplementedError(error_msg) + + firewall = None + if IS_LINUX: + firewall = LinuxEmailFirewall + + leap_assert(firewall is not None) + + return firewall() + + +class EmailFirewall(object): + """ + Abstract email firwall class + """ + __metaclass__ = ABCMeta + + @abstractmethod + def start(self): + """ + Start email firewall + """ + return False + + @abstractmethod + def stop(self): + """ + Stop email firewall + """ + return False + + +class EmailFirewallException(Exception): + pass + + +class LinuxEmailFirewall(EmailFirewall): + + class BITMASK_ROOT(object): + def __call__(self): + return ("/usr/local/sbin/bitmask-root" if flags.STANDALONE else + "/usr/sbin/bitmask-root") + + def start(self): + uid = str(os.getuid()) + return True if self._run(["start", uid]) is 0 else False + + def stop(self): + return True if self._run(["stop"]) is 0 else False + + def _run(self, cmd): + """ + Run an email firewall command with bitmask-root + + Might raise: + NoPkexecAvailable, + NoPolkitAuthAgentAvailable, + + :param cmd: command to send to bitmask-root fw-email + :type cmd: [str] + :returns: exit code of bitmask-root + :rtype: int + """ + command = [] + + policyChecker = LinuxPolicyChecker() + pkexec = policyChecker.maybe_pkexec() + if pkexec: + command.append(first(pkexec)) + + command.append(force_eval(self.BITMASK_ROOT)) + command.append("fw-email") + command += cmd + + # XXX: will be nice to use twisted ProcessProtocol instead of + # subprocess to avoid blocking until it finish + return subprocess.call(command) -- cgit v1.2.3