From bb69e8a2bd6117ee432e7b9ced09f200d61926b7 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 17 Jan 2018 21:03:48 +0100 Subject: [feat] autostart application when user logs in --- docs/changelog.rst | 1 + src/leap/bitmask/config.py | 4 ++++ src/leap/bitmask/vpn/autostart.py | 45 +++++++++++++++++++++++++++++++++++++++ src/leap/bitmask/vpn/service.py | 33 ++++++++++++++++++++++------ 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 src/leap/bitmask/vpn/autostart.py diff --git a/docs/changelog.rst b/docs/changelog.rst index 86f07ea4..c7bca741 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,7 @@ Features - `#9188 `_: try other gateways if the main one fails. - `#9125 `_: port to use qtwebengine for rendering UI. - `#9181 `_: hardcode tcp4 in the vpn connection parameters. +- Autostart VPN if it was running when closed the application. - Set a windows title, so that Bitmask windows can be programmatically manipulated. - Support anonymous vpn. diff --git a/src/leap/bitmask/config.py b/src/leap/bitmask/config.py index 4c1fbca7..17a20d3f 100644 --- a/src/leap/bitmask/config.py +++ b/src/leap/bitmask/config.py @@ -96,4 +96,8 @@ class _ConfigurationSection(object): return self.config.get(self.section, option, default, boolean) def set(self, option, value): + if value is True: + value = 'true' + elif value is False: + value = 'false' return self.config.set(self.section, option, value) diff --git a/src/leap/bitmask/vpn/autostart.py b/src/leap/bitmask/vpn/autostart.py new file mode 100644 index 00000000..43abfdf5 --- /dev/null +++ b/src/leap/bitmask/vpn/autostart.py @@ -0,0 +1,45 @@ +import os +import os.path + +from leap.bitmask.vpn.constants import IS_LINUX, IS_MAC +from leap.bitmask.util import STANDALONE +from leap.common.config import get_path_prefix + +if IS_LINUX: + AUTOSTART = r"""[Desktop Entry] +Name=Bitmask +Type=Application +Exec=bitmask +Terminal=false +""" + config = get_path_prefix(standalone=False) + autostart_file = os.path.join(config, 'autostart', 'bitmask.desktop') + + def autostart_app(status): + """ + Leave an autostart file in the user's autostart path. + + The bundle could in principle find its own path and add + the path to the bitmaskd binary in the Exec entry. + But for now it's simpler to do autostart only for the debian packages + or any other method that puts bitmask in the path. + On the other hand, we want to reduce the modifications that the bundle + leaves behind. + """ + if not STANDALONE: + if status == 'on': + _dir = os.path.split(autostart_file)[0] + if not os.path.isdir(_dir): + os.makedirs(_dir) + with open(autostart_file, 'w') as f: + f.write(AUTOSTART) + elif status == 'off': + os.unlink(autostart_file) + +if IS_MAC: + + def autostart_app_on(): + pass + + def autostart_app_off(): + pass diff --git a/src/leap/bitmask/vpn/service.py b/src/leap/bitmask/vpn/service.py index db4c20af..c12f66dd 100644 --- a/src/leap/bitmask/vpn/service.py +++ b/src/leap/bitmask/vpn/service.py @@ -19,6 +19,7 @@ """ VPN service declaration. """ + import json import os @@ -38,6 +39,7 @@ from leap.bitmask.vpn._checks import ( ) from leap.bitmask.vpn import privilege, helpers +from leap.bitmask.vpn import autostart from leap.common.config import get_path_prefix from leap.common.files import check_and_fix_urw_only from leap.common.events import catalog, emit_async @@ -85,10 +87,10 @@ class VPNService(HookableService): except ValueError: self._loc = [] - _autostart = self._cfg.get('autostart', False) + _autostart = self._cfg.get('autostart', False, boolean=True) self._autostart = _autostart - _anonymous = self._cfg.get('anonymous', True) + _anonymous = self._cfg.get('anonymous', True, boolean=True) self._anonymous_enabled = _anonymous if helpers.check() and self._firewall.is_up(): @@ -114,6 +116,7 @@ class VPNService(HookableService): @defer.inlineCallbacks def start_vpn(self, domain=None): self._cfg.set('autostart', True) + autostart.autostart_app('on') if self.do_status()['status'] == 'on': exc = Exception('VPN already started') exc.expected = True @@ -152,26 +155,42 @@ class VPNService(HookableService): else: data = {'result': 'failed', 'error': '%r' % result} - self.watchdog.start(WATCHDOG_PERIOD) + if not self.watchdog.running: + self.watchdog.start(WATCHDOG_PERIOD) defer.returnValue(data) def stop_vpn(self, shutdown=False): - self._cfg.set('autostart', shutdown) + if shutdown: + if self._tunnel and self._tunnel.status.get('status') == 'on': + self._set_autostart('on') + else: + self._set_autostart('off') + else: + self._set_autostart('off') + if self._firewall.is_up(): fw_ok = self._firewall.stop() if not fw_ok: - self.log.error("Firewall: error stopping") + self.log.error('Firewall: error stopping') if not self._tunnel: return {'result': 'VPN was not running'} vpn_ok = self._tunnel.stop() if not vpn_ok: - raise Exception("Error stopping VPN") + raise Exception('Error stopping VPN') self.watchdog.stop() return {'result': 'vpn stopped'} + def _set_autostart(self, status): + if status.lower() == 'on': + self._cfg.set('autostart', True) + autostart.autostart_app('on') + elif status.lower() == 'off': + self._cfg.set('autostart', False) + autostart.autostart_app('off') + def push_status(self): try: statusdict = self.do_status() @@ -221,7 +240,7 @@ class VPNService(HookableService): # fetch vpn cert and store bonafide = self.parent.getServiceNamed("bonafide") _, cert_str = yield bonafide.do_get_vpn_cert( - username, anonymous=anonymous) + username, anonymous=anonymous) cert_path = get_vpn_cert_path(provider) cert_dir = os.path.dirname(cert_path) -- cgit v1.2.3