diff options
Diffstat (limited to 'sshuttle')
-rw-r--r-- | sshuttle/__init__.py | 3 | ||||
-rw-r--r-- | sshuttle/client.py | 62 | ||||
-rw-r--r-- | sshuttle/hostwatch.py | 2 | ||||
-rw-r--r-- | sshuttle/sdnotify.py | 2 | ||||
-rw-r--r-- | sshuttle/server.py | 4 | ||||
-rw-r--r-- | sshuttle/ssh.py | 17 | ||||
-rw-r--r-- | sshuttle/ssnet.py | 12 | ||||
-rwxr-xr-x | sshuttle/stresstest.py | 12 | ||||
-rw-r--r-- | sshuttle/sudoers.py | 18 |
9 files changed, 82 insertions, 50 deletions
diff --git a/sshuttle/__init__.py b/sshuttle/__init__.py index a6ab7f4..3bc3d0e 100644 --- a/sshuttle/__init__.py +++ b/sshuttle/__init__.py @@ -1,3 +1,6 @@ +""" +sshuttle: where transparent proxy meets VPN meets ssh +""" try: from sshuttle.version import version as __version__ except ImportError: diff --git a/sshuttle/client.py b/sshuttle/client.py index 671f7b6..b0b4324 100644 --- a/sshuttle/client.py +++ b/sshuttle/client.py @@ -1,3 +1,4 @@ +""" Sshuttle client code """ import errno import re import signal @@ -40,53 +41,56 @@ except AttributeError: _extra_fd = os.open(os.devnull, os.O_RDONLY) -def got_signal(signum, frame): +def got_signal(signum, _frame): + """ Process client signal """ log('exiting on signal %d\n' % signum) sys.exit(1) -_pidname = None +_PID_NAME = None def check_daemon(pidfile): - global _pidname - _pidname = os.path.abspath(pidfile) + """ Check if daemon """ + global _PID_NAME + _PID_NAME = os.path.abspath(pidfile) try: - oldpid = open(_pidname).read(1024) + oldpid = open(_PID_NAME).read(1024) except IOError as e: if e.errno == errno.ENOENT: return # no pidfile, ok else: - raise Fatal("c : can't read %s: %s" % (_pidname, e)) + raise Fatal("c : can't read %s: %s" % (_PID_NAME, e)) if not oldpid: - os.unlink(_pidname) + os.unlink(_PID_NAME) return # invalid pidfile, ok oldpid = int(oldpid.strip() or 0) if oldpid <= 0: - os.unlink(_pidname) + os.unlink(_PID_NAME) return # invalid pidfile, ok try: os.kill(oldpid, 0) except OSError as e: if e.errno == errno.ESRCH: - os.unlink(_pidname) + os.unlink(_PID_NAME) return # outdated pidfile, ok elif e.errno == errno.EPERM: pass else: raise raise Fatal("%s: sshuttle is already running (pid=%d)" - % (_pidname, oldpid)) + % (_PID_NAME, oldpid)) def daemonize(): + """ Run code as daemon """ if os.fork(): - os._exit(0) + sys.exit(0) os.setsid() if os.fork(): - os._exit(0) + sys.exit(0) - outfd = os.open(_pidname, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o666) + outfd = os.open(_PID_NAME, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o666) try: os.write(outfd, b'%d\n' % os.getpid()) finally: @@ -104,8 +108,9 @@ def daemonize(): def daemon_cleanup(): + """ Clean up after daemon """ try: - os.unlink(_pidname) + os.unlink(_PID_NAME) except OSError as e: if e.errno == errno.ENOENT: pass @@ -114,6 +119,7 @@ def daemon_cleanup(): class MultiListener: + """ Listen to multiple sockets """ def __init__(self, kind=socket.SOCK_STREAM, proto=0): self.type = kind @@ -123,14 +129,14 @@ class MultiListener: self.bind_called = False def setsockopt(self, level, optname, value): - assert(self.bind_called) + assert self.bind_called if self.v6: self.v6.setsockopt(level, optname, value) if self.v4: self.v4.setsockopt(level, optname, value) def add_handler(self, handlers, callback, method, mux): - assert(self.bind_called) + assert self.bind_called socks = [] if self.v6: socks.append(self.v6) @@ -145,7 +151,7 @@ class MultiListener: ) def listen(self, backlog): - assert(self.bind_called) + assert self.bind_called if self.v6: self.v6.listen(backlog) if self.v4: @@ -160,7 +166,7 @@ class MultiListener: raise e def bind(self, address_v6, address_v4): - assert(not self.bind_called) + assert not self.bind_called self.bind_called = True if address_v6 is not None: self.v6 = socket.socket(socket.AF_INET6, self.type, self.proto) @@ -174,7 +180,7 @@ class MultiListener: self.v4 = None def print_listening(self, what): - assert(self.bind_called) + assert self.bind_called if self.v6: listenip = self.v6.getsockname() debug1('%s listening on %r.\n' % (what, listenip)) @@ -186,6 +192,7 @@ class MultiListener: class FirewallClient: + """ Start firewall code """ def __init__(self, method_name, sudo_pythonpath): self.auto_nets = [] @@ -309,8 +316,8 @@ class FirewallClient: raise Fatal('%r expected STARTED, got %r' % (self.argv, line)) def sethostip(self, hostname, ip): - assert(not re.search(br'[^-\w\.]', hostname)) - assert(not re.search(br'[^0-9.]', ip)) + assert not re.search(br'[^-\w\.]', hostname) + assert not re.search(br'[^0-9.]', ip) self.pfile.write(b'HOST %s,%s\n' % (hostname, ip)) self.pfile.flush() @@ -326,6 +333,7 @@ udp_by_src = {} def expire_connections(now, mux): + """ Expire connections that have timed out """ remove = [] for chan, timeout in dnsreqs.items(): if timeout < now: @@ -349,6 +357,7 @@ def expire_connections(now, mux): def onaccept_tcp(listener, method, mux, handlers): + """ Accept a new TCP connection """ global _extra_fd try: sock, srcip = listener.accept() @@ -386,6 +395,7 @@ def onaccept_tcp(listener, method, mux, handlers): def udp_done(chan, data, method, sock, dstip): + """ Respond to UDP request """ (src, srcport, data) = data.split(b",", 2) srcip = (src, int(srcport)) debug3('doing send from %r to %r\n' % (srcip, dstip,)) @@ -393,6 +403,7 @@ def udp_done(chan, data, method, sock, dstip): def onaccept_udp(listener, method, mux, handlers): + """ Accept a new UDP request """ now = time.time() t = method.recv_udp(listener, 4096) if t is None: @@ -415,6 +426,7 @@ def onaccept_udp(listener, method, mux, handlers): def dns_done(chan, data, method, sock, srcip, dstip, mux): + """ Respond to a DNS request """ debug3('dns_done: channel=%d src=%r dst=%r\n' % (chan, srcip, dstip)) del mux.channels[chan] del dnsreqs[chan] @@ -422,6 +434,7 @@ def dns_done(chan, data, method, sock, srcip, dstip, mux): def ondns(listener, method, mux, handlers): + """ Accept a new DNS request """ now = time.time() t = method.recv_udp(listener, 4096) if t is None: @@ -499,7 +512,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, sys.stdout.flush() if daemon: daemonize() - log('daemonizing (%s).\n' % _pidname) + log('daemonizing (%s).\n' % _PID_NAME) def onroutes(routestr): if auto_nets: @@ -581,6 +594,7 @@ def main(listenip_v6, listenip_v4, method_name, seed_hosts, auto_hosts, auto_nets, subnets_include, subnets_exclude, daemon, to_nameserver, pidfile, user, sudo_pythonpath): + """ Main client code """ if not remotename: print("WARNING: You must specify -r/--remote to securely route " @@ -821,7 +835,7 @@ def main(listenip_v6, listenip_v4, raise e if not bound: - assert(last_e) + assert last_e raise last_e tcp_listener.listen(10) tcp_listener.print_listening("TCP redirector") @@ -867,7 +881,7 @@ def main(listenip_v6, listenip_v4, dns_listener.print_listening("DNS") if not bound: - assert(last_e) + assert last_e raise last_e else: dnsport_v6 = 0 diff --git a/sshuttle/hostwatch.py b/sshuttle/hostwatch.py index d40eaf4..f3d554c 100644 --- a/sshuttle/hostwatch.py +++ b/sshuttle/hostwatch.py @@ -197,7 +197,7 @@ def _check_smb(hostname): check_workgroup(workgroup) if lines: - assert(0) + assert 0 def _check_nmb(hostname, is_workgroup, is_master): diff --git a/sshuttle/sdnotify.py b/sshuttle/sdnotify.py index 5024dd2..72e827b 100644 --- a/sshuttle/sdnotify.py +++ b/sshuttle/sdnotify.py @@ -35,7 +35,7 @@ def _notify(message): assert isinstance(message, bytes) try: - return (sock.sendto(message, addr) > 0) + return sock.sendto(message, addr) > 0 except (OSError, IOError) as e: debug1("Error notifying systemd: %s\n" % e) return False diff --git a/sshuttle/server.py b/sshuttle/server.py index fe84ba4..8c9a088 100644 --- a/sshuttle/server.py +++ b/sshuttle/server.py @@ -304,7 +304,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets): hw.leftover = b('') def hostwatch_ready(sock): - assert(hw.pid) + assert hw.pid content = hw.sock.recv(4096) if content: lines = (hw.leftover + content).split(b('\n')) @@ -379,7 +379,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets): while mux.ok: if hw.pid: - assert(hw.pid > 0) + assert hw.pid > 0 (rpid, rv) = os.waitpid(hw.pid, os.WNOHANG) if rpid: raise Fatal( diff --git a/sshuttle/ssh.py b/sshuttle/ssh.py index ae235ed..10de13b 100644 --- a/sshuttle/ssh.py +++ b/sshuttle/ssh.py @@ -1,3 +1,7 @@ +""" +Run sshuttle via remove ssh session +""" + import sys import os import re @@ -16,23 +20,27 @@ from sshuttle.helpers import debug2, which, get_path, Fatal def get_module_source(name): + """ Get source code for module """ spec = importlib.util.find_spec(name) with open(spec.origin, "rt") as f: return f.read().encode("utf-8") -def empackage(z, name, data=None): +def empackage(zobj, name, data=None): + """ Compress and package module source code """ if not data: data = get_module_source(name) - content = z.compress(data) - content += z.flush(zlib.Z_SYNC_FLUSH) + content = zobj.compress(data) + content += zobj.flush(zlib.Z_SYNC_FLUSH) return b'%s\n%d\n%s' % (name.encode("ASCII"), len(content), content) def parse_hostport(rhostport): """ - parses the given rhostport variable, looking like this: + Parses the given rhostport variable + + rhostport looks like this: [username[:password]@]host[:port] @@ -85,6 +93,7 @@ def parse_hostport(rhostport): def connect(ssh_cmd, rhostport, python, stderr, options): + """ Connect to a remote server via ssh and run sshuttle """ username, password, port, host = parse_hostport(rhostport) if username: rhost = "{}@{}".format(username, host) diff --git a/sshuttle/ssnet.py b/sshuttle/ssnet.py index e7f9bf2..7e64bf6 100644 --- a/sshuttle/ssnet.py +++ b/sshuttle/ssnet.py @@ -227,7 +227,7 @@ class SockWrapper: return 0 def write(self, buf): - assert(buf) + assert buf return self.uwrite(buf) def uread(self): @@ -402,15 +402,15 @@ class Mux(Handler): elif cmd == CMD_EXIT: self.ok = False elif cmd == CMD_TCP_CONNECT: - assert(not self.channels.get(channel)) + assert not self.channels.get(channel) if self.new_channel: self.new_channel(channel, data) elif cmd == CMD_DNS_REQ: - assert(not self.channels.get(channel)) + assert not self.channels.get(channel) if self.got_dns_req: self.got_dns_req(channel, data) elif cmd == CMD_UDP_OPEN: - assert(not self.channels.get(channel)) + assert not self.channels.get(channel) if self.got_udp_open: self.got_udp_open(channel, data) elif cmd == CMD_ROUTES: @@ -479,8 +479,8 @@ class Mux(Handler): if len(self.inbuf) >= (self.want or HDR_LEN): (s1, s2, channel, cmd, datalen) = \ struct.unpack('!ccHHH', self.inbuf[:HDR_LEN]) - assert(s1 == b('S')) - assert(s2 == b('S')) + assert s1 == b('S') + assert s2 == b('S') self.want = datalen + HDR_LEN if self.want and len(self.inbuf) >= self.want: data = self.inbuf[HDR_LEN:self.want] diff --git a/sshuttle/stresstest.py b/sshuttle/stresstest.py index 490e60a..2885dd0 100755 --- a/sshuttle/stresstest.py +++ b/sshuttle/stresstest.py @@ -38,7 +38,7 @@ while 1: r = [listener] + servers + clients print('select(%d)' % len(r)) r, w, x = select.select(r, [], [], 5) - assert(r) + assert r for i in r: if i == listener: s, addr = listener.accept() @@ -47,7 +47,7 @@ while 1: b = i.recv(4096) print('srv << %r' % len(b)) if i not in remain: - assert(len(b) >= 4) + assert len(b) >= 4 want = struct.unpack('I', b[:4])[0] b = b[4:] # i.send('y'*want) @@ -55,13 +55,13 @@ while 1: want = remain[i] if want < len(b): print('weird wanted %d bytes, got %d: %r' % (want, len(b), b)) - assert(want >= len(b)) + assert want >= len(b) want -= len(b) remain[i] = want if not b: # EOF if want: print('weird: eof but wanted %d more' % want) - assert(want == 0) + assert want == 0 i.close() servers.remove(i) del remain[i] @@ -76,13 +76,13 @@ while 1: want = remain[i] if want < len(b): print('weird wanted %d bytes, got %d: %r' % (want, len(b), b)) - assert(want >= len(b)) + assert want >= len(b) want -= len(b) remain[i] = want if not b: # EOF if want: print('weird: eof but wanted %d more' % want) - assert(want == 0) + assert want == 0 i.close() clients.remove(i) del remain[i] diff --git a/sshuttle/sudoers.py b/sshuttle/sudoers.py index 3f01e8e..513a858 100644 --- a/sshuttle/sudoers.py +++ b/sshuttle/sudoers.py @@ -1,10 +1,13 @@ +""" +Manage sudoers file +""" import os import sys import getpass from uuid import uuid4 from subprocess import Popen, PIPE -from sshuttle.helpers import log, debug1 from distutils import spawn +from sshuttle.helpers import log, debug1 path_to_sshuttle = sys.argv[0] path_to_dist_packages = os.path.dirname(os.path.abspath(__file__))[:-9] @@ -13,7 +16,7 @@ path_to_dist_packages = os.path.dirname(os.path.abspath(__file__))[:-9] command_alias = 'SSHUTTLE%(num)s' % {'num': uuid4().hex[-3:].upper()} # Template for the sudoers file -template = ''' +TEMPLATE = ''' Cmnd_Alias %(ca)s = /usr/bin/env PYTHONPATH=%(dist_packages)s %(py)s %(path)s * %(user_name)s ALL=NOPASSWD: %(ca)s @@ -21,7 +24,8 @@ Cmnd_Alias %(ca)s = /usr/bin/env PYTHONPATH=%(dist_packages)s %(py)s %(path)s * def build_config(user_name): - content = template % { + """ Build sudoers config """ + content = TEMPLATE % { 'ca': command_alias, 'dist_packages': path_to_dist_packages, 'py': sys.executable, @@ -33,6 +37,7 @@ def build_config(user_name): def save_config(content, file_name): + """ Save sudoers config """ process = Popen([ '/usr/bin/sudo', spawn.find_executable('sudoers-add'), @@ -47,18 +52,19 @@ def save_config(content, file_name): if returncode: log('Failed updating sudoers file.\n') debug1(streamdata) - exit(returncode) + sys.exit(returncode) else: log('Success, sudoers file update.\n') - exit(0) + sys.exit(0) def sudoers(user_name=None, no_modify=None, file_name=None): + """ Update sudoers config """ user_name = user_name or getpass.getuser() content = build_config(user_name) if no_modify: sys.stdout.write(content) - exit(0) + sys.exit(0) else: save_config(content, file_name) |