summaryrefslogtreecommitdiffstats
path: root/custom_components/patch_asyncssh
diff options
context:
space:
mode:
Diffstat (limited to 'custom_components/patch_asyncssh')
-rw-r--r--custom_components/patch_asyncssh/__init__.py49
-rw-r--r--custom_components/patch_asyncssh/__pycache__/__init__.cpython-312.pycbin0 -> 2002 bytes
-rw-r--r--custom_components/patch_asyncssh/manifest.json9
3 files changed, 58 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
diff --git a/custom_components/patch_asyncssh/__pycache__/__init__.cpython-312.pyc b/custom_components/patch_asyncssh/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..1788a71
--- /dev/null
+++ b/custom_components/patch_asyncssh/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/custom_components/patch_asyncssh/manifest.json b/custom_components/patch_asyncssh/manifest.json
new file mode 100644
index 0000000..7017f14
--- /dev/null
+++ b/custom_components/patch_asyncssh/manifest.json
@@ -0,0 +1,9 @@
+{
+ "domain": "patch_asyncssh",
+ "name": "Patch AsyncSSH (host key algs)",
+ "version": "0.0.1",
+ "documentation": "",
+ "requirements": [],
+ "codeowners": [],
+ "iot_class": "local_push"
+}