summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2019-12-03 14:04:00 -0500
committerJeff Forcier <jeff@bitprophet.org>2019-12-03 14:04:00 -0500
commit84fa355a253d30d6c39adaea8bb095ced0c3b751 (patch)
treedda481f679fbd57b7a1760dfa42903b5a9e58b59
parent8ce1e4c36c43363dcc5964daaf6e06754bf12cc2 (diff)
downloadparamiko-84fa355a253d30d6c39adaea8bb095ced0c3b751.tar.gz
Apply %h tokenization to HostName
This was another spot that incidentally occurred in older (and moved) code, but was made incorrect after cleanup
-rw-r--r--paramiko/config.py12
-rw-r--r--tests/configs/hostname-exec-tokenized2
-rw-r--r--tests/configs/hostname-tokenized1
-rw-r--r--tests/test_config.py10
4 files changed, 19 insertions, 6 deletions
diff --git a/paramiko/config.py b/paramiko/config.py
index bef42610..e6877d01 100644
--- a/paramiko/config.py
+++ b/paramiko/config.py
@@ -60,6 +60,7 @@ class SSHConfig(object):
# compatible across the board, e.g. OpenSSH 8.1 added %n to ProxyCommand.
TOKENS_BY_CONFIG_KEY = {
"controlpath": ["%h", "%l", "%L", "%n", "%p", "%r", "%u"],
+ "hostname": ["%h"],
"identityfile": ["~", "%d", "%h", "%l", "%u", "%r"],
"proxycommand": ["~", "%h", "%p", "%r"],
# Doesn't seem worth making this 'special' for now, it will fit well
@@ -412,13 +413,12 @@ class SSHConfig(object):
# Short-circuit if no tokenization possible
if not allowed_tokens:
return value
- # Obtain potentially configured (and even possibly itself tokenized)
- # hostname, for use with %h in other values.
+ # Obtain potentially configured hostname, for use with %h.
+ # Special-case where we are tokenizing the hostname itself, to avoid
+ # replacing %h with a %h-bearing value, etc.
configured_hostname = target_hostname
- if "hostname" in config:
- configured_hostname = config["hostname"].replace(
- "%h", target_hostname
- )
+ if key != "hostname":
+ configured_hostname = config.get("hostname", configured_hostname)
# Ditto the rest of the source values
if "port" in config:
port = config["port"]
diff --git a/tests/configs/hostname-exec-tokenized b/tests/configs/hostname-exec-tokenized
new file mode 100644
index 00000000..1cae2c03
--- /dev/null
+++ b/tests/configs/hostname-exec-tokenized
@@ -0,0 +1,2 @@
+Match exec "ping %h"
+ HostName pingable.%h
diff --git a/tests/configs/hostname-tokenized b/tests/configs/hostname-tokenized
new file mode 100644
index 00000000..1905c0cc
--- /dev/null
+++ b/tests/configs/hostname-tokenized
@@ -0,0 +1 @@
+HostName prefix.%h
diff --git a/tests/test_config.py b/tests/test_config.py
index 7c86667a..5e9aa059 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -467,6 +467,10 @@ Host *
cmd = config.lookup("some-random-host")["proxycommand"]
assert cmd == "default-proxy"
+ def test_hostname_tokenization(self):
+ result = load_config("hostname-tokenized").lookup("whatever")
+ assert result["hostname"] == "prefix.whatever"
+
class TestSSHConfigDict(object):
def test_SSHConfigDict_construct_empty(self):
@@ -774,6 +778,12 @@ class TestMatchExec(object):
with raises(ConfigParseError):
load_config("match-exec-no-arg")
+ @patch("paramiko.config.invoke.run")
+ def test_works_with_tokenized_hostname(self, run):
+ run.side_effect = _expect("ping target")
+ result = load_config("hostname-exec-tokenized").lookup("target")
+ assert result["hostname"] == "pingable.target"
+
class TestMatchHost(object):
def test_matches_target_name_when_no_hostname(self):