summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortobigrimm <tobi-github@grimm.gr>2020-04-25 01:40:39 +0200
committerGitHub <noreply@github.com>2020-04-25 09:40:39 +1000
commit966fd0c5231d56c4f464752865d96f97bd3c0aac (patch)
tree3dc75ed4d2763ca251c8bf892832d3949b8ab5f4
parent580462156e49e905e371ae7de01e86a811ccdbbb (diff)
Fix parsing of hostnames to allow ssh aliases defined in ssh configs) (#418)
* Fix parsing of hostnames to allow ssh aliases defined in ssh configs) * nicer formatting, pep8 applied * Properly parse IPv6 addresses with port specification * Now also handles hostnames with port specified and IPv6 addresses without port properly * Updated parameter description for the remotehost specification * Make the urlparse import backwards compatible to python2 Co-authored-by: Tobi <tobi-git@grimm.gr>
-rw-r--r--sshuttle/options.py4
-rw-r--r--sshuttle/ssh.py81
2 files changed, 52 insertions, 33 deletions
diff --git a/sshuttle/options.py b/sshuttle/options.py
index 79c404b..12ce55d 100644
--- a/sshuttle/options.py
+++ b/sshuttle/options.py
@@ -177,9 +177,9 @@ parser.add_argument(
)
parser.add_argument(
"-r", "--remote",
- metavar="[USERNAME@]ADDR[:PORT]",
+ metavar="[USERNAME[:PASSWORD]@]ADDR[:PORT]",
help="""
- ssh hostname (and optional username) of remote %(prog)s server
+ ssh hostname (and optional username and password) of remote %(prog)s server
"""
)
parser.add_argument(
diff --git a/sshuttle/ssh.py b/sshuttle/ssh.py
index 9f99ff7..72951f6 100644
--- a/sshuttle/ssh.py
+++ b/sshuttle/ssh.py
@@ -6,6 +6,14 @@ import zlib
import imp
import subprocess as ssubprocess
import shlex
+import ipaddress
+
+# ensure backwards compatiblity with python2.7
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urlparse import urlparse
+
import sshuttle.helpers as helpers
from sshuttle.helpers import debug2
@@ -61,53 +69,64 @@ def empackage(z, name, data=None):
def parse_hostport(rhostport):
- # default define variable
- port = ""
- username = re.split(r'\s*:', rhostport)[0]
+ """
+ parses the given rhostport variable, looking like this:
+
+ [username[:password]@]host[:port]
- # Fix #410 bad username error detect
- if "@" in username:
- username = re.split(r'\s*@', rhostport)[0]
+ if only host is given, can be a hostname, IPv4/v6 address or a ssh alias
+ from ~/.ssh/config
+ and returns a tuple (username, password, port, host)
+ """
+ # default port for SSH is TCP port 22
+ port = 22
+ username = None
password = None
- host = None
+ host = rhostport
- try:
- password = re.split(r'\s*:', rhostport)[1]
- if "@" in password:
- password = password.split("@")[0]
- except (IndexError, TypeError):
- pass
-
- if password is None or "@" in password:
- # default define password
- password = None
- host = password
+ if "@" in host:
+ # split username (and possible password) from the host[:port]
+ username, host = host.split("@")
+ # Fix #410 bad username error detect
+ # username cannot contain an @ sign in this scenario
+ if ":" in username:
+ # this will even allow for the username to be empty
+ username, password = username.split(":")
+
+ if ":" in host:
+ # IPv6 address and/or got a port specified
- if host is None:
- # split for ipv4 or ipv6
- host = "{}".format(re.split(r'\s*@', rhostport)[1])
+ # If it is an IPv6 adress with port specification,
+ # then it will look like: [::1]:22
- # try if port define
try:
- # Fix #410 detect host:port
- port = re.split(r'\s*:', host)[1]
- host = re.split(r'\s*:', host)[0]
- except IndexError:
- pass
+ # try to parse host as an IP adress,
+ # if that works it is an IPv6 address
+ host = ipaddress.ip_address(host)
+ except ValueError:
+ # if that fails parse as URL to get the port
+ parsed = urlparse('//{}'.format(host))
+ try:
+ host = ipaddress.ip_address(parsed.hostname)
+ except ValueError:
+ # else if both fails, we have a hostname with port
+ host = parsed.hostname
+ port = parsed.port
- if port == "":
- port = 22
if password is None or len(password) == 0:
password = None
return username, password, port, host
+
def connect(ssh_cmd, rhostport, python, stderr, options):
username, password, port, host = parse_hostport(rhostport)
-
- rhost = "{}@{}".format(username, host)
+ if username:
+ rhost = "{}@{}".format(username, host)
+ else:
+ rhost = host
z = zlib.compressobj(1)
content = readfile('sshuttle.assembler')