From 26b92825384e5836a407758fa4b6b14d8726bb9b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 4 Nov 2015 11:36:57 -0300 Subject: [bug] fix typo on signal name - Resolves: #7568 --- src/leap/bitmask/services/mail/conductor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 68197d9d..b79ea9c7 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -113,7 +113,7 @@ class IMAPControl(object): """ Callback for IMAP failed state. """ - self.imap_connection.qtsigs.connetion_aborted_signal.emit() + self.imap_connection.qtsigs.connection_aborted_signal.emit() class SMTPControl(object): -- cgit v1.2.3 From f4b0c01b6737e4266f12276e6b2a058bf3c0f743 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 11 Nov 2015 19:42:09 +0100 Subject: [but] Fix errback on InvalidAuthToken - Related: #7583 --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 60a2130b..a10a2731 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -654,7 +654,7 @@ class Syncer(object): logger.error('Invalid auth token while trying to sync Soledad') self._signaler.signal( self._signaler.soledad_invalid_auth_token) - self._callback_deferred.fail(failure) + self._callback_deferred.errback(failure) elif failure.check(sqlite_ProgrammingError, sqlcipher_ProgrammingError): logger.exception("%r" % (failure.value,)) -- cgit v1.2.3 From 97de43f5ef1b7fa4735e3371581bfaf4c3919de3 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 30 Nov 2015 12:12:57 -0400 Subject: [docs] fix outdated signature description --- src/leap/bitmask/services/mail/imap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 5934756d..b06c1d4a 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -61,7 +61,7 @@ def start_imap_service(*args, **kwargs): """ Initializes and run imap service. - :returns: twisted.internet.task.LoopingCall instance + :returns: LeapIMAPFactory instance """ from leap.bitmask.config import flags logger.debug('Launching imap service') -- cgit v1.2.3 From 8d3309701af51df3046aa0df10545dfa35a64ef7 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 30 Nov 2015 12:15:09 -0400 Subject: [feat] multi-user events. Adapt to users emitting the userid/uuid too. - Resolves: #7656 - Releases: 0.10.0 --- src/leap/bitmask/services/mail/conductor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index b79ea9c7..738531e6 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -73,12 +73,13 @@ class IMAPControl(object): self._backend.imap_stop_service() - def _handle_imap_events(self, event, content): + def _handle_imap_events(self, event, userid=None, content=None): """ Callback handler for the IMAP events :param event: The event that triggered the callback. :type event: str + :param userid: The user id of the logged in user. Ignored. :param content: The content of the event. :type content: list """ -- cgit v1.2.3 From 6c0299e7e2df65651ff8738fa18acbc08af18c32 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 30 Nov 2015 16:31:10 -0400 Subject: [style] autopep8 --- src/leap/bitmask/services/mail/conductor.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 738531e6..b94b3cc8 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -34,6 +34,7 @@ class IMAPControl(object): """ Methods related to IMAP control. """ + def __init__(self): """ Initializes smtp variables. @@ -118,6 +119,7 @@ class IMAPControl(object): class SMTPControl(object): + def __init__(self): """ Initializes smtp variables. -- cgit v1.2.3 From 98384361a7c49ad4e0ff0127fd923a8b72cc910a Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 8 Dec 2015 21:04:11 -0400 Subject: [feat] adapt to use cred-based authentication for imap This includes getting the token for the imap authentication, and displaying it on the help window. - Resolves: #4469 - Releases: 0.10.0 --- src/leap/bitmask/services/mail/imap.py | 31 ++++++++++++------------ src/leap/bitmask/services/mail/imapcontroller.py | 8 +++--- 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index b06c1d4a..54935f8c 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -20,11 +20,14 @@ Initialization of imap service import os import sys +from twisted.python import log + from leap.bitmask.logs.utils import get_logger from leap.mail.constants import INBOX_NAME from leap.mail.imap.service import imap from leap.mail.incoming.service import IncomingMail, INCOMING_CHECK_PERIOD -from twisted.python import log +from leap.mail.mail import Account + logger = get_logger() @@ -57,11 +60,13 @@ def get_mail_check_period(): return period -def start_imap_service(*args, **kwargs): +def start_imap_service(soledad_sessions): """ Initializes and run imap service. - :returns: LeapIMAPFactory instance + :returns: the port as returned by the reactor when starts listening, and + the factory for the protocol. + :rtype: tuple """ from leap.bitmask.config import flags logger.debug('Launching imap service') @@ -70,10 +75,10 @@ def start_imap_service(*args, **kwargs): log.startLogging(open(flags.MAIL_LOGFILE, 'w')) log.startLogging(sys.stdout) - return imap.run_service(*args, **kwargs) + return imap.run_service(soledad_sessions) -def start_incoming_mail_service(keymanager, soledad, imap_factory, userid): +def start_incoming_mail_service(keymanager, soledad, userid): """ Initalizes and starts the incomming mail service. @@ -81,19 +86,13 @@ def start_incoming_mail_service(keymanager, soledad, imap_factory, userid): """ def setUpIncomingMail(inbox): incoming_mail = IncomingMail( - keymanager, - soledad, - inbox.collection, - userid, + keymanager, soledad, + inbox, userid, check_period=get_mail_check_period()) return incoming_mail - # XXX: do I really need to know here how to get a mailbox?? - # XXX: ideally, the parent service in mail would take care of initializing - # the account, and passing the mailbox to the incoming service. - # In an even better world, we just would subscribe to a channel that would - # pass us the serialized object to be inserted. - acc = imap_factory.theAccount - d = acc.callWhenReady(lambda _: acc.getMailbox(INBOX_NAME)) + acc = Account(soledad) + d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME)) d.addCallback(setUpIncomingMail) + d.addErrback(log.err) return d diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index 5053d897..855fb74b 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -60,9 +60,9 @@ class IMAPController(object): """ logger.debug('Starting imap service') + soledad_sessions = {userid: self._soledad} self.imap_port, self.imap_factory = imap.start_imap_service( - self._soledad, - userid=userid) + soledad_sessions) def start_and_assign_incoming_service(incoming_mail): # this returns a deferred that will be called when the looping call @@ -74,9 +74,7 @@ class IMAPController(object): if offline is False: d = imap.start_incoming_mail_service( - self._keymanager, - self._soledad, - self.imap_factory, + self._keymanager, self._soledad, userid) d.addCallback(start_and_assign_incoming_service) d.addErrback(lambda f: logger.error(f.printTraceback())) -- cgit v1.2.3 From 7b80dd1fca9828331f3327c418913539a3a303c0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 16 Dec 2015 15:33:25 -0400 Subject: [feat] adapt to use cred-based authentication for smtp --- src/leap/bitmask/services/mail/smtpbootstrapper.py | 33 +++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index a577509e..dadf59dd 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -19,6 +19,7 @@ SMTP bootstrapping """ import os import warnings +from collections import namedtuple from requests.exceptions import HTTPError @@ -127,9 +128,6 @@ class SMTPBootstrapper(AbstractBootstrapper): Start the smtp service using the downloaded configurations. """ # TODO Make the encrypted_only configurable - # TODO pick local smtp port in a better way - # TODO remove hard-coded port and let leap.mail set - # the specific default. # TODO handle more than one host and define how to choose hosts = self._smtp_config.get_hosts() hostname = hosts.keys()[0] @@ -138,19 +136,25 @@ class SMTPBootstrapper(AbstractBootstrapper): client_cert_path = self._smtp_config.get_client_cert_path( self._userid, self._provider_config, about_to_download=True) - from leap.mail.smtp import setup_smtp_gateway + # XXX this should be defined in leap.mail.smtp, it's in bitmask.core + # right now. + SendmailOpts = namedtuple( + 'SendmailOpts', ['cert', 'key', 'hostname', 'port']) - self._smtp_service, self._smtp_port = setup_smtp_gateway( - port=2013, - userid=self._userid, - keymanager=self._keymanager, - smtp_host=host, - smtp_port=port, - smtp_cert=client_cert_path, - smtp_key=client_cert_path, - encrypted_only=False) + userid = self._userid + soledad_sessions = {userid: self._soledad} + keymanager_sessions = {userid: self._keymanager} - def start_smtp_service(self, keymanager, userid, download_if_needed=False): + key = cert = client_cert_path + opts = SendmailOpts(cert, key, host, port) + sendmail_opts = {userid: opts} + + from leap.mail.smtp import run_service + self._smtp_service, self._smtp_port = run_service( + soledad_sessions, keymanager_sessions, sendmail_opts) + + def start_smtp_service(self, soledad, keymanager, userid, + download_if_needed=False): """ Starts the SMTP service. @@ -170,6 +174,7 @@ class SMTPBootstrapper(AbstractBootstrapper): raise MalformedUserId() self._provider_config = ProviderConfig.get_provider_config(domain) + self._soledad = soledad self._keymanager = keymanager self._smtp_config = SMTPConfig() self._userid = str(userid) -- cgit v1.2.3 From 21a0e07ffccbee57fa02f20525441f96516132dc Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 21 Mar 2016 15:52:43 -0400 Subject: [bug] re-download smtp certificate if needed. the should_redownload function was only called if the pemfile was not present of the fs. - Resolves: #7869 --- src/leap/bitmask/services/mail/smtpbootstrapper.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index dadf59dd..f73687a7 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -29,7 +29,6 @@ from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.mail.smtpconfig import SMTPConfig -from leap.bitmask.util import is_file from leap.common import certs as leap_certs from leap.common.check import leap_assert @@ -93,11 +92,13 @@ class SMTPBootstrapper(AbstractBootstrapper): client_cert_path = self._smtp_config.get_client_cert_path( self._userid, self._provider_config, about_to_download=True) - if not is_file(client_cert_path): + needs_download = leap_certs.should_redownload(client_cert_path) + + if needs_download: # For re-download if something is wrong with the cert + # FIXME this doesn't read well. should reword the logic here. self._download_if_needed = ( - self._download_if_needed and - not leap_certs.should_redownload(client_cert_path)) + self._download_if_needed and not needs_download) if self._download_if_needed and os.path.isfile(client_cert_path): check_and_fix_urw_only(client_cert_path) -- cgit v1.2.3 From c866892b988912a5b9a88edfd6d1e71491617822 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 23 Mar 2016 11:53:15 -0400 Subject: [feature] quick integration with legacy gui --- src/leap/bitmask/services/mail/conductor.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index b94b3cc8..05fafa1a 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -192,7 +192,17 @@ class SMTPControl(object): self.smtp_connection.qtsigs.connection_aborted_signal.emit() -class MailConductor(IMAPControl, SMTPControl): +class PixelatedControl(object): + + def start_pixelated_service(self): + self._backend.pixelated_start_service( + full_user_id=self.userid) + + def stop_pixelated_service(self): + pass + + +class MailConductor(IMAPControl, SMTPControl, PixelatedControl): """ This class encapsulates everything related to the initialization and process control for the mail services. @@ -269,6 +279,9 @@ class MailConductor(IMAPControl, SMTPControl): self.start_smtp_service(download_if_needed=download_if_needed) self.start_imap_service() + # TODO --- check if it's enabled!!! + self.start_pixelated_service() + self._mail_services_started = True def stop_mail_services(self): -- cgit v1.2.3 From e92e4f1e4d57957af5d8c9e08a6c3c9152409612 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 23 Mar 2016 12:03:46 -0400 Subject: [feature] allow to disable pixelmail integration --- src/leap/bitmask/services/mail/conductor.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 05fafa1a..cccbcf14 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -18,6 +18,7 @@ Mail Services Conductor """ from leap.bitmask.config import flags +from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.logs.utils import get_logger from leap.bitmask.gui import statemachines from leap.bitmask.services.mail import connection as mail_connection @@ -279,8 +280,10 @@ class MailConductor(IMAPControl, SMTPControl, PixelatedControl): self.start_smtp_service(download_if_needed=download_if_needed) self.start_imap_service() - # TODO --- check if it's enabled!!! - self.start_pixelated_service() + settings = LeapSettings() + pixelmail = settings.get_pixelmail_enabled() + if pixelmail: + self.start_pixelated_service() self._mail_services_started = True -- cgit v1.2.3 From 541cf77d2c7bc9202474cce4c10b535a9c225ccd Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 28 Mar 2016 12:28:52 -0400 Subject: [bug] set standalone flag properly otherwise, the configs are saved to the user home config folder. --- src/leap/bitmask/services/__init__.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py index 54426669..d86f8aa4 100644 --- a/src/leap/bitmask/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py @@ -154,6 +154,9 @@ def download_service_config(provider_config, service_config, # Not modified service_path = ("leap", "providers", provider_config.get_domain(), service_json) + + service_config.__class__.standalone = flags.STANDALONE + if res.status_code == 304: logger.debug( "{0} definition has not been modified".format( -- cgit v1.2.3 From 62e9ae1bc0e28961e10b46646f6131152844d94c Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 28 Mar 2016 12:29:57 -0400 Subject: [bug] instantiate soledadconfig if needed --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index a10a2731..21cdee31 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -331,6 +331,9 @@ class SoledadBootstrapper(AbstractBootstrapper): :returns: the server url :rtype: unicode """ + if not self._soledad_config: + self._soledad_config = SoledadConfig() + # TODO: Select server based on timezone (issue #3308) server_dict = self._soledad_config.get_hosts() -- cgit v1.2.3 From 92f4b40ab48ec537aade244af3e3e4f2c17b1475 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 15 Apr 2016 16:10:00 -0400 Subject: [refactor] adapt to the new Account signature --- src/leap/bitmask/services/mail/imap.py | 2 +- src/leap/bitmask/services/mail/plumber.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 54935f8c..2f000b2a 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -91,7 +91,7 @@ def start_incoming_mail_service(keymanager, soledad, userid): check_period=get_mail_check_period()) return incoming_mail - acc = Account(soledad) + acc = Account(soledad, userid) d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME)) d.addCallback(setUpIncomingMail) d.addErrback(log.err) diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py index 43203f0c..cd1f06bb 100644 --- a/src/leap/bitmask/services/mail/plumber.py +++ b/src/leap/bitmask/services/mail/plumber.py @@ -60,6 +60,7 @@ def initialize_soledad(uuid, email, passwd, cert_file = "" class Mock(object): + def __init__(self, return_value=None): self._return = return_value @@ -140,7 +141,7 @@ class MBOXPlumber(object): self.sol = initialize_soledad( self.uuid, self.userid, self.passwd, secrets, localdb, "/tmp", "/tmp") - self.acct = IMAPAccount(self.userid, self.sol) + self.acct = IMAPAccount(self.sol, self.userid) return True # -- cgit v1.2.3 From e9e9abc4ec26be29b3a6b09e6a0b67786269183b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 29 Jan 2016 13:18:36 -0800 Subject: [feature] privileged bitmask helper This is still quite untested, and a bit hacky, but the main idea behind let us have a daemonized bitmask helper, that should be installed by the Bitmask installer. Its responsibilities are to launch the vpn process as a privileged user, and start/stop the firewall. --- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 63 ++++--- src/leap/bitmask/services/eip/vpnlauncher.py | 8 +- src/leap/bitmask/services/eip/vpnprocess.py | 188 +++++++++++++++------ 3 files changed, 186 insertions(+), 73 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index 17fc11c2..42d9576b 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -20,6 +20,7 @@ Darwin VPN launcher implementation. import commands import getpass import os +import socket import sys from leap.bitmask.logs.utils import get_logger @@ -34,17 +35,47 @@ class EIPNoTunKextLoaded(VPNLauncherException): pass +class DarwinHelperCommand(object): + + SOCKET_ADDR = '/tmp/bitmask-helper.socket' + + def __init__(self): + pass + + def _connect(self): + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + self._sock.connect(self.SOCKET_ADDR) + except socket.error, msg: + raise RuntimeError(msg) + + def send(self, cmd, args=''): + # TODO check cmd is in allowed list + self._connect() + sock = self._sock + data = "" + + command = cmd + ' ' + args + '/CMD' + + try: + sock.sendall(command) + while '\n' not in data: + data += sock.recv(32) + finally: + sock.close() + + return data + + class DarwinVPNLauncher(VPNLauncher): """ VPN launcher for the Darwin Platform """ - COCOASUDO = "cocoasudo" - # XXX need the good old magic translate for these strings - # (look for magic in 0.2.0 release) - SUDO_MSG = ("Bitmask needs administrative privileges to run " - "Encrypted Internet.") - INSTALL_MSG = ("\"Bitmask needs administrative privileges to install " - "missing scripts and fix permissions.\"") + UP_SCRIPT = None + DOWN_SCRIPT = None + + # TODO -- move this to bitmask-helper + # Hardcode the installation path for OSX for security, openvpn is # run as root @@ -56,14 +87,9 @@ class DarwinVPNLauncher(VPNLauncher): INSTALL_PATH_ESCAPED,) OPENVPN_BIN_PATH = "%s/Contents/Resources/%s" % (INSTALL_PATH, OPENVPN_BIN) - - UP_SCRIPT = "%s/client.up.sh" % (OPENVPN_PATH,) - DOWN_SCRIPT = "%s/client.down.sh" % (OPENVPN_PATH,) - OPENVPN_DOWN_PLUGIN = '%s/openvpn-down-root.so' % (OPENVPN_PATH,) - - UPDOWN_FILES = (UP_SCRIPT, DOWN_SCRIPT, OPENVPN_DOWN_PLUGIN) OTHER_FILES = [] + # TODO deprecate ------------------------------------------------ @classmethod def cmd_for_missing_scripts(kls, frompath): """ @@ -87,7 +113,7 @@ class DarwinVPNLauncher(VPNLauncher): :returns: True if kext is loaded, False otherwise. :rtype: bool """ - return bool(commands.getoutput('kextstat | grep "leap.tun"')) + return bool(commands.getoutput('kextstat | grep "foo.tun"')) @classmethod def _get_icon_path(kls): @@ -101,6 +127,8 @@ class DarwinVPNLauncher(VPNLauncher): return os.path.join(resources_path, "bitmask.tiff") + + # TODO deprecate --------------------------------------------------------- @classmethod def get_cocoasudo_ovpn_cmd(kls): """ @@ -120,6 +148,7 @@ class DarwinVPNLauncher(VPNLauncher): return kls.COCOASUDO, args + # TODO deprecate --------------------------------------------------------- @classmethod def get_cocoasudo_installmissing_cmd(kls): """ @@ -171,12 +200,6 @@ class DarwinVPNLauncher(VPNLauncher): # we use `super` in order to send the class to use command = super(DarwinVPNLauncher, kls).get_vpn_command( eipconfig, providerconfig, socket_host, socket_port, openvpn_verb) - - cocoa, cargs = kls.get_cocoasudo_ovpn_cmd() - cargs.extend(command) - command = cargs - command.insert(0, cocoa) - command.extend(['--setenv', "LEAPUSER", getpass.getuser()]) return command diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index c48f857c..16dfd9cf 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -29,7 +29,7 @@ from leap.bitmask.config import flags from leap.bitmask.logs.utils import get_logger from leap.bitmask.backend.settings import Settings, GATEWAY_AUTOMATIC from leap.bitmask.config.providerconfig import ProviderConfig -from leap.bitmask.platform_init import IS_LINUX +from leap.bitmask.platform_init import IS_LINUX, IS_MAC from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector from leap.bitmask.util import force_eval from leap.common.check import leap_assert, leap_assert_type @@ -286,8 +286,8 @@ class VPNLauncher(object): :rtype: list """ # FIXME - # XXX remove method when we ditch UPDOWN in osx and win too - if IS_LINUX: + # XXX remove method when we ditch UPDOWN in win too + if IS_LINUX or IS_MAC: return [] else: leap_assert(kls.UPDOWN_FILES is not None, @@ -308,7 +308,7 @@ class VPNLauncher(object): """ leap_assert(kls.OTHER_FILES is not None, "Need to define OTHER_FILES for this particular " - "auncher before calling this method") + "launcher before calling this method") other = force_eval(kls.OTHER_FILES) file_exist = partial(_has_other_files, warn=False) diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 586b50f5..6d18a599 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -23,6 +23,7 @@ import shutil import socket import subprocess import sys +import time from itertools import chain, repeat @@ -41,6 +42,7 @@ from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.logs.utils import get_logger from leap.bitmask.services.eip import get_vpn_launcher from leap.bitmask.services.eip import linuxvpnlauncher +from leap.bitmask.services.eip import darwinvpnlauncher from leap.bitmask.services.eip.eipconfig import EIPConfig from leap.bitmask.services.eip.udstelnet import UDSTelnet from leap.bitmask.util import first, force_eval @@ -145,7 +147,7 @@ class VPN(object): demand. """ TERMINATE_MAXTRIES = 10 - TERMINATE_WAIT = 1 # secs + TERMINATE_WAIT = 2 # secs OPENVPN_VERB = "openvpn_verb" @@ -173,7 +175,7 @@ class VPN(object): :param kwargs: kwargs to be passed to the VPNProcess :type kwargs: dict """ - logger.debug('VPN: start') + logger.debug('VPN: start ---------------------------------------------------') self._user_stopped = False self._stop_pollers() kwargs['openvpn_verb'] = self._openvpn_verb @@ -181,22 +183,6 @@ class VPN(object): restart = kwargs.pop('restart', False) - # start the main vpn subprocess - vpnproc = VPNProcess(*args, **kwargs) - - if vpnproc.get_openvpn_process(): - logger.info("Another vpn process is running. Will try to stop it.") - vpnproc.stop_if_already_running() - - # we try to bring the firewall up - if IS_LINUX: - gateways = vpnproc.getGateways() - firewall_up = self._launch_firewall(gateways, - restart=restart) - if not restart and not firewall_up: - logger.error("Could not bring firewall up, " - "aborting openvpn launch.") - return # FIXME it would be good to document where the # errors here are catched, since we currently handle them @@ -211,18 +197,56 @@ class VPN(object): # the ping-pong to the frontend, and without adding any logical checks # in the frontend. We should just communicate UI changes to frontend, # and abstract us away from anything else. - try: + + # TODO factor this out to the platform-launchers + + if IS_LINUX: + # start the main vpn subprocess + vpnproc = VPNProcess(*args, **kwargs) cmd = vpnproc.getCommand() - except Exception as e: - logger.error("Error while getting vpn command... {0!r}".format(e)) - raise + + if vpnproc.get_openvpn_process(): + logger.info("Another vpn process is running. Will try to stop it.") + vpnproc.stop_if_already_running() + + # we try to bring the firewall up + gateways = vpnproc.getGateways() + firewall_up = self._launch_firewall_linux( + gateways, restart=restart) + if not restart and not firewall_up: + logger.error("Could not bring firewall up, " + "aborting openvpn launch.") + return + + if IS_MAC: + # start the main vpn subprocess + vpnproc = VPNCanary(*args, **kwargs) + + # we try to bring the firewall up + gateways = vpnproc.getGateways() + firewall_up = self._launch_firewall_osx( + gateways, restart=restart) + if not restart and not firewall_up: + logger.error("Could not bring firewall up, " + "aborting openvpn launch.") + return + + helper = darwinvpnlauncher.DarwinHelperCommand() + cmd = vpnproc.getVPNCommand() + result = helper.send('openvpn_start %s' % ' '.join(cmd)) + + # TODO Windows version -- should be similar to osx. env = os.environ for key, val in vpnproc.vpn_env.items(): env[key] = val - reactor.spawnProcess(vpnproc, cmd[0], cmd, env) + cmd = vpnproc.getCommand() + running_proc = reactor.spawnProcess(vpnproc, cmd[0], cmd, env) + vpnproc.pid = running_proc.pid self._vpnproc = vpnproc + + # add pollers for status and state # this could be extended to a collection of @@ -233,9 +257,9 @@ class VPN(object): self._pollers.extend(poll_list) self._start_pollers() - def _launch_firewall(self, gateways, restart=False): + def _launch_firewall_linux(self, gateways, restart=False): """ - Launch the firewall using the privileged wrapper. + Launch the firewall using the privileged wrapper (linux). :param gateways: :type gateways: list @@ -254,40 +278,63 @@ class VPN(object): exitCode = subprocess.call(cmd + gateways) return True if exitCode is 0 else False + def _launch_firewall_osx(self, gateways, restart=False): + cmd = 'firewall_start %s' % ' '.join(gateways) + helper = darwinvpnlauncher.DarwinHelperCommand() + result = helper.send(cmd) + return True + + # TODO -- write LINUX/OSX VERSION too ------------------------------------ def is_fw_down(self): """ Return whether the firewall is down or not. :rtype: bool """ - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) - fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) - fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 - return fw_is_down() + if IS_LINUX: + BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) + fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 + return fw_is_down() + + if IS_MAC: + cmd = 'firewall_isup' + helper = darwinvpnlauncher.DarwinHelperCommand() + result = helper.send(cmd) + return True + def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. """ if IS_MAC: - # We don't support Mac so far + cmd = 'firewall_stop' + helper = darwinvpnlauncher.DarwinHelperCommand() + result = helper.send(cmd) return True - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) - exitCode = subprocess.call(["pkexec", - BM_ROOT, "firewall", "stop"]) - return True if exitCode is 0 else False + + if IS_LINUX: + BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + exitCode = subprocess.call(["pkexec", + BM_ROOT, "firewall", "stop"]) + return True if exitCode is 0 else False def bitmask_root_vpn_down(self): """ Bring openvpn down using the privileged wrapper. """ if IS_MAC: - # We don't support Mac so far + cmd = 'openvpn_stop' + helper = darwinvpnlauncher.DarwinHelperCommand() + result = helper.send(cmd) return True - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) - exitCode = subprocess.call(["pkexec", - BM_ROOT, "openvpn", "stop"]) - return True if exitCode is 0 else False + + if IS_LINUX: + BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + exitCode = subprocess.call(["pkexec", + BM_ROOT, "openvpn", "stop"]) + return True if exitCode is 0 else False def _kill_if_left_alive(self, tries=0): """ @@ -297,18 +344,18 @@ class VPN(object): :param tries: counter of tries, used in recursion :type tries: int """ + # we try to tear the firewall down + if (IS_LINUX or IS_MAC) and self._user_stopped: + logger.debug('trying to bring firewall down...') + firewall_down = self.tear_down_firewall() + if firewall_down: + logger.debug("Firewall down") + else: + logger.warning("Could not tear firewall down") + while tries < self.TERMINATE_MAXTRIES: if self._vpnproc.transport.pid is None: logger.debug("Process has been happily terminated.") - - # we try to tear the firewall down - if IS_LINUX and self._user_stopped: - firewall_down = self.tear_down_firewall() - if firewall_down: - logger.debug("Firewall down") - else: - logger.warning("Could not tear firewall down") - return else: logger.debug("Process did not die, waiting...") @@ -813,6 +860,8 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): programmatically. """ + pid = None + def __init__(self, eipconfig, providerconfig, socket_host, socket_port, signaler, openvpn_verb): """ @@ -861,7 +910,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): self._vpn_observer = VPNObserver(signaler) self.is_restart = False - # processProtocol methods + # ProcessProtocol methods def connectionMade(self): """ @@ -893,8 +942,11 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): .. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa """ exit_code = reason.value.exitCode + if isinstance(exit_code, int): logger.debug("processExited, status %d" % (exit_code,)) + else: + exit_code = 0 self._signaler.signal( self._signaler.eip_process_finished, exit_code) self._alive = False @@ -976,3 +1028,41 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): self.transport.signalProcess('KILL') except internet_error.ProcessExitedAlready: logger.debug('Process Exited Already') + + +class VPNCanary(VPNProcess): + + """ + This is a Canary Process that does not run openvpn itself, but it's + notified by the privileged process when the process dies. + + This is an ugly workaround to allow the qt signals and the processprotocol + to live happily together until we refactor EIP out of the qt model + completely. + """ + + def connectionMade(self): + VPNProcess.connectionMade(self) + reactor.callLater(2, self.registerPID) + + def registerPID(self): + helper = darwinvpnlauncher.DarwinHelperCommand() + cmd = 'openvpn_set_watcher %s' % self.pid + result = helper.send(cmd) + + def killProcess(self): + helper = darwinvpnlauncher.DarwinHelperCommand() + cmd = 'openvpn_force_stop' + result = helper.send(cmd) + + def getVPNCommand(self): + return VPNProcess.getCommand(self) + + def getCommand(self): + canary = '''import sys, signal, time +def receive_signal(signum, stack): + sys.exit() +signal.signal(signal.SIGTERM, receive_signal) +while True: + time.sleep(60)''' + return ['python', '-c', '%s' % canary] -- cgit v1.2.3 From 9affaaacb18598fc98be669ef1c086b0afe4ad91 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 11 Feb 2016 13:34:46 -0800 Subject: [refactor] cleanup helper usage to adapt to new one also cleanups build process --- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 4 +--- src/leap/bitmask/services/eip/vpnprocess.py | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index 42d9576b..f1d17698 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -54,7 +54,7 @@ class DarwinHelperCommand(object): self._connect() sock = self._sock data = "" - + command = cmd + ' ' + args + '/CMD' try: @@ -76,7 +76,6 @@ class DarwinVPNLauncher(VPNLauncher): # TODO -- move this to bitmask-helper - # Hardcode the installation path for OSX for security, openvpn is # run as root INSTALL_PATH = "/Applications/Bitmask.app/" @@ -127,7 +126,6 @@ class DarwinVPNLauncher(VPNLauncher): return os.path.join(resources_path, "bitmask.tiff") - # TODO deprecate --------------------------------------------------------- @classmethod def get_cocoasudo_ovpn_cmd(kls): diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 6d18a599..de8d92f3 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -175,7 +175,8 @@ class VPN(object): :param kwargs: kwargs to be passed to the VPNProcess :type kwargs: dict """ - logger.debug('VPN: start ---------------------------------------------------') + logger.debug( + 'VPN: start ---------------------------------------------------') self._user_stopped = False self._stop_pollers() kwargs['openvpn_verb'] = self._openvpn_verb @@ -183,7 +184,6 @@ class VPN(object): restart = kwargs.pop('restart', False) - # FIXME it would be good to document where the # errors here are catched, since we currently handle them # at the frontend layer. This *should* move to be handled entirely @@ -206,7 +206,8 @@ class VPN(object): cmd = vpnproc.getCommand() if vpnproc.get_openvpn_process(): - logger.info("Another vpn process is running. Will try to stop it.") + logger.info( + "Another vpn process is running. Will try to stop it.") vpnproc.stop_if_already_running() # we try to bring the firewall up @@ -245,8 +246,6 @@ class VPN(object): running_proc = reactor.spawnProcess(vpnproc, cmd[0], cmd, env) vpnproc.pid = running_proc.pid self._vpnproc = vpnproc - - # add pollers for status and state # this could be extended to a collection of @@ -292,7 +291,8 @@ class VPN(object): :rtype: bool """ if IS_LINUX: - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + BM_ROOT = force_eval( + linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 return fw_is_down() @@ -303,7 +303,6 @@ class VPN(object): result = helper.send(cmd) return True - def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. @@ -315,7 +314,8 @@ class VPN(object): return True if IS_LINUX: - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + BM_ROOT = force_eval( + linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "firewall", "stop"]) return True if exitCode is 0 else False @@ -331,7 +331,8 @@ class VPN(object): return True if IS_LINUX: - BM_ROOT = force_eval(linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) + BM_ROOT = force_eval( + linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT) exitCode = subprocess.call(["pkexec", BM_ROOT, "openvpn", "stop"]) return True if exitCode is 0 else False -- cgit v1.2.3 From d01772d0a83535bf45fa43786213a9a0fcb232bc Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 11 Feb 2016 13:34:46 -0800 Subject: [refactor] cleanup helper usage to adapt to new one also cleanups build process --- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index f1d17698..94161192 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -112,7 +112,10 @@ class DarwinVPNLauncher(VPNLauncher): :returns: True if kext is loaded, False otherwise. :rtype: bool """ - return bool(commands.getoutput('kextstat | grep "foo.tun"')) + loaded = bool(commands.getoutput('kextstat | grep "net.sf.tuntaposx.tun"')) + if not loaded: + logger.error("tuntaposx extension not loaded!") + return loaded @classmethod def _get_icon_path(kls): -- cgit v1.2.3 From 9c3a713ff33c87af03b31ec9ad018a6ca3dfbb97 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 18 Apr 2016 16:22:02 -0400 Subject: [style] autopep8 --- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index 94161192..e697b118 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -112,7 +112,8 @@ class DarwinVPNLauncher(VPNLauncher): :returns: True if kext is loaded, False otherwise. :rtype: bool """ - loaded = bool(commands.getoutput('kextstat | grep "net.sf.tuntaposx.tun"')) + loaded = bool(commands.getoutput( + 'kextstat | grep "net.sf.tuntaposx.tun"')) if not loaded: logger.error("tuntaposx extension not loaded!") return loaded -- cgit v1.2.3 From 5b90ad3552025436edb40665203ab98eceaa065b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 19 Apr 2016 12:07:09 -0400 Subject: pep8/flake8 --- src/leap/bitmask/services/eip/vpnprocess.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index de8d92f3..580bd572 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -23,7 +23,6 @@ import shutil import socket import subprocess import sys -import time from itertools import chain, repeat -- cgit v1.2.3 From a68bbe5e69a3481ede78f518b1637761e8f8cd01 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 20 Apr 2016 12:44:15 -0300 Subject: [bug] let the failure propagate The failure was processed in start_incoming_mail_service what will make it return a None when an IncomingMail object was expected. If we propagate the failure it can be treated properly by the IMAPController. - Related: #8051 --- src/leap/bitmask/services/mail/imap.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 2f000b2a..7875a4af 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -94,5 +94,4 @@ def start_incoming_mail_service(keymanager, soledad, userid): acc = Account(soledad, userid) d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME)) d.addCallback(setUpIncomingMail) - d.addErrback(log.err) return d -- cgit v1.2.3