Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix misconfigured Haier TLS Certs #20

Merged
merged 4 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ __pycache__/
.idea/
scripts/translations/
scripts/test*
.venv/
22 changes: 14 additions & 8 deletions custom_components/hon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from pathlib import Path
from typing import Any

from aiohttp.client_exceptions import ClientConnectorCertificateError
from pyhon import Hon
import voluptuous as vol # type: ignore[import-untyped]

Expand All @@ -12,6 +13,7 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

from .const import CONF_REFRESH_TOKEN, DOMAIN, PLATFORMS
from .ssl import update_certifi_certificates

_LOGGER = logging.getLogger(__name__)

Expand All @@ -35,14 +37,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
email = entry.data[CONF_EMAIL]
password = entry.data[CONF_PASSWORD]
refresh_token = entry.data.get(CONF_REFRESH_TOKEN)
hon = await Hon(
email=email,
password=password,
session=session,
mqtt=True,
test_data_path=Path(config_dir),
refresh_token=refresh_token,
).setup()
try:
hon = await Hon(
email=email,
password=password,
session=session,
mqtt=True,
test_data_path=Path(config_dir),
refresh_token=refresh_token,
).setup()
except ClientConnectorCertificateError:
await update_certifi_certificates(hass)
return False

if (new_refresh_token := hon.auth.refresh_token) != refresh_token:
hass.config_entries.async_update_entry(
Expand Down
2 changes: 1 addition & 1 deletion custom_components/hon/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async def async_press(self) -> None:
persistent_notification.create(
self._hass, f"````\n```\n{diagnostic_info}\n```\n````", title
)
_LOGGER.info(diagnostic_info.replace(" ", "\u200B "))
_LOGGER.info(diagnostic_info.replace(" ", "\u200b "))


class HonDataArchive(HonEntity, ButtonEntity):
Expand Down
28 changes: 28 additions & 0 deletions custom_components/hon/ssl/RapidSSL_TLS_RSA_CA_G1.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIEszCCA5ugAwIBAgIQCyWUIs7ZgSoVoE6ZUooO+jANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xNzExMDIxMjI0MzNaFw0yNzExMDIxMjI0MzNaMGAxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xHzAdBgNVBAMTFlJhcGlkU1NMIFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC/uVklRBI1FuJdUEkFCuDL/I3aJQiaZ6aibRHj
ap/ap9zy1aYNrphe7YcaNwMoPsZvXDR+hNJOo9gbgOYVTPq8gXc84I75YKOHiVA4
NrJJQZ6p2sJQyqx60HkEIjzIN+1LQLfXTlpuznToOa1hyTD0yyitFyOYwURM+/CI
8FNFMpBhw22hpeAQkOOLmsqT5QZJYeik7qlvn8gfD+XdDnk3kkuuu0eG+vuyrSGr
5uX5LRhFWlv1zFQDch/EKmd163m6z/ycx/qLa9zyvILc7cQpb+k7TLra9WE17YPS
n9ANjG+ECo9PDW3N9lwhKQCNvw1gGoguyCQu7HE7BnW8eSSFAgMBAAGjggFmMIIB
YjAdBgNVHQ4EFgQUDNtsgkkPSmcKuBTuesRIUojrVjgwHwYDVR0jBBgwFoAUTiJU
IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB
BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud
HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds
b2JhbFJvb3RHMi5jcmwwYwYDVR0gBFwwWjA3BglghkgBhv1sAQEwKjAoBggrBgEF
BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sAQIw
CAYGZ4EMAQIBMAgGBmeBDAECAjANBgkqhkiG9w0BAQsFAAOCAQEAGUSlOb4K3Wtm
SlbmE50UYBHXM0SKXPqHMzk6XQUpCheF/4qU8aOhajsyRQFDV1ih/uPIg7YHRtFi
CTq4G+zb43X1T77nJgSOI9pq/TqCwtukZ7u9VLL3JAq3Wdy2moKLvvC8tVmRzkAe
0xQCkRKIjbBG80MSyDX/R4uYgj6ZiNT/Zg6GI6RofgqgpDdssLc0XIRQEotxIZcK
zP3pGJ9FCbMHmMLLyuBd+uCWvVcF2ogYAawufChS/PT61D9rqzPRS5I2uqa3tmIT
44JhJgWhBnFMb7AGQkvNq9KNS9dd3GWc17H/dXa1enoxzWjE0hBdFjxPhUb0W3wi
8o34/m8Fxw==
-----END CERTIFICATE-----
56 changes: 56 additions & 0 deletions custom_components/hon/ssl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import asyncio
import logging
from pathlib import Path
import shutil

import certifi
from homeassistant.core import HomeAssistant


_LOGGER = logging.getLogger(__name__)


# Heavily based on https://github.com/Athozs/hass-additional-ca/blob/c9499d39a4b4d7175336d1d31c4e1b6d9bd6932f/custom_components/additional_ca/__init__.py#L125
async def update_certifi_certificates(hass: HomeAssistant) -> bool:
"""Update CA certificates in Certifi bundle."""

certifi_bundle_path = Path(certifi.where())
_LOGGER.debug(f"Certifi CA bundle path: {certifi_bundle_path}")

certifi_backup_path = certifi_bundle_path.with_suffix(
certifi_bundle_path.suffix + ".bak"
)

rapidssl_ca_path = Path(__file__).with_name("RapidSSL_TLS_RSA_CA_G1.crt")

if certifi_backup_path.exists():
# reset Certifi bundle
await hass.async_add_executor_job(
shutil.copyfile, certifi_backup_path, certifi_bundle_path
)
else:
# backup Certifi bundle
await hass.async_add_executor_job(
shutil.copyfile, certifi_bundle_path, certifi_backup_path
)

_LOGGER.info("Certifi bundle CA ready.")

cacerts, rapidssl_ca = await asyncio.gather(
*(
hass.async_add_executor_job(path.read_text)
for path in (certifi_bundle_path, rapidssl_ca_path)
)
)

if rapidssl_ca not in cacerts:
cert_name = rapidssl_ca_path.stem.replace("_", " ")
cacerts += f"\n# Haier hOn: {cert_name}\n"
cacerts += rapidssl_ca
await hass.async_add_executor_job(certifi_bundle_path.write_text, cacerts)

_LOGGER.info(
f"{cert_name} -> loaded into Certifi CA bundle. Restart Home Assistant to apply changes."
)

return True