From ef57df5a4791f81871f2da42c1bb3086d0ed0815 Mon Sep 17 00:00:00 2001 From: "Kali Kaneko (leap communications)" Date: Wed, 1 Feb 2017 16:12:39 +0100 Subject: [refactor] sort out some imports --- src/leap/bitmask/vpn/_control.py | 20 ++++++++++- src/leap/bitmask/vpn/_management.py | 67 ++++++++++++++++++++++++++----------- src/leap/bitmask/vpn/_telnet.py | 60 +++++++++++++++++++++++++++++++++ src/leap/bitmask/vpn/manager.py | 13 ++++--- src/leap/bitmask/vpn/process.py | 12 +------ src/leap/bitmask/vpn/udstelnet.py | 60 --------------------------------- 6 files changed, 134 insertions(+), 98 deletions(-) create mode 100644 src/leap/bitmask/vpn/_telnet.py delete mode 100644 src/leap/bitmask/vpn/udstelnet.py diff --git a/src/leap/bitmask/vpn/_control.py b/src/leap/bitmask/vpn/_control.py index 82dd90bc..6e942f48 100644 --- a/src/leap/bitmask/vpn/_control.py +++ b/src/leap/bitmask/vpn/_control.py @@ -1,3 +1,21 @@ + +import os + +from twisted.internet.task import LoopingCall +from twisted.internet import reactor +from twisted.logger import Logger + +from .process import VPNProcess +from .constants import IS_MAC + +logger = Logger() + +# NOTE: We need to set a bigger poll time in OSX because it seems +# openvpn malfunctions when you ask it a lot of things in a short +# amount of time. +POLL_TIME = 2.5 if IS_MAC else 1.0 + + class VPNControl(object): """ This is the high-level object that the service is dealing with. @@ -181,7 +199,7 @@ class VPNControl(object): and start the looping call for them. """ for poller in self._pollers: - poller.start(VPNManager.POLL_TIME) + poller.start(POLL_TIME) def _stop_pollers(self): diff --git a/src/leap/bitmask/vpn/_management.py b/src/leap/bitmask/vpn/_management.py index 51120a34..9ae90118 100644 --- a/src/leap/bitmask/vpn/_management.py +++ b/src/leap/bitmask/vpn/_management.py @@ -1,4 +1,24 @@ -from leap.bitmask.vpn.constants import IS_MAC +import os +import shutil +import socket + +from twisted.internet import defer, reactor +from twisted.logger import Logger + +import psutil +try: + # psutil < 2.0.0 + from psutil.error import AccessDenied as psutil_AccessDenied + PSUTIL_2 = False +except ImportError: + # psutil >= 2.0.0 + from psutil import AccessDenied as psutil_AccessDenied + PSUTIL_2 = True + +from ._telnet import UDSTelnet + + +logger = Logger() class OpenVPNAlreadyRunning(Exception): @@ -23,10 +43,6 @@ class VPNManagement(object): """ # Timers, in secs - # NOTE: We need to set a bigger poll time in OSX because it seems - # openvpn malfunctions when you ask it a lot of things in a short - # amount of time. - POLL_TIME = 2.5 if IS_MAC else 1.0 CONNECTION_RETRY_TIME = 1 def __init__(self, signaler=None): @@ -81,7 +97,7 @@ class VPNManagement(object): except socket.error: # XXX should get a counter and repeat only # after mod X times. - logger.warning('socket error (command was: "%s")' % (command,)) + logger.warn('socket error (command was: "%s")' % (command,)) self._close_management_socket(announce=False) logger.debug('trying to connect to management again') self.try_to_connect_to_management(max_retries=5) @@ -89,8 +105,8 @@ class VPNManagement(object): # XXX should move this to a errBack! except Exception as e: - logger.warning("Error sending command %s: %r" % - (command, e)) + logger.warn("Error sending command %s: %r" % + (command, e)) return [] def _close_management_socket(self, announce=True): @@ -135,7 +151,7 @@ class VPNManagement(object): # XXX move this to the Errback except Exception as e: - logger.warning("Could not connect to OpenVPN yet: %r" % (e,)) + logger.warn("Could not connect to OpenVPN yet: %r" % (e,)) self._tn = None def _connectCb(self, *args): @@ -155,7 +171,7 @@ class VPNManagement(object): :param failure: Failure """ - logger.warning(failure) + logger.warn(failure) def connect_to_management(self, host, port): """ @@ -192,8 +208,8 @@ class VPNManagement(object): :type retry: int """ if max_retries and retry > max_retries: - logger.warning("Max retries reached while attempting to connect " - "to management. Aborting.") + logger.warn("Max retries reached while attempting to connect " + "to management. Aborting.") self.aborted = True return @@ -230,7 +246,8 @@ class VPNManagement(object): state = status_step if state != self._last_state: if self._signaler is not None: - self._signaler.signal(self._signaler.eip_state_changed, state) + self._signaler.signal( + self._signaler.eip_state_changed, state) self._last_state = state def _parse_status_and_notify(self, output): @@ -269,7 +286,8 @@ class VPNManagement(object): status = (tun_tap_read, tun_tap_write) if status != self._last_status: if self._signaler is not None: - self._signaler.signal(self._signaler.eip_status_changed, status) + self._signaler.signal( + self._signaler.eip_status_changed, status) self._last_status = status def get_state(self): @@ -313,7 +331,7 @@ class VPNManagement(object): """ if self._socket_port == "unix": logger.debug('cleaning socket file temp folder') - tempfolder = first(os.path.split(self._socket_host)) + tempfolder = _first(os.path.split(self._socket_host)) if tempfolder and os.path.isdir(tempfolder): try: shutil.rmtree(tempfolder) @@ -371,12 +389,16 @@ class VPNManagement(object): cmdline = process.cmdline manag_flag = "--management" + if isinstance(cmdline, list) and manag_flag in cmdline: + # we know that our invocation has this distinctive fragment, so # we use this fingerprint to tell other invocations apart. # this might break if we change the configuration path in the # launchers - smellslikeleap = lambda s: "leap" in s and "providers" in s + + def smellslikeleap(s): + return "leap" in s and "providers" in s if not any(map(smellslikeleap, cmdline)): logger.debug("We cannot stop this instance since we do not " @@ -401,8 +423,8 @@ class VPNManagement(object): self._send_command("signal SIGTERM") self._close_management_socket(announce=True) except (Exception, AssertionError) as e: - logger.warning("Problem trying to terminate OpenVPN: %r" - % (e,)) + logger.warn("Problem trying to terminate OpenVPN: %r" + % (e,)) else: logger.debug("Could not find the expected openvpn command line.") @@ -412,5 +434,12 @@ class VPNManagement(object): "openvpn process.") return True else: - logger.warning("Unable to terminate OpenVPN") + logger.warn("Unable to terminate OpenVPN") raise OpenVPNAlreadyRunning + + +def _first(things): + try: + return things[0] + except (IndexError, TypeError): + return None diff --git a/src/leap/bitmask/vpn/_telnet.py b/src/leap/bitmask/vpn/_telnet.py new file mode 100644 index 00000000..cfc82ef0 --- /dev/null +++ b/src/leap/bitmask/vpn/_telnet.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# _telnet.py +# Copyright (C) 2013-2017 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 . + +import os +import socket +import telnetlib + + +class ConnectionRefusedError(Exception): + pass + + +class MissingSocketError(Exception): + pass + + +class UDSTelnet(telnetlib.Telnet): + """ + A telnet-alike class, that can listen on unix domain sockets + """ + + def open(self, host, port=23, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): + """ + Connect to a host. If port is 'unix', it will open a + connection over unix docmain sockets. + + The optional second argument is the port number, which + defaults to the standard telnet port (23). + Don't try to reopen an already connected instance. + """ + self.eof = 0 + self.host = host + self.port = port + self.timeout = timeout + + if self.port == "unix": + # unix sockets spoken + if not os.path.exists(self.host): + raise MissingSocketError() + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + self.sock.connect(self.host) + except socket.error: + raise ConnectionRefusedError() + else: + self.sock = socket.create_connection((host, port), timeout) diff --git a/src/leap/bitmask/vpn/manager.py b/src/leap/bitmask/vpn/manager.py index 68025852..a27789c3 100644 --- a/src/leap/bitmask/vpn/manager.py +++ b/src/leap/bitmask/vpn/manager.py @@ -22,14 +22,14 @@ VPN Manager import os import tempfile -from .process import VPNProcess -from ._config import _TempEIPConfig +from ._control import VPNControl +from ._config import _TempEIPConfig, _TempProviderConfig from .constants import IS_WIN # TODO this is very badly named. There is another class that is called -# manager!!! +# manager. This class VPNManager(object): @@ -50,10 +50,9 @@ class VPNManager(object): self._remotes = remotes self._eipconfig = _TempEIPConfig(extra_flags, cert_path, ports) - self._providerconfig = _config._TempProviderConfig(domain, ca_path) - # signaler = None # XXX handle signaling somehow... - signaler = mock_signaler - self._vpn = VPNProcess(remotes=remotes, signaler=signaler) + self._providerconfig = _TempProviderConfig(domain, ca_path) + signaler = None # XXX handle signaling somehow... + self._vpn = VPNControl(remotes=remotes, signaler=signaler) def start(self): diff --git a/src/leap/bitmask/vpn/process.py b/src/leap/bitmask/vpn/process.py index 47c29423..ef5ee37f 100644 --- a/src/leap/bitmask/vpn/process.py +++ b/src/leap/bitmask/vpn/process.py @@ -29,16 +29,6 @@ import sys from itertools import chain, repeat -import psutil -try: - # psutil < 2.0.0 - from psutil.error import AccessDenied as psutil_AccessDenied - PSUTIL_2 = False -except ImportError: - # psutil >= 2.0.0 - from psutil import AccessDenied as psutil_AccessDenied - PSUTIL_2 = True - from twisted.internet import defer, protocol, reactor from twisted.internet import error as internet_error from twisted.internet.task import LoopingCall @@ -90,7 +80,7 @@ class VPNProcess(protocol.ProcessProtocol, _management.VPNManagement): openvpn invocation :type openvpn_verb: int """ - VPNManagement.__init__(self, signaler=signaler) + _management.VPNManagement.__init__(self, signaler=signaler) self._eipconfig = eipconfig self._providerconfig = providerconfig diff --git a/src/leap/bitmask/vpn/udstelnet.py b/src/leap/bitmask/vpn/udstelnet.py deleted file mode 100644 index e6c82350..00000000 --- a/src/leap/bitmask/vpn/udstelnet.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# udstelnet.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 . - -import os -import socket -import telnetlib - - -class ConnectionRefusedError(Exception): - pass - - -class MissingSocketError(Exception): - pass - - -class UDSTelnet(telnetlib.Telnet): - """ - A telnet-alike class, that can listen on unix domain sockets - """ - - def open(self, host, port=23, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): - """ - Connect to a host. If port is 'unix', it will open a - connection over unix docmain sockets. - - The optional second argument is the port number, which - defaults to the standard telnet port (23). - Don't try to reopen an already connected instance. - """ - self.eof = 0 - self.host = host - self.port = port - self.timeout = timeout - - if self.port == "unix": - # unix sockets spoken - if not os.path.exists(self.host): - raise MissingSocketError() - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - try: - self.sock.connect(self.host) - except socket.error: - raise ConnectionRefusedError() - else: - self.sock = socket.create_connection((host, port), timeout) -- cgit v1.2.3