summaryrefslogtreecommitdiffstats
path: root/custom_components/patch_asyncssh/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'custom_components/patch_asyncssh/__init__.py')
-rw-r--r--custom_components/patch_asyncssh/__init__.py49
1 files changed, 49 insertions, 0 deletions
diff --git a/custom_components/patch_asyncssh/__init__.py b/custom_components/patch_asyncssh/__init__.py
new file mode 100644
index 0000000..cdcb095
--- /dev/null
+++ b/custom_components/patch_asyncssh/__init__.py
@@ -0,0 +1,49 @@
+# /config/custom_components/patch_asyncssh/__init__.py
+from __future__ import annotations
+import logging
+
+_LOGGER = logging.getLogger(__name__)
+
+async def async_setup(hass, config):
+ """Patch asyncssh at HA startup, then return True to finish setup."""
+ try:
+ import asyncssh
+
+ # Re-expose ReadHostKeysPolicy at top-level for libs that expect it
+ try:
+ from asyncssh.hostkeys import ReadHostKeysPolicy
+ asyncssh.ReadHostKeysPolicy = ReadHostKeysPolicy # type: ignore[attr-defined]
+ except Exception:
+ pass
+
+ # Patch only once
+ if not getattr(asyncssh, "_ha_patched_connect", False):
+ _real_connect = asyncssh.connect
+
+ def _patched_connect(*args, **kwargs):
+ # Expand allowed *server* host key algorithms to match Dropbear
+ algs = list(
+ kwargs.get("server_host_key_algs")
+ or kwargs.get("host_key_algs")
+ or []
+ )
+ wanted = ["ssh-ed25519", "ecdsa-sha2-nistp256", "rsa-sha2-256"]
+ for a in wanted:
+ if a not in algs:
+ algs.append(a)
+ kwargs["server_host_key_algs"] = algs or wanted
+
+ return _real_connect(*args, **kwargs)
+
+ asyncssh.connect = _patched_connect # type: ignore[assignment]
+ asyncssh._ha_patched_connect = True # type: ignore[attr-defined]
+ _LOGGER.info(
+ "patch_asyncssh: asyncssh.connect patched (added algs %s)",
+ ["ssh-ed25519", "ecdsa-sha2-nistp256", "rsa-sha2-256"],
+ )
+ else:
+ _LOGGER.debug("patch_asyncssh: asyncssh.connect already patched")
+ except Exception:
+ _LOGGER.exception("patch_asyncssh: failed to patch asyncssh")
+
+ return True