def original_dst(sock): try: SO_ORIGINAL_DST = 80 SOCKADDR_MIN = 16 sockaddr_in = sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, SOCKADDR_MIN) (proto, port, a, b, c, d) = struct.unpack('!HHBBBB', sockaddr_in[:8]) assert (socket.htons(proto) == socket.AF_INET) ip = '%d.%d.%d.%d' % (a, b, c, d) return (ip, port) except socket.error, e: if e.args[0] == errno.ENOPROTOOPT: peer = sock.getpeername() output = ssubprocess.Popen( ["sudo", "-n", "/sbin/pfctl", "-s", "state"], stdout=ssubprocess.PIPE, stderr=ssubprocess.PIPE).communicate()[0] spec = "%s:%s" % (peer[0], peer[1]) for line in output.split("\n"): if "ESTABLISHED:ESTABLISHED" in line and spec in line: match = line.split() if len(match) > 4: submatch = match[4].split(":") if len(submatch) == 2: return submatch[0], int(submatch[1]) raise
def pfctl(*arg): argv = ['sudo', 'pfctl'] argv.extend(arg) p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=ssubprocess.PIPE) return p.wait()
def ipt_chain_exists(name): argv = ['iptables', '-t', 'nat', '-nL'] p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) for line in p.stdout: if line.startswith('Chain %s ' % name): return True rv = p.wait() if rv: raise Fatal('%r returned %d' % (argv, rv))
def _defaults_read_kernel_flags(): argv = ['defaults', 'read', KERNEL_FLAGS_PATH, KERNEL_FLAGS_NAME] debug1('>> %s\n' % ' '.join(argv)) p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) flagstr = p.stdout.read().strip() rv = p.wait() if rv: raise Fatal('%r returned %d' % (argv, rv)) flags = flagstr and flagstr.split(' ') or [] return flags
def _check_netstat(): debug2(' > netstat\n') argv = ['netstat', '-n'] try: p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null) content = p.stdout.read() p.wait() except OSError, e: log('%r failed: %r\n' % (argv, e)) return
def _fill_oldctls(prefix): argv = ['sysctl', prefix] p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) for line in p.stdout: assert (line[-1] == '\n') (k, v) = line[:-1].split(': ', 1) _oldctls[k] = v rv = p.wait() if rv: raise Fatal('%r returned %d' % (argv, rv)) if not line: raise Fatal('%r returned no data' % (argv, ))
def pfctl(args, stdin = None): argv = ['pfctl'] + list(args.split(" ")) debug1('>> %s\n' % ' '.join(argv)) p = ssubprocess.Popen(argv, stdin = ssubprocess.PIPE, stdout = ssubprocess.PIPE, stderr = ssubprocess.PIPE) o = p.communicate(stdin) if p.returncode: raise Fatal('%r returned %d' % (argv, p.returncode)) return o
def ipfw_rule_exists(n): argv = ['ipfw', 'list'] p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) found = False for line in p.stdout: if line.startswith('%05d ' % n): if not ('ipttl 42' in line or ('skipto %d' % (n + 1)) in line or 'check-state' in line): log('non-sshuttle ipfw rule: %r\n' % line.strip()) raise Fatal('non-sshuttle ipfw rule #%d already exists!' % n) found = True rv = p.wait() if rv: raise Fatal('%r returned %d' % (argv, rv)) return found
def ipt_chain_exists(family, table, name): if family == socket.AF_INET6: cmd = 'ip6tables' elif family == socket.AF_INET: cmd = 'iptables' else: raise Exception('Unsupported family "%s"' % family_to_string(family)) argv = [cmd, '-t', table, '-nL'] p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) for line in p.stdout: if line.startswith('Chain %s ' % name): return True rv = p.wait() if rv: raise Fatal('%r returned %d' % (argv, rv))
def _check_nmb(hostname, is_workgroup, is_master): return global _nmb_ok if not _nmb_ok: return argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname] debug2(' > n%d%d: %s\n' % (is_workgroup, is_master, hostname)) try: p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null) lines = p.stdout.readlines() rv = p.wait() except OSError, e: log('%r failed: %r\n' % (argv, e)) _nmb_ok = False return
def _check_smb(hostname): return global _smb_ok if not _smb_ok: return argv = ['smbclient', '-U', '%', '-L', hostname] debug2(' > smb: %s\n' % hostname) try: p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null) lines = p.stdout.readlines() p.wait() except OSError, e: log('%r failed: %r\n' % (argv, e)) _smb_ok = False return
def _list_routes(): argv = ['netstat', '-rn'] p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE) routes = [] for line in p.stdout: cols = re.split(r'\s+', line) ipw = _ipmatch(cols[0]) if not ipw: continue # some lines won't be parseable; never mind maskw = _ipmatch(cols[2]) # linux only mask = _maskbits(maskw) # returns 32 if maskw is null width = min(ipw[1], mask) ip = ipw[0] & _shl(_shl(1, width) - 1, 32 - width) routes.append((socket.inet_ntoa(struct.pack('!I', ip)), width)) rv = p.wait() if rv != 0: log('WARNING: %r returned %d\n' % (argv, rv)) log('WARNING: That prevents --auto-nets from working.\n') return routes
def __init__(self, port_v6, port_v4, subnets_include, subnets_exclude, dnsport_v6, dnsport_v4, method, udp): self.auto_nets = [] self.subnets_include = subnets_include self.subnets_exclude = subnets_exclude argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] + ['-v'] * (helpers.verbose or 0) + [ '--firewall', str(port_v6), str(port_v4), str(dnsport_v6), str(dnsport_v4), method, str(int(udp)) ]) if ssyslog._p: argvbase += ['--syslog'] argv_tries = [['sudo', '-p', '[local sudo] Password: '******'su', '-c', ' '.join(argvbase)], argvbase] # we can't use stdin/stdout=subprocess.PIPE here, as we normally would, # because stupid Linux 'su' requires that stdin be attached to a tty. # Instead, attach a *bidirectional* socket to its stdout, and use # that for talking in both directions. (s1, s2) = socket.socketpair() def setup(): # run in the child process s2.close() e = None if os.getuid() == 0: argv_tries = argv_tries[-1:] # last entry only for argv in argv_tries: try: if argv[0] == 'su': sys.stderr.write('[local su] ') self.p = ssubprocess.Popen(argv, stdout=s1, preexec_fn=setup) e = None break except OSError, e: pass
def connect(ssh_cmd, rhostport, python, stderr, options): main_exe = sys.argv[0] portl = [] if (rhostport or '').count(':') > 1: if rhostport.count(']') or rhostport.count('['): result = rhostport.split(']') rhost = result[0].strip('[') if len(result) > 1: result[1] = result[1].strip(':') if result[1] is not '': portl = ['-p', str(int(result[1]))] else: # can't disambiguate IPv6 colons and a port number. pass the hostname through. rhost = rhostport else: # IPv4 l = (rhostport or '').split(':', 1) rhost = l[0] if len(l) > 1: portl = ['-p', str(int(l[1]))] if rhost == '-': rhost = None z = zlib.compressobj(1) content = readfile('assembler.py') optdata = ''.join("%s=%r\n" % (k, v) for (k, v) in options.items()) content2 = (empackage(z, 'cmdline_options.py', optdata) + empackage(z, 'helpers.py') + empackage(z, 'compat/ssubprocess.py') + empackage(z, 'ssnet.py') + empackage(z, 'hostwatch.py') + empackage(z, 'server.py') + "\n") pyscript = r""" import sys; skip_imports=1; verbosity=%d; exec compile(sys.stdin.read(%d), "assembler.py", "exec") """ % (helpers.verbose or 0, len(content)) pyscript = re.sub(r'\s+', ' ', pyscript.strip()) if not rhost: # ignore the --python argument when running locally; we already know # which python version works. argv = [sys.argv[1], '-c', pyscript] else: if ssh_cmd: sshl = ssh_cmd.split(' ') else: sshl = ['ssh'] if python: pycmd = "'%s' -c '%s'" % (python, pyscript) else: pycmd = ("P=python2; $P -V 2>/dev/null || P=python; " "exec \"$P\" -c '%s'") % pyscript argv = (sshl + portl + [rhost, '--', pycmd]) (s1, s2) = socket.socketpair() def setup(): # runs in the child process s2.close() s1a, s1b = os.dup(s1.fileno()), os.dup(s1.fileno()) s1.close() debug2('executing: %r\n' % argv) p = ssubprocess.Popen(argv, stdin=s1a, stdout=s1b, preexec_fn=setup, close_fds=True, stderr=stderr) os.close(s1a) os.close(s1b) s2.sendall(content) s2.sendall(content2) return p, s2
def start_syslog(): global _p _p = ssubprocess.Popen(['logger', '-p', 'daemon.notice', '-t', 'sshuttle'], stdin=ssubprocess.PIPE)