summaryrefslogtreecommitdiff
path: root/paramiko/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'paramiko/config.py')
-rw-r--r--paramiko/config.py145
1 files changed, 70 insertions, 75 deletions
diff --git a/paramiko/config.py b/paramiko/config.py
index 1705de7..77fa13d 100644
--- a/paramiko/config.py
+++ b/paramiko/config.py
@@ -18,7 +18,7 @@
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
"""
-L{SSHConfig}.
+Configuration file (aka ``ssh_config``) support.
"""
import fnmatch
@@ -30,69 +30,15 @@ SSH_PORT = 22
proxy_re = re.compile(r"^(proxycommand)\s*=*\s*(.*)", re.I)
-class LazyFqdn(object):
- """
- Returns the host's fqdn on request as string.
- """
-
- def __init__(self, config, host=None):
- self.fqdn = None
- self.config = config
- self.host = host
-
- def __str__(self):
- if self.fqdn is None:
- #
- # If the SSH config contains AddressFamily, use that when
- # determining the local host's FQDN. Using socket.getfqdn() from
- # the standard library is the most general solution, but can
- # result in noticeable delays on some platforms when IPv6 is
- # misconfigured or not available, as it calls getaddrinfo with no
- # address family specified, so both IPv4 and IPv6 are checked.
- #
-
- # Handle specific option
- fqdn = None
- address_family = self.config.get('addressfamily', 'any').lower()
- if address_family != 'any':
- try:
- family = socket.AF_INET if address_family == 'inet' \
- else socket.AF_INET6
- results = socket.getaddrinfo(
- self.host,
- None,
- family,
- socket.SOCK_DGRAM,
- socket.IPPROTO_IP,
- socket.AI_CANONNAME
- )
- for res in results:
- af, socktype, proto, canonname, sa = res
- if canonname and '.' in canonname:
- fqdn = canonname
- break
- # giaerror -> socket.getaddrinfo() can't resolve self.host
- # (which is from socket.gethostname()). Fall back to the
- # getfqdn() call below.
- except socket.gaierror:
- pass
- # Handle 'any' / unspecified
- if fqdn is None:
- fqdn = socket.getfqdn()
- # Cache
- self.fqdn = fqdn
- return self.fqdn
-
-
class SSHConfig (object):
"""
Representation of config information as stored in the format used by
- OpenSSH. Queries can be made via L{lookup}. The format is described in
- OpenSSH's C{ssh_config} man page. This class is provided primarily as a
+ OpenSSH. Queries can be made via `lookup`. The format is described in
+ OpenSSH's ``ssh_config`` man page. This class is provided primarily as a
convenience to posix users (since the OpenSSH format is a de-facto
standard on posix) but should work fine on Windows too.
- @since: 1.6
+ .. versionadded:: 1.6
"""
def __init__(self):
@@ -105,8 +51,7 @@ class SSHConfig (object):
"""
Read an OpenSSH config from the given file object.
- @param file_obj: a file-like object to read the config file from
- @type file_obj: file
+ :param file file_obj: a file-like object to read the config file from
"""
host = {"host": ['*'], "config": {}}
for line in file_obj:
@@ -152,28 +97,26 @@ class SSHConfig (object):
"""
Return a dict of config options for a given hostname.
- The host-matching rules of OpenSSH's C{ssh_config} man page are used,
+ The host-matching rules of OpenSSH's ``ssh_config`` man page are used,
which means that all configuration options from matching host
specifications are merged, with more specific hostmasks taking
- precedence. In other words, if C{"Port"} is set under C{"Host *"}
- and also C{"Host *.example.com"}, and the lookup is for
- C{"ssh.example.com"}, then the port entry for C{"Host *.example.com"}
+ precedence. In other words, if ``"Port"`` is set under ``"Host *"``
+ and also ``"Host *.example.com"``, and the lookup is for
+ ``"ssh.example.com"``, then the port entry for ``"Host *.example.com"``
will win out.
The keys in the returned dict are all normalized to lowercase (look for
- C{"port"}, not C{"Port"}. The values are processed according to the
- rules for substitution variable expansion in C{ssh_config}.
+ ``"port"``, not ``"Port"``. The values are processed according to the
+ rules for substitution variable expansion in ``ssh_config``.
- @param hostname: the hostname to lookup
- @type hostname: str
+ :param str hostname: the hostname to lookup
"""
-
matches = [config for config in self._config if
self._allowed(hostname, config['host'])]
ret = {}
for match in matches:
- for key, value in match['config'].iteritems():
+ for key, value in match['config'].items():
if key not in ret:
# Create a copy of the original value,
# else it will reference the original list
@@ -199,13 +142,11 @@ class SSHConfig (object):
Return a dict of config options with expanded substitutions
for a given hostname.
- Please refer to man C{ssh_config} for the parameters that
+ Please refer to man ``ssh_config`` for the parameters that
are replaced.
- @param config: the config for the hostname
- @type hostname: dict
- @param hostname: the hostname that the config belongs to
- @type hostname: str
+ :param dict config: the config for the hostname
+ :param str hostname: the hostname that the config belongs to
"""
if 'hostname' in config:
@@ -264,3 +205,57 @@ class SSHConfig (object):
else:
config[k] = config[k].replace(find, str(replace))
return config
+
+
+class LazyFqdn(object):
+ """
+ Returns the host's fqdn on request as string.
+ """
+
+ def __init__(self, config, host=None):
+ self.fqdn = None
+ self.config = config
+ self.host = host
+
+ def __str__(self):
+ if self.fqdn is None:
+ #
+ # If the SSH config contains AddressFamily, use that when
+ # determining the local host's FQDN. Using socket.getfqdn() from
+ # the standard library is the most general solution, but can
+ # result in noticeable delays on some platforms when IPv6 is
+ # misconfigured or not available, as it calls getaddrinfo with no
+ # address family specified, so both IPv4 and IPv6 are checked.
+ #
+
+ # Handle specific option
+ fqdn = None
+ address_family = self.config.get('addressfamily', 'any').lower()
+ if address_family != 'any':
+ try:
+ family = socket.AF_INET if address_family == 'inet' \
+ else socket.AF_INET6
+ results = socket.getaddrinfo(
+ self.host,
+ None,
+ family,
+ socket.SOCK_DGRAM,
+ socket.IPPROTO_IP,
+ socket.AI_CANONNAME
+ )
+ for res in results:
+ af, socktype, proto, canonname, sa = res
+ if canonname and '.' in canonname:
+ fqdn = canonname
+ break
+ # giaerror -> socket.getaddrinfo() can't resolve self.host
+ # (which is from socket.gethostname()). Fall back to the
+ # getfqdn() call below.
+ except socket.gaierror:
+ pass
+ # Handle 'any' / unspecified
+ if fqdn is None:
+ fqdn = socket.getfqdn()
+ # Cache
+ self.fqdn = fqdn
+ return self.fqdn