| # SOCKSv5 proxy manager for network-sandbox |
| # Copyright 2015 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| import os |
| import signal |
| |
| from portage import _python_interpreter |
| from portage.data import portage_gid, portage_uid, userpriv_groups |
| from portage.process import atexit_register, spawn |
| |
| |
| class ProxyManager(object): |
| """ |
| A class to start and control a single running SOCKSv5 server process |
| for Portage. |
| """ |
| |
| def __init__(self): |
| self.socket_path = None |
| self._pids = [] |
| |
| def start(self, settings): |
| """ |
| Start the SOCKSv5 server. |
| |
| @param settings: Portage settings instance (used to determine |
| paths) |
| @type settings: portage.config |
| """ |
| try: |
| import asyncio # NOQA |
| except ImportError: |
| raise NotImplementedError('SOCKSv5 proxy requires asyncio module') |
| |
| self.socket_path = os.path.join(settings['PORTAGE_TMPDIR'], |
| '.portage.%d.net.sock' % os.getpid()) |
| server_bin = os.path.join(settings['PORTAGE_BIN_PATH'], 'socks5-server.py') |
| self._pids = spawn([_python_interpreter, server_bin, self.socket_path], |
| returnpid=True, uid=portage_uid, gid=portage_gid, |
| groups=userpriv_groups, umask=0o077) |
| |
| def stop(self): |
| """ |
| Stop the SOCKSv5 server. |
| """ |
| for p in self._pids: |
| os.kill(p, signal.SIGINT) |
| os.waitpid(p, 0) |
| |
| self.socket_path = None |
| self._pids = [] |
| |
| def is_running(self): |
| """ |
| Check whether the SOCKSv5 server is running. |
| |
| @return: True if the server is running, False otherwise |
| """ |
| return self.socket_path is not None |
| |
| |
| proxy = ProxyManager() |
| |
| |
| def get_socks5_proxy(settings): |
| """ |
| Get UNIX socket path for a SOCKSv5 proxy. A new proxy is started if |
| one isn't running yet, and an atexit event is added to stop the proxy |
| on exit. |
| |
| @param settings: Portage settings instance (used to determine paths) |
| @type settings: portage.config |
| @return: (string) UNIX socket path |
| """ |
| |
| if not proxy.is_running(): |
| proxy.start(settings) |
| atexit_register(proxy.stop) |
| |
| return proxy.socket_path |