From d6c8cb0f12e8924820c296a8114a7899f61e5180 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 17 Jan 2013 05:54:16 +0900 Subject: (osx) detect which interface is traffic going thru --- pkg/requirements.pip | 3 +- src/leap/app.py | 7 +++ src/leap/base/checks.py | 98 ++++++++++++++++++++++++++++++--------- src/leap/eip/checks.py | 1 - src/leap/eip/config.py | 2 +- src/leap/eip/openvpnconnection.py | 3 ++ src/leap/util/certs.py | 3 +- 7 files changed, 90 insertions(+), 27 deletions(-) diff --git a/pkg/requirements.pip b/pkg/requirements.pip index fa40c490..69d435dc 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -1,5 +1,5 @@ # in order of addition to the project. -# do not change it, we will freeze the requirements before tagging a release. +# do not change the ordering. argparse # only for python 2.6 requests<1.0.0 @@ -16,3 +16,4 @@ python-gnupg u1db oauth couchdb +sh diff --git a/src/leap/app.py b/src/leap/app.py index 7b8ac3cd..5f4fd656 100644 --- a/src/leap/app.py +++ b/src/leap/app.py @@ -49,6 +49,13 @@ def main(): logger.addHandler(console) #logger.debug(opts) + import os + ldlib = os.environ.get("LD_LIBRARY_PATH", None) + dyldlib = os.environ.get("DYLD_LIBRARY_PATH", None) + + logger.debug("LD_LIBRARY_PATH %s" % ldlib) + logger.debug("DYLD_LIBRARY_PATH %s" % dyldlib) + logger.info('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') logger.info('LEAP client version %s', VERSION) logger.info('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') diff --git a/src/leap/base/checks.py b/src/leap/base/checks.py index e5767018..0bdfd593 100644 --- a/src/leap/base/checks.py +++ b/src/leap/base/checks.py @@ -1,20 +1,25 @@ # -*- coding: utf-8 -*- import logging import platform +import re import socket import netifaces import ping import requests +import sh from leap.base import constants from leap.base import exceptions logger = logging.getLogger(name=__name__) +_platform = platform.system() #EVENTS OF NOTE EVENT_CONNECT_REFUSED = "[ECONNREFUSED]: Connection refused (code=111)" +ICMP_TARGET = "8.8.8.8" + class LeapNetworkChecker(object): """ @@ -43,6 +48,7 @@ class LeapNetworkChecker(object): try: # XXX remove this hardcoded random ip # ping leap.se or eip provider instead...? + # XXX could use icmp instead.. requests.get('http://216.172.161.165') except requests.ConnectionError as e: error = "Unidentified Connection Error" @@ -65,59 +71,104 @@ class LeapNetworkChecker(object): return False return True - def check_tunnel_default_interface(self): - """ - Raises an TunnelNotDefaultRouteError - (including when no routes are present) - """ - if not platform.system() == "Linux": - raise NotImplementedError - - # XXX GET DARWIN IMPLEMENTATION + def _get_route_table_linux(self): - f = open("/proc/net/route") - route_table = f.readlines() - f.close() + with open("/proc/net/route") as f: + route_table = f.readlines() #toss out header route_table.pop(0) - if not route_table: raise exceptions.TunnelNotDefaultRouteError() + return route_table + def _get_def_iface_osx(self): + default_iface = None + gateway = None + routes = list(sh.route('-n', 'get', ICMP_TARGET, _iter=True)) + iface = filter(lambda l: "interface" in l, routes) + if not iface: + return None, None + def_ifacel = re.findall('\w+\d', iface[0]) + default_iface = def_ifacel[0] if def_ifacel else None + if not default_iface: + return None, None + _gw = filter(lambda l: "gateway" in l, routes) + gw = re.findall('\d+\.\d+\.\d+\.\d+', _gw[0])[0] + return default_iface, gw + + def _get_tunnel_iface_linux(): + # XXX review. + # valid also when local router has a default entry? + route_table = self._get_route_table_linux() line = route_table.pop(0) iface, destination = line.split('\t')[0:2] if not destination == '00000000' or not iface == 'tun0': raise exceptions.TunnelNotDefaultRouteError() + return True - def get_default_interface_gateway(self): - """only impletemented for linux so far.""" - if not platform.system() == "Linux": + def check_tunnel_default_interface(self): + """ + Raises an TunnelNotDefaultRouteError + if tun0 is not the chosen default route + (including when no routes are present) + """ + #logger.debug('checking tunnel default interface...') + + if _platform == "Linux": + valid = self._get_tunnel_iface_linux() + return valid + elif _platform == "Darwin": + default_iface, gw = self._get_def_iface_osx() + #logger.debug('iface: %s', default_iface) + if default_iface != "tun0": + logger.debug('tunnel not default route! gw: %s', default_iface) + # XXX should catch this and act accordingly... + # but rather, this test should only be launched + # when we have successfully completed a connection + # ... TRIGGER: Connection stablished (or whatever it is) + # in the logs + raise exceptions.TunnelNotDefaultRouteError + else: + logger.debug('PLATFORM !!! %s', _platform) raise NotImplementedError - # XXX use psutil - f = open("/proc/net/route") - route_table = f.readlines() - f.close() - #toss out header - route_table.pop(0) + def _get_def_iface_linux(self): default_iface = None gateway = None + + route_table = self._get_route_table_linux() while route_table: line = route_table.pop(0) iface, destination, gateway = line.split('\t')[0:3] if destination == '00000000': default_iface = iface break + return default_iface, gateway + + + def get_default_interface_gateway(self): + """ + gets the interface we are going thru. + (this should be merged with check tunnel default interface, + imo...) + """ + if _platform == "Linux": + default_iface, gw = self.get_def_iface_linux() + elif _platform == "Darwin": + default_iface, gw = self.get_def_iface_osx() + else: + raise NotImplementedError if not default_iface: raise exceptions.NoDefaultInterfaceFoundError if default_iface not in netifaces.interfaces(): raise exceptions.InterfaceNotFoundError - + logger.debug('-- default iface', default_iface) return default_iface, gateway + def ping_gateway(self, gateway): # TODO: Discuss how much packet loss (%) is acceptable. @@ -132,6 +183,7 @@ class LeapNetworkChecker(object): # or wrap around system traceroute (using sh module, fi) # -- kali packet_loss = ping.quiet_ping(gateway)[0] + logger.debug('packet loss %s' % packet_loss) if packet_loss > constants.MAX_ICMP_PACKET_LOSS: raise exceptions.NoConnectionToGateway diff --git a/src/leap/eip/checks.py b/src/leap/eip/checks.py index 9fb13c74..0d07ef08 100644 --- a/src/leap/eip/checks.py +++ b/src/leap/eip/checks.py @@ -187,7 +187,6 @@ class ProviderCertChecker(object): def check_new_cert_needed(self, skip_download=False, verify=True): # XXX add autocacert - logger.debug('is new cert needed?') if not self.is_cert_valid(do_raise=False): logger.debug('cert needed: true') self.download_new_client_cert( diff --git a/src/leap/eip/config.py b/src/leap/eip/config.py index 6a19633d..a60d7ed5 100644 --- a/src/leap/eip/config.py +++ b/src/leap/eip/config.py @@ -253,7 +253,7 @@ def build_ovpn_options(daemon=False, socket_path=None, **kwargs): #if daemon is True: #opts.append('--daemon') - logger.debug('vpn options: %s', opts) + logger.debug('vpn options: %s', ' '.join(opts)) return opts diff --git a/src/leap/eip/openvpnconnection.py b/src/leap/eip/openvpnconnection.py index a36d99de..e5169465 100644 --- a/src/leap/eip/openvpnconnection.py +++ b/src/leap/eip/openvpnconnection.py @@ -6,6 +6,7 @@ import logging import os import psutil import shutil +import select import socket from functools import partial @@ -103,6 +104,8 @@ class OpenVPNManagement(object): return [] except socket.error as exc: logger.debug('socket error: %s' % exc.message) + except select.error as exc: + logger.debug('select error: %s' % exc.message) def _send_short_command(self, cmd): """ diff --git a/src/leap/util/certs.py b/src/leap/util/certs.py index 304db08a..f0f790e9 100644 --- a/src/leap/util/certs.py +++ b/src/leap/util/certs.py @@ -14,4 +14,5 @@ def get_mac_cabundle(): #logger.error('VERIFY PATH = %s' % verify) exists = os.path.isfile(verify) #logger.error('do exist? %s', exists) - return verify + if exists: + return verify -- cgit v1.2.3