def list_providers(): """ List all OpenVPN connections. """ if not have_dbus(): # fall back to just listing the json files try: providers = [ i for i in os.listdir(providers_path) if i.endswith('.json') ] except (IOError, OSError) as e: logger.error( "can't list configurations in {}".format(providers_path)) raise StopIteration else: for p in providers: try: yield Metadata.from_uuid(p[:-5]) except IOError as e: logger.error("cant open {}: {}".format(p, e)) else: all_ = NetworkManager.Settings.ListConnections() vpn_connections = [ c.GetSettings()['connection'] for c in all_ if c.GetSettings()['connection']['type'] == 'vpn' ] logger.info("There are {} VPN connections in networkmanager".format( len(vpn_connections))) for conn in vpn_connections: yield Metadata.from_uuid(conn['uuid'], display_name=conn['id'])
def update_config_provider(meta, config_dict): # type: (Metadata, dict) -> None """ Update an existing network manager configuration args: uuid (str): the unique ID of the network manager configuration display_name (str): The new display name of the configuration config (str): The new OpenVPN configuration """ logger.info(u"updating config for {} ({})".format(meta.display_name, meta.uuid)) nm_config = ovpn_to_nm(config_dict, meta=meta, display_name=meta.display_name, username=meta.username) if have_dbus(): connection = NetworkManager.Settings.GetConnectionByUuid( meta.uuid) # type: ignore old_settings = connection.GetSettings() nm_config['vpn']['data'].update({ 'cert': old_settings['vpn']['data']['cert'], 'key': old_settings['vpn']['data']['key'] }) # type: ignore connection.Update(nm_config)
def list_providers(): # type: () -> Iterable[Metadata] """ List all OpenVPN connections. """ if not have_dbus(): # fall back to just listing the json files try: providers = [ i for i in os.listdir(providers_path) if i.endswith('.json') ] except (IOError, OSError) as e: logger.error(u"can't list configurations in" "{}".format(providers_path)) raise StopIteration else: for p in providers: try: yield Metadata.from_uuid(p[:-5]) except IOError as e: logger.error(u"cant open {}: {}".format(p, e)) else: all_ = NetworkManager.Settings.ListConnections() # type: ignore # if the uuid is not set we probably can't access the object due to permission errors all_ = [i for i in all_ if i.uuid] vpn_connections = ([ c.GetSettings()['connection'] for c in all_ if c.GetSettings()['connection']['type'] == 'vpn' ]) logger.info(u"There are {} VPN connections in" "networkmanager".format(len(vpn_connections))) for conn in vpn_connections: yield Metadata.from_uuid(conn['uuid'], display_name=conn['id'])
def active_connections(): if not have_dbus(): return [] try: return NetworkManager.NetworkManager.ActiveConnections except DBusException: return []
def disconnect_all(): # type: () -> Any """ Disconnect all active VPN connections. """ if not have_dbus(): return [] for active in NetworkManager.NetworkManager.ActiveConnections: conn = NetworkManager.Settings.GetConnectionByUuid(active.Uuid) if conn.GetSettings()['connection']['type'] == 'vpn': disconnect_provider(active.Uuid)
def list_active(): """ List active connections returns: list: a list of NetworkManager.ActiveConnection objects """ logger.info("getting list of active connections") if have_dbus(): return NetworkManager.NetworkManager.ActiveConnections else: return []
def monitor_vpn(uuid, callback): """ This installs a dbus callback which will be called every time the state of a specific VPN changes args: callback (func): a callback function """ if not have_dbus(): return connection = NetworkManager.Settings.GetConnectionByUuid(uuid) connection.connect_to_signal('Updated', callback)
def monitor_all_vpn(callback): """ This installs a dbus callback which will be called every time the state of any VPN connection changes. args: callback (func): a callback function """ if not have_dbus(): return [] bus = dbus.SystemBus() bus.add_signal_receiver(handler_function=callback, dbus_interface='org.freedesktop.NetworkManager.VPN.Connection', signal_name='VpnStateChanged')
def monitor_all_vpn(callback): """ This installs a dbus callback which will be called every time the state of any VPN connection changes. args: callback (func): a callback function """ if not have_dbus(): return [] for connection in NetworkManager.Settings.ListConnections(): if connection.GetSettings()['connection']['type'] == 'vpn': connection.connect_to_signal('Updated', callback)
def insert_config(settings): """ Add a configuration to the networkmanager args: settings (dict): a nm settings dict, typically generated by :meth:`ovpn_to_nm()` """ if not have_dbus(): return name = settings['connection']['id'] logger.info("generating or updating OpenVPN configuration with name {}".format(name)) connection = NetworkManager.Settings.AddConnection(settings) return connection
def delete_provider(uuid): # type: (str) -> None """ Delete the network manager configuration by its UUID args: uuid (str): the unique ID of the configuration """ metadata = os.path.join(providers_path, uuid + '.json') logger.info(u"deleting metadata file {}".format(metadata)) try: os.remove(metadata) except Exception as e: logger.error(u"can't remove ovpn file: {}".format(str(e))) if not have_dbus(): return logger.info(u"deleting profile with uuid {}" "using NetworkManager".format(uuid)) all_connections = NetworkManager.Settings.ListConnections() # type: ignore conns = [ c for c in all_connections if c.GetSettings()['connection']['uuid'] == uuid ] if len(conns) != 1: logger.error(u"{} connections matching uid {}".format( len(conns), uuid)) return conn = conns[0] logger.info(u"removing certificates for {}".format(uuid)) for f in ['ca', 'cert', 'key', 'ta']: if f not in conn.GetSettings()['vpn']['data']: logger.error(u"key {} not in config for {}".format(f, uuid)) continue path = conn.GetSettings()['vpn']['data'][f] logger.info(u"removing certificate {}".format(path)) try: os.remove(path) except (IOError, OSError) as e: logger.error(u"can't remove certificate {}: {}".format(path, e)) try: conn.Delete() except Exception as e: logger.error(u"can't remove networkmanager" "connection: {}".format(str(e))) raise
def disconnect_provider(uuid): """ Disconnect the network manager configuration by its UUID args: uuid (str): the unique ID of the configuration """ logger.info("Disconnecting profile with uuid {} using NetworkManager".format(uuid)) if not have_dbus(): raise EduvpnException("No DBus daemon running") conns = [i for i in NetworkManager.NetworkManager.ActiveConnections if i.Uuid == uuid] if len(conns) == 0: raise EduvpnException("no active connection found with uuid {}".format(uuid)) for conn in conns: NetworkManager.NetworkManager.DeactivateConnection(conn)
def connect_provider(uuid): """ Enable the network manager configuration by its UUID args: uuid (str): the unique ID of the configuration """ logger.info("connecting profile with uuid {} using NetworkManager".format(uuid)) if not have_dbus(): raise EduvpnException("No DBus daemon running") try: connection = NetworkManager.Settings.GetConnectionByUuid(uuid) return NetworkManager.NetworkManager.ActivateConnection(connection, "/", "/") except DBusException as e: raise EduvpnException(e)
def list_active(): """ List active connections returns: list: a list of NetworkManager.ActiveConnection objects """ logger.info("getting list of active connections") if not have_dbus(): return [] try: active = NetworkManager.NetworkManager.ActiveConnections return [a for a in active if NetworkManager.Settings.GetConnectionByUuid(a.Uuid).GetSettings()['connection']['type'] == 'vpn'] except DBusException: return []
def init(lets_connect): # type: (bool) -> EduVpnApp (level, secure_internet_uri, institute_access_uri, verify_key, lets_connect_arg) = parse_args() lets_connect = lets_connect or lets_connect_arg if geteuid() == 0: logger.error("Running eduVPN client as root is not supported (yet)") exit(1) GObject.threads_init() if have_dbus(): import dbus.mainloop.glib dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) # import this later so the logging is properly configured from eduvpn.ui import EduVpnApp edu_vpn_app = EduVpnApp(secure_internet_uri=secure_internet_uri, institute_access_uri=institute_access_uri, verify_key=verify_key, lets_connect=lets_connect) edu_vpn_app.run() return edu_vpn_app
def update_config_provider(meta): """ Update an existing network manager configuration args: uuid (str): the unique ID of the network manager configuration display_name (str): The new display name of the configuration config (str): The new OpenVPN configuration """ logger.info("updating config for {} ({})".format(meta.display_name, meta.uuid)) config_dict = parse_ovpn(meta.config) ca_path = write_cert(config_dict.pop('ca'), 'ca', meta.uuid) ta_path = write_cert(config_dict.pop('tls-auth'), 'ta', meta.uuid) if have_dbus(): nm_config = ovpn_to_nm(config_dict, uuid=meta.uuid, display_name=meta.display_name, username=meta.username) old_conn = NetworkManager.Settings.GetConnectionByUuid(meta.uuid) old_settings = old_conn.GetSettings() nm_config['vpn']['data'].update({'cert': old_settings['vpn']['data']['cert'], 'key': old_settings['vpn']['data']['key'], 'ca': ca_path, 'ta': ta_path}) old_conn.Delete() insert_config(nm_config)
""" Due to an issue with systemd-resolvd on ubuntu 18.04 a connection is leaking DNS information. This module implements a workaround that sets the link domain to ~. more information in this issue: https://github.com/eduvpn/python-eduvpn-client/issues/160 """ # type: ignore from eduvpn.util import have_dbus import dbus import subprocess if have_dbus(): import eduvpn.other_nm as NetworkManager type_tun = 16 # NM_DEVICE_TYPE_TUN state_acticated = 100 # NM_DEVICE_STATE_ACTIVATED def get_link(interface): # type: (str) -> int """ Returns link ID associated with the interface name """ return int( subprocess.check_output(['/sbin/ip', 'link', 'show', 'dev', interface]).decode('ascii').split()[0][:-1]) def get_active_vpn_device(): # type: () -> str
def notify(notification, msg, small_msg=None): # type: (Notify, str, Optional[Any]) -> None notification.update(msg, small_msg) if have_dbus(): notification.show()
def test_have_dbus(self): have_dbus()
def notify(notification, msg, small_msg=None): notification.update(msg, small_msg) if have_dbus(): notification.show()