From 6ecb91e214be29d54b55a7f9b9b8f2bd0ff55b0b Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 30 Nov 2024 16:38:09 -0800 Subject: [PATCH] Add logging for hostname canonicalization feature --- asyncssh/connection.py | 25 ++++++++++++++++++++++--- tests/test_connection.py | 10 ++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/asyncssh/connection.py b/asyncssh/connection.py index 3c666c0..201e44b 100644 --- a/asyncssh/connection.py +++ b/asyncssh/connection.py @@ -281,8 +281,12 @@ async def _canonicalize_host(loop: asyncio.AbstractEventLoop, host = options.host - if not options.canonicalize_hostname or not options.canonical_domains or \ - host.count('.') > options.canonicalize_max_dots: + if not options.canonicalize_hostname or not options.canonical_domains: + logger.info('Host canonicalization disabled') + return None + + if host.count('.') > options.canonicalize_max_dots: + logger.info('Host canonicalization skipped due to max dots') return None try: @@ -290,9 +294,14 @@ async def _canonicalize_host(loop: asyncio.AbstractEventLoop, except ValueError: pass else: + logger.info('Hostname canonicalization skipped on IP address') return None + logger.debug1('Beginning hostname canonicalization') + for domain in options.canonical_domains: + logger.debug1(' Checking domain %s', domain) + canon_host = f'{host}.{domain}' try: @@ -303,18 +312,28 @@ async def _canonicalize_host(loop: asyncio.AbstractEventLoop, cname = addrinfo[0][3] - if cname: + if cname and cname != canon_host: + logger.debug1(' Checking CNAME rules for hostname %s ' + 'with CNAME %s', canon_host, cname) + for patterns in options.canonicalize_permitted_cnames: host_pat, cname_pat = map(WildcardPatternList, patterns) if host_pat.matches(canon_host) and cname_pat.matches(cname): + logger.info('Hostname canonicalization to CNAME ' + 'applied: %s -> %s', options.host, cname) return cname + logger.info('Hostname canonicalization applied: %s -> %s', + options.host, canon_host) + return canon_host if not options.canonicalize_fallback_local: + logger.info('Hostname canonicalization failed (fallback disabled)') raise OSError(f'Unable to canonicalize hostname "{host}"') + logger.info('Hostname canonicalization failed, using local resolver') return None diff --git a/tests/test_connection.py b/tests/test_connection.py index d1a0826..9c8c1ce 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -2693,6 +2693,16 @@ async def test_canonicalize(self): canonical_domains=['test']) as conn: self.assertEqual(conn.get_extra_info('host'), 'testhost.test') + @asynctest + async def test_canonicalize_max_dots(self): + """Test hostname canonicalization exceeding max_dots""" + + async with self.connect('testhost.test', known_hosts=None, + canonicalize_hostname=True, + canonicalize_max_dots=0, + canonical_domains=['test']) as conn: + self.assertEqual(conn.get_extra_info('host'), 'testhost.test') + @asynctest async def test_canonicalize_ip_address(self): """Test hostname canonicalization with IP address"""