diff options
author | Brian May <brian@linuxpenguins.xyz> | 2016-01-17 10:17:44 +1100 |
---|---|---|
committer | Brian May <brian@linuxpenguins.xyz> | 2016-01-17 10:21:21 +1100 |
commit | 7f0b5c698b6336f91c9587f2dc10e2439d0f73bd (patch) | |
tree | e718e284733246b8ee9e0b592e1effa002b0e90d | |
parent | f59508f41b5543159a3ada57ffdb4bd11a805b54 (diff) |
Fix installation from wheel
Fix the following error. Looks like we have to have a function to call
for the entrypoint.
$ pip install dist/sshuttle-0.76.dev8_ngf59508f-py2-none-any.whl
Processing ./dist/sshuttle-0.76.dev8_ngf59508f-py2-none-any.whl
Installing collected packages: sshuttle
Exception:
Traceback (most recent call last):
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/basecommand.py", line 211, in main
status = self.run(options, args)
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/commands/install.py", line 311, in run
root=options.root_path,
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/req/req_set.py", line 646, in install
**kwargs
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/req/req_install.py", line 803, in install
self.move_wheel_files(self.source_dir, root=root)
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/req/req_install.py", line 998, in move_wheel_files
isolated=self.isolated,
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/wheel.py", line 479, in move_wheel_files
maker.make_multiple(['%s = %s' % kv for kv in console.items()])
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 364, in make_multiple
filenames.extend(self.make(specification, options))
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 353, in make
self._make_script(entry, filenames, options=options)
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 244, in _make_script
script = self._get_script_text(entry).encode('utf-8')
File "/tmp/ddd/local/lib/python2.7/site-packages/pip/wheel.py", line 396, in _get_script_text
"import_name": entry.suffix.split(".")[0],
AttributeError: 'NoneType' object has no attribute 'split'
-rwxr-xr-x | setup.py | 2 | ||||
-rw-r--r-- | sshuttle/__main__.py | 240 | ||||
-rw-r--r-- | sshuttle/cmdline.py | 240 |
3 files changed, 244 insertions, 238 deletions
@@ -53,7 +53,7 @@ setup( ], entry_points={ 'console_scripts': [ - 'sshuttle = sshuttle.__main__', + 'sshuttle = sshuttle.cmdline:main', ], }, tests_require=['pytest', 'mock'], diff --git a/sshuttle/__main__.py b/sshuttle/__main__.py index 19803d0..b4bd42f 100644 --- a/sshuttle/__main__.py +++ b/sshuttle/__main__.py @@ -1,238 +1,4 @@ +"""Coverage.py's main entry point.""" import sys -import re -import socket -import sshuttle.helpers as helpers -import sshuttle.options as options -import sshuttle.client as client -import sshuttle.firewall as firewall -import sshuttle.hostwatch as hostwatch -import sshuttle.ssyslog as ssyslog -from sshuttle.helpers import family_ip_tuple, log, Fatal - - -# 1.2.3.4/5 or just 1.2.3.4 -def parse_subnet4(s): - m = re.match(r'(\d+)(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?$', s) - if not m: - raise Fatal('%r is not a valid IP subnet format' % s) - (a, b, c, d, width) = m.groups() - (a, b, c, d) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0)) - if width is None: - width = 32 - else: - width = int(width) - if a > 255 or b > 255 or c > 255 or d > 255: - raise Fatal('%d.%d.%d.%d has numbers > 255' % (a, b, c, d)) - if width > 32: - raise Fatal('*/%d is greater than the maximum of 32' % width) - return(socket.AF_INET, '%d.%d.%d.%d' % (a, b, c, d), width) - - -# 1:2::3/64 or just 1:2::3 -def parse_subnet6(s): - m = re.match(r'(?:([a-fA-F\d:]+))?(?:/(\d+))?$', s) - if not m: - raise Fatal('%r is not a valid IP subnet format' % s) - (net, width) = m.groups() - if width is None: - width = 128 - else: - width = int(width) - if width > 128: - raise Fatal('*/%d is greater than the maximum of 128' % width) - return(socket.AF_INET6, net, width) - - -# Subnet file, supporting empty lines and hash-started comment lines -def parse_subnet_file(s): - try: - handle = open(s, 'r') - except OSError: - raise Fatal('Unable to open subnet file: %s' % s) - - raw_config_lines = handle.readlines() - config_lines = [] - for line_no, line in enumerate(raw_config_lines): - line = line.strip() - if len(line) == 0: - continue - if line[0] == '#': - continue - config_lines.append(line) - - return config_lines - - -# list of: -# 1.2.3.4/5 or just 1.2.3.4 -# 1:2::3/64 or just 1:2::3 -def parse_subnets(subnets_str): - subnets = [] - for s in subnets_str: - if ':' in s: - subnet = parse_subnet6(s) - else: - subnet = parse_subnet4(s) - subnets.append(subnet) - return subnets - - -# 1.2.3.4:567 or just 1.2.3.4 or just 567 -def parse_ipport4(s): - s = str(s) - m = re.match(r'(?:(\d+)\.(\d+)\.(\d+)\.(\d+))?(?::)?(?:(\d+))?$', s) - if not m: - raise Fatal('%r is not a valid IP:port format' % s) - (a, b, c, d, port) = m.groups() - (a, b, c, d, port) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0), - int(port or 0)) - if a > 255 or b > 255 or c > 255 or d > 255: - raise Fatal('%d.%d.%d.%d has numbers > 255' % (a, b, c, d)) - if port > 65535: - raise Fatal('*:%d is greater than the maximum of 65535' % port) - if a is None: - a = b = c = d = 0 - return ('%d.%d.%d.%d' % (a, b, c, d), port) - - -# [1:2::3]:456 or [1:2::3] or 456 -def parse_ipport6(s): - s = str(s) - m = re.match(r'(?:\[([^]]*)])?(?::)?(?:(\d+))?$', s) - if not m: - raise Fatal('%s is not a valid IP:port format' % s) - (ip, port) = m.groups() - (ip, port) = (ip or '::', int(port or 0)) - return (ip, port) - - -def parse_list(list): - return re.split(r'[\s,]+', list.strip()) if list else [] - - -optspec = """ -sshuttle [-l [ip:]port] [-r [username@]sshserver[:port]] <subnets...> -sshuttle --firewall <port> <subnets...> -sshuttle --hostwatch --- -l,listen= transproxy to this ip address and port number -H,auto-hosts scan for remote hostnames and update local /etc/hosts -N,auto-nets automatically determine subnets to route -dns capture local DNS requests and forward to the remote DNS server -ns-hosts= capture and forward remote DNS requests to the following servers -method= auto, nat, tproxy or pf -python= path to python interpreter on the remote server -r,remote= ssh hostname (and optional username) of remote sshuttle server -x,exclude= exclude this subnet (can be used more than once) -X,exclude-from= exclude the subnets in a file (whitespace separated) -v,verbose increase debug message verbosity -V,version print the sshuttle version number and exit -e,ssh-cmd= the command to use to connect to the remote [ssh] -seed-hosts= with -H, use these hostnames for initial scan (comma-separated) -no-latency-control sacrifice latency to improve bandwidth benchmarks -wrap= restart counting channel numbers after this number (for testing) -disable-ipv6 disables ipv6 support -D,daemon run in the background as a daemon -s,subnets= file where the subnets are stored, instead of on the command line -syslog send log messages to syslog (default if you use --daemon) -pidfile= pidfile name (only if using --daemon) [./sshuttle.pid] -server (internal use only) -firewall (internal use only) -hostwatch (internal use only) -""" -o = options.Options(optspec) -(opt, flags, extra) = o.parse(sys.argv[1:]) - -if opt.version: - from sshuttle.version import version - print(version) - exit(0) -if opt.daemon: - opt.syslog = 1 -if opt.wrap: - import sshuttle.ssnet as ssnet - ssnet.MAX_CHANNEL = int(opt.wrap) -helpers.verbose = opt.verbose or 0 - -try: - if opt.firewall: - if len(extra) != 0: - o.fatal('exactly zero arguments expected') - result = firewall.main(opt.method, opt.syslog) - sys.exit(result) - elif opt.hostwatch: - sys.exit(hostwatch.hw_main(extra)) - else: - if len(extra) < 1 and not opt.auto_nets and not opt.subnets: - o.fatal('at least one subnet, subnet file, or -N expected') - includes = extra - excludes = ['127.0.0.0/8'] - for k, v in flags: - if k in ('-x', '--exclude'): - excludes.append(v) - if k in ('-X', '--exclude-from'): - excludes += open(v).read().split() - remotename = opt.remote - if remotename == '' or remotename == '-': - remotename = None - nslist = [family_ip_tuple(ns) for ns in parse_list(opt.ns_hosts)] - if opt.seed_hosts and not opt.auto_hosts: - o.fatal('--seed-hosts only works if you also use -H') - if opt.seed_hosts: - sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) - elif opt.auto_hosts: - sh = [] - else: - sh = None - if opt.subnets: - includes = parse_subnet_file(opt.subnets) - if not opt.method: - method_name = "auto" - elif opt.method in ["auto", "nat", "tproxy", "pf"]: - method_name = opt.method - else: - o.fatal("method_name %s not supported" % opt.method) - if opt.listen: - ipport_v6 = None - ipport_v4 = None - list = opt.listen.split(",") - for ip in list: - if '[' in ip and ']' in ip: - ipport_v6 = parse_ipport6(ip) - else: - ipport_v4 = parse_ipport4(ip) - else: - # parse_ipport4('127.0.0.1:0') - ipport_v4 = "auto" - # parse_ipport6('[::1]:0') - ipport_v6 = "auto" if not opt.disable_ipv6 else None - if opt.syslog: - ssyslog.start_syslog() - ssyslog.stderr_to_syslog() - return_code = client.main(ipport_v6, ipport_v4, - opt.ssh_cmd, - remotename, - opt.python, - opt.latency_control, - opt.dns, - nslist, - method_name, - sh, - opt.auto_nets, - parse_subnets(includes), - parse_subnets(excludes), - opt.daemon, opt.pidfile) - - if return_code == 0: - log('Normal exit code, exiting...') - else: - log('Abnormal exit code detected, failing...' % return_code) - sys.exit(return_code) - -except Fatal as e: - log('fatal: %s\n' % e) - sys.exit(99) -except KeyboardInterrupt: - log('\n') - log('Keyboard interrupt: exiting.\n') - sys.exit(1) +from sshuttle.cmdline import main +sys.exit(main()) diff --git a/sshuttle/cmdline.py b/sshuttle/cmdline.py new file mode 100644 index 0000000..48c0fbe --- /dev/null +++ b/sshuttle/cmdline.py @@ -0,0 +1,240 @@ +import sys +import re +import socket +import sshuttle.helpers as helpers +import sshuttle.options as options +import sshuttle.client as client +import sshuttle.firewall as firewall +import sshuttle.hostwatch as hostwatch +import sshuttle.ssyslog as ssyslog +from sshuttle.helpers import family_ip_tuple, log, Fatal + + +# 1.2.3.4/5 or just 1.2.3.4 +def parse_subnet4(s): + m = re.match(r'(\d+)(?:\.(\d+)\.(\d+)\.(\d+))?(?:/(\d+))?$', s) + if not m: + raise Fatal('%r is not a valid IP subnet format' % s) + (a, b, c, d, width) = m.groups() + (a, b, c, d) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0)) + if width is None: + width = 32 + else: + width = int(width) + if a > 255 or b > 255 or c > 255 or d > 255: + raise Fatal('%d.%d.%d.%d has numbers > 255' % (a, b, c, d)) + if width > 32: + raise Fatal('*/%d is greater than the maximum of 32' % width) + return(socket.AF_INET, '%d.%d.%d.%d' % (a, b, c, d), width) + + +# 1:2::3/64 or just 1:2::3 +def parse_subnet6(s): + m = re.match(r'(?:([a-fA-F\d:]+))?(?:/(\d+))?$', s) + if not m: + raise Fatal('%r is not a valid IP subnet format' % s) + (net, width) = m.groups() + if width is None: + width = 128 + else: + width = int(width) + if width > 128: + raise Fatal('*/%d is greater than the maximum of 128' % width) + return(socket.AF_INET6, net, width) + + +# Subnet file, supporting empty lines and hash-started comment lines +def parse_subnet_file(s): + try: + handle = open(s, 'r') + except OSError: + raise Fatal('Unable to open subnet file: %s' % s) + + raw_config_lines = handle.readlines() + config_lines = [] + for line_no, line in enumerate(raw_config_lines): + line = line.strip() + if len(line) == 0: + continue + if line[0] == '#': + continue + config_lines.append(line) + + return config_lines + + +# list of: +# 1.2.3.4/5 or just 1.2.3.4 +# 1:2::3/64 or just 1:2::3 +def parse_subnets(subnets_str): + subnets = [] + for s in subnets_str: + if ':' in s: + subnet = parse_subnet6(s) + else: + subnet = parse_subnet4(s) + subnets.append(subnet) + return subnets + + +# 1.2.3.4:567 or just 1.2.3.4 or just 567 +def parse_ipport4(s): + s = str(s) + m = re.match(r'(?:(\d+)\.(\d+)\.(\d+)\.(\d+))?(?::)?(?:(\d+))?$', s) + if not m: + raise Fatal('%r is not a valid IP:port format' % s) + (a, b, c, d, port) = m.groups() + (a, b, c, d, port) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0), + int(port or 0)) + if a > 255 or b > 255 or c > 255 or d > 255: + raise Fatal('%d.%d.%d.%d has numbers > 255' % (a, b, c, d)) + if port > 65535: + raise Fatal('*:%d is greater than the maximum of 65535' % port) + if a is None: + a = b = c = d = 0 + return ('%d.%d.%d.%d' % (a, b, c, d), port) + + +# [1:2::3]:456 or [1:2::3] or 456 +def parse_ipport6(s): + s = str(s) + m = re.match(r'(?:\[([^]]*)])?(?::)?(?:(\d+))?$', s) + if not m: + raise Fatal('%s is not a valid IP:port format' % s) + (ip, port) = m.groups() + (ip, port) = (ip or '::', int(port or 0)) + return (ip, port) + + +def parse_list(list): + return re.split(r'[\s,]+', list.strip()) if list else [] + + +optspec = """ +sshuttle [-l [ip:]port] [-r [username@]sshserver[:port]] <subnets...> +sshuttle --firewall <port> <subnets...> +sshuttle --hostwatch +-- +l,listen= transproxy to this ip address and port number +H,auto-hosts scan for remote hostnames and update local /etc/hosts +N,auto-nets automatically determine subnets to route +dns capture local DNS requests and forward to the remote DNS server +ns-hosts= capture and forward remote DNS requests to the following servers +method= auto, nat, tproxy or pf +python= path to python interpreter on the remote server +r,remote= ssh hostname (and optional username) of remote sshuttle server +x,exclude= exclude this subnet (can be used more than once) +X,exclude-from= exclude the subnets in a file (whitespace separated) +v,verbose increase debug message verbosity +V,version print the sshuttle version number and exit +e,ssh-cmd= the command to use to connect to the remote [ssh] +seed-hosts= with -H, use these hostnames for initial scan (comma-separated) +no-latency-control sacrifice latency to improve bandwidth benchmarks +wrap= restart counting channel numbers after this number (for testing) +disable-ipv6 disables ipv6 support +D,daemon run in the background as a daemon +s,subnets= file where the subnets are stored, instead of on the command line +syslog send log messages to syslog (default if you use --daemon) +pidfile= pidfile name (only if using --daemon) [./sshuttle.pid] +server (internal use only) +firewall (internal use only) +hostwatch (internal use only) +""" + + +def main(): + o = options.Options(optspec) + (opt, flags, extra) = o.parse(sys.argv[1:]) + + if opt.version: + from sshuttle.version import version + print(version) + return 0 + if opt.daemon: + opt.syslog = 1 + if opt.wrap: + import sshuttle.ssnet as ssnet + ssnet.MAX_CHANNEL = int(opt.wrap) + helpers.verbose = opt.verbose or 0 + + try: + if opt.firewall: + if len(extra) != 0: + o.fatal('exactly zero arguments expected') + return firewall.main(opt.method, opt.syslog) + elif opt.hostwatch: + return hostwatch.hw_main(extra) + else: + if len(extra) < 1 and not opt.auto_nets and not opt.subnets: + o.fatal('at least one subnet, subnet file, or -N expected') + includes = extra + excludes = ['127.0.0.0/8'] + for k, v in flags: + if k in ('-x', '--exclude'): + excludes.append(v) + if k in ('-X', '--exclude-from'): + excludes += open(v).read().split() + remotename = opt.remote + if remotename == '' or remotename == '-': + remotename = None + nslist = [family_ip_tuple(ns) for ns in parse_list(opt.ns_hosts)] + if opt.seed_hosts and not opt.auto_hosts: + o.fatal('--seed-hosts only works if you also use -H') + if opt.seed_hosts: + sh = re.split(r'[\s,]+', (opt.seed_hosts or "").strip()) + elif opt.auto_hosts: + sh = [] + else: + sh = None + if opt.subnets: + includes = parse_subnet_file(opt.subnets) + if not opt.method: + method_name = "auto" + elif opt.method in ["auto", "nat", "tproxy", "pf"]: + method_name = opt.method + else: + o.fatal("method_name %s not supported" % opt.method) + if opt.listen: + ipport_v6 = None + ipport_v4 = None + list = opt.listen.split(",") + for ip in list: + if '[' in ip and ']' in ip: + ipport_v6 = parse_ipport6(ip) + else: + ipport_v4 = parse_ipport4(ip) + else: + # parse_ipport4('127.0.0.1:0') + ipport_v4 = "auto" + # parse_ipport6('[::1]:0') + ipport_v6 = "auto" if not opt.disable_ipv6 else None + if opt.syslog: + ssyslog.start_syslog() + ssyslog.stderr_to_syslog() + return_code = client.main(ipport_v6, ipport_v4, + opt.ssh_cmd, + remotename, + opt.python, + opt.latency_control, + opt.dns, + nslist, + method_name, + sh, + opt.auto_nets, + parse_subnets(includes), + parse_subnets(excludes), + opt.daemon, opt.pidfile) + + if return_code == 0: + log('Normal exit code, exiting...') + else: + log('Abnormal exit code detected, failing...' % return_code) + return return_code + + except Fatal as e: + log('fatal: %s\n' % e) + return 99 + except KeyboardInterrupt: + log('\n') + log('Keyboard interrupt: exiting.\n') + return 1 |