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

TLS v1 Fix in v 6.3 causing issues - rollback to 6.2 fixes issue #114

Open
ColinSainsbury opened this issue Oct 16, 2024 · 18 comments
Open
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@ColinSainsbury
Copy link

v 6.3 update causes HTTPS errors

Logger: custom_components.climate_ip
Source: custom_components/climate_ip/connection_request.py:163
integration: climate_ip (documentation, issues)
First occurred: 13:55:46 (653 occurrences)
Last logged: 15:17:04

Request result exception: HTTPSConnectionPool(host='api.smartthings.com', port=443): Max retries exceeded with url: /v1/devices/XXXXXXXXXXXXXXXXXXXXXX/status/ (Caused by SSLError(SSLError(1, '[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:1000)')))

I have obscured my device ID . This was working fine before the update to 6.3 and rolling back to 6.2 fixes the issue.

@samuelecarpene
Copy link

Hi @ColinSainsbury I wrote the patch for tls v1 so I can help you and you can help me solve the problem.
The main problem is that no one person has all the devices so it is difficult to understand every single case. The problem is definitely here but it can be easily solved by removing the "if" (line 140 and 141). However if you could enable debug and copy paste the logs (line 136 and 143 ) it would be very helpful. The if is based on the only thing i found to try to understand when using tls 1 or not (i based the code on the certificate presence or not). If you can describe how you configured your devices and what types are helpful in understanding how to solve the problem for all users/cases. Yesterday i spent some hours to develop a better way but with no result. I need to understand better how components work.

@ColinSainsbury
Copy link
Author

@samuelecarpene thanks for coming back to me. My configuration is that I have an EHS Mono Quiet AE120BXYDEG/EU ASHP connected via the MIM-H04EN. I will run the test scenarios you suggest and report back.

@ColinSainsbury
Copy link
Author

Hopefully these logs will help. I have a secondary connection to the REST API running through a Climate Template https://github.com/jcwillox/hass-template-climate which I discovered before the MIM-H04EN connectivity was added to this integration.
home-assistant_climate_ip_2024-10-17T04-44-40.180Z.log
This continues to work as expected.

@samuelecarpene
Copy link

I think I understand the problem.
There are a couple of things that i try to explain and if you can you can test:

  • it seems that there is a default certificate value (that i think is better to set to empty string because for example for calls to api.smartthings.com is not needed). First test is to empty the default value of cetificate here (replce DEFAULT_CONF_CERT_FILE = "ac14k_m.pem" with DEFAULT_CONF_CERT_FILE = "". This first text i think is the right fix.
  • another improvements could be to check if the url is api.smartthings.com and in the case use tls auto modify this if replacing
                if 'cert' in self._params :
                    tls_version = '1'

with

                if not self._params.url.startwith('https://api.smartthings.com')
                    if 'cert' in self._params :
                        tls_version = '1'

Pay attention to correct indentation.

I can't test this code right now because I'm having router issues.

Can you try these 2 things and let me know the result? If there are errors the logs are helpful. Thanks.

@ColinSainsbury
Copy link
Author

The bad news is that neither worked. I tried them independently. Removing reference to the certificate PEM file appeared to have no obvious effect. The code change above caused the integration not to start. I have attempted to capture logs.

Logger: homeassistant.util.loop
Source: util/loop.py:136
First occurred: 13:56:10 (2 occurrences)
Last logged: 13:56:12

Detected blocking call to load_default_certs with args (<ssl.SSLContext object at 0x7fb2267f4050>, <Purpose.SERVER_AUTH: _ASN1Object(nid=129, shortname='serverAuth', longname='TLS Web Server Authentication', oid='1.3.6.1.5.5.7.3.1')>) inside the event loop by custom integration 'climate_ip' at custom_components/climate_ip/connection_request.py, line 29: ssl_context = ssl.create_default_context() (offender: /usr/local/lib/python3.12/ssl.py, line 713: context.load_default_certs(purpose)), please create a bug report at https://github.com/atxbyea/samsungrac/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#load_default_certs Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/main.py", line 223, in sys.exit(main()) File "/usr/src/homeassistant/homeassistant/main.py", line 209, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 189, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete self.run_forever() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 641, in run_forever self._run_once() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1990, in _run_once handle._run() File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run self._context.run(self._callback, *self._args) File "/config/custom_components/climate_ip/climate.py", line 125, in async_setup_platform device_controller = await create_controller( File "/config/custom_components/climate_ip/controller.py", line 71, in create_controller if await c.initialize(): File "/config/custom_components/climate_ip/controller_yaml.py", line 177, in initialize self.update_state() File "/config/custom_components/climate_ip/controller_yaml.py", line 229, in update_state self._state_getter.update_state(self._state_getter.value, debug) File "/config/custom_components/climate_ip/properties.py", line 254, in update_state device_state = self.get_connection(None).execute( File "/config/custom_components/climate_ip/connection_request.py", line 180, in execute j, ok, code = self.execute_internal(template, value, device_state) File "/config/custom_components/climate_ip/connection_request.py", line 123, in execute_internal session.mount("https://", SamsungHTTPAdapter()) File "/config/custom_components/climate_ip/connection_request.py", line 26, in init super().init(*args, **kwargs) File "/usr/local/lib/python3.12/site-packages/requests/adapters.py", line 222, in init self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) File "/config/custom_components/climate_ip/connection_request.py", line 29, in init_poolmanager ssl_context = ssl.create_default_context()
Detected blocking call to load_default_certs with args (<ssl.SSLContext object at 0x7fb21fe287d0>,) inside the event loop by custom integration 'meross_cloud' at custom_components/meross_cloud/init.py, line 189: await self._manager.async_device_discovery() (offender: /usr/local/lib/python3.12/site-packages/paho/mqtt/client.py, line 806: context.load_default_certs()), please create a bug report at https://github.com/albertogeniola/meross-homeassistant For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#load_default_certs Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/main.py", line 223, in sys.exit(main()) File "/usr/src/homeassistant/homeassistant/main.py", line 209, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 189, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.12/asyncio/base_events.py", line 674, in run_until_complete self.run_forever() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 641, in run_forever self._run_once() File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1990, in _run_once handle._run() File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run self._context.run(self._callback, *self._args) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 742, in async_setup_locked await self.async_setup(hass, integration=integration) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 594, in async_setup result = await component.async_setup_entry(hass, self) File "/config/custom_components/meross_cloud/init.py", line 419, in async_setup_entry await meross_coordinator.initial_setup() File "/config/custom_components/meross_cloud/init.py", line 189, in initial_setup await self._manager.async_device_discovery()

@atxbyea atxbyea added bug Something isn't working help wanted Extra attention is needed labels Oct 21, 2024
@samuelecarpene
Copy link

samuelecarpene commented Oct 21, 2024

@ColinSainsbury i noticed that there are other pieces of code related to cert configuration.

Here the first one
https://github.com/atxbyea/samsungrac/blob/master/custom_components/climate_ip/connection_request.py#L72
where the check is with None.

So, try to set None to default here instead of string empty.
I think this can solve the problem.
If the value is ""(empty string) i think it pass the if
See here.
image

I don't know if this can be a problem.
Maybe try to indent this line
nested into this if if cert_file is not None:. Because it seems wrong

Give it a try.

PS: For the second test I posted in the previous comment i saw that i made 1 or more mistakes.
First one i forgot two points for if condition

                if not self._params.url.startwith('https://api.smartthings.com') :
                    if 'cert' in self._params :
                        tls_version = '1'

But i'm not very familiar with python so try this that i think it works.

                if not 'https://api.smartthings.com' in self._params.url :
                    if 'cert' in self._params :
                        tls_version = '1'

I will try to debug my installation in the next few days.

Let me know.

@ColinSainsbury
Copy link
Author

@samuelecarpene I made all the changes you suggested above except the indent you suggested for line 76 in connection_request.py but the integration failed to start. I was uncertain about the change you were looking for to the indentation so left it alone.

Here are the error messages from the log:
2024-10-21 09:18:22.142 ERROR (MainThread) [homeassistant.config] Invalid config for 'climate' from integration 'climate_ip' at climate.yaml, line 121: string value is None for dictionary value 'cert', got None, please check the docs at https://github.com/atxbyea/samsungrac
2024-10-21 09:18:22.142 ERROR (MainThread) [homeassistant.config] Invalid config for 'climate' from integration 'climate_ip' at climate.yaml, line 130: string value is None for dictionary value 'cert', got None, please check the docs at https://github.com/atxbyea/samsungrac

@samuelecarpene
Copy link

try using string.
so let default to empty string and try to change these 2 rows

            cert_file = hass_config.get(CONF_CERT, "")
            if cert_file != "" and cert_file is not None:

please try these things separately so we can understand where is the problem.

@ColinSainsbury
Copy link
Author

OK - I reverted to the original 6.3 download
I modified with your last suggestion (no other changes) and rebooted HA.

Error message:
Logger: custom_components.climate_ip
Source: custom_components/climate_ip/connection_request.py:163
integration: Climate IP (documentation, issues)
First occurred: 10:11:33 (8 occurrences)
Last logged: 10:12:08

Request result exception: HTTPSConnectionPool(host='api.smartthings.com', port=443): Max retries exceeded with url: /v1/devices/MY_DEVICE_ID/status/ (Caused by SSLError(SSLError(1, '[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:1000)')))

@samuelecarpene
Copy link

I will try to investigate and study the problem. The fact is that there seems to be 2 scenarios:

  • devices accessed on local network (requiring tls v1);
  • api calls made to smarthings api requiring an updated tls version;
    The problem is to implement how to decide which tls version to use based on the type/configuration of the device.
    The easiest way can be to create 2 packages (but I think it is absurd to have to do such a thing).

@samuelecarpene
Copy link

I noticed that for 2878 devices there is a specific connection parameter
https://github.com/atxbyea/samsungrac/blob/6.3/custom_components/climate_ip/samsung_2878.yaml#L6
that make the component use a specific class connection

class ConnectionSamsung2878(Connection):

So, for MIM-H04EN i think there can be a similar solution.
Basically, to create a specific connection that these devices can use.
I will try to write the connection and let you know.
Maybe @MichaelMraka that made this pull request #97 can help us.

@samuelecarpene
Copy link

@ColinSainsbury try this samuelecarpene@d8554f7 and let me know.
As i said i copied connection request to make a specific one for device that require tls_auto.

@ColinSainsbury
Copy link
Author

@samuelecarpene Thank you so much for your efforts here. The integration failed to start. The log output is below:

Logger: homeassistant.components.climate
Source: helpers/entity_platform.py:361
integration: Climate (documentation, issues)
First occurred: 06:01:27 (2 occurrences)
Last logged: 06:01:28

Error while setting up climate_ip platform for climate
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 361, in _async_setup_platform
await asyncio.shield(awaitable)
File "/config/custom_components/climate_ip/climate.py", line 126, in async_setup_platform
device_controller = await create_controller(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/climate_ip/controller.py", line 71, in create_controller
if await c.initialize():
^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/climate_ip/controller_yaml.py", line 141, in initialize
connection = create_connection(connection_node, self._config, self._logger)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/climate_ip/connection.py", line 44, in create_connection
c = conn(config, logger)
^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 161, in init
super(ConnectionRequest, self).init(hass_config, logger)
^^^^^^^^^^^^^^^^^
NameError: name 'ConnectionRequest' is not defined. Did you mean: 'ConnectionRequestBase'?

This error originated from a custom integration.

Logger: custom_components.climate_ip
Source: custom_components/climate_ip/climate.py:133
integration: climate_ip (documentation, issues)
First occurred: 06:01:27 (2 occurrences)
Last logged: 06:01:28

Traceback (most recent call last): File "/config/custom_components/climate_ip/climate.py", line 126, in async_setup_platform device_controller = await create_controller( ^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/climate_ip/controller.py", line 71, in create_controller if await c.initialize(): ^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/climate_ip/controller_yaml.py", line 141, in initialize connection = create_connection(connection_node, self._config, self._logger) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/climate_ip/connection.py", line 44, in create_connection c = conn(config, logger) ^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 161, in init super(ConnectionRequest, self).init(hass_config, logger) ^^^^^^^^^^^^^^^^^ NameError: name 'ConnectionRequest' is not defined. Did you mean: 'ConnectionRequestBase'?

@samuelecarpene
Copy link

Maybe these modifications fix the problem.
samuelecarpene@75fefb4
Let me know.

@ColinSainsbury
Copy link
Author

@samuelecarpene That works for me - you are an absolute star - thank you so much. I will leave the issue open for a couple of days in case others have issues and then close. I will put a beer in an email for you.

@samuelecarpene
Copy link

Don't close the issue, I will make a pull request for this issue. Then when the pull request is accepted the issue will be closed. Thank you for the beer!

@samuelecarpene samuelecarpene mentioned this issue Nov 27, 2024
@flavioxavier
Copy link

flavioxavier commented Dec 23, 2024

I'm having the same or similar issue also with I think the same samsung hardware and running HAOS

Registo: homeassistant.util.loop
Origem: util/loop.py:136
Primeira ocorrência: 03:16:19 (2 ocorrências)
Último registo: 03:16:21

Detected blocking call to load_default_certs with args (<ssl.SSLContext object at 0x7f86d86180>, <Purpose.SERVER_AUTH: _ASN1Object(nid=129, shortname='serverAuth', longname='TLS Web Server Authentication', oid='1.3.6.1.5.5.7.3.1')>) inside the event loop by custom integration 'climate_ip' at custom_components/climate_ip/connection_request_tls_auto.py, line 30: ssl_context = ssl.create_default_context() (offender: /usr/local/lib/python3.13/ssl.py, line 722: context.load_default_certs(purpose)), please create a bug report at https://github.com/atxbyea/samsungrac/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#load_default_certs Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/__main__.py", line 227, in <module> sys.exit(main()) File "/usr/src/homeassistant/homeassistant/__main__.py", line 213, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 154, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.13/asyncio/base_events.py", line 708, in run_until_complete self.run_forever() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 679, in run_forever self._run_once() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 2027, in _run_once handle._run() File "/usr/local/lib/python3.13/asyncio/events.py", line 89, in _run self._context.run(self._callback, *self._args) File "/config/custom_components/climate_ip/climate.py", line 126, in async_setup_platform device_controller = await create_controller( File "/config/custom_components/climate_ip/controller.py", line 71, in create_controller if await c.initialize(): File "/config/custom_components/climate_ip/controller_yaml.py", line 177, in initialize self.update_state() File "/config/custom_components/climate_ip/controller_yaml.py", line 229, in update_state self._state_getter.update_state(self._state_getter.value, debug) File "/config/custom_components/climate_ip/properties.py", line 254, in update_state device_state = self.get_connection(None).execute( File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 185, in execute j, ok, code = self.execute_internal(template, value, device_state) File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 127, in execute_internal session.mount("https://", SamsungHTTPAdapter()) File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 27, in __init__ super().__init__(*args, **kwargs) File "/usr/local/lib/python3.13/site-packages/requests/adapters.py", line 222, in __init__ self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) File "/config/custom_components/climate_ip/connection_request_tls_auto.py", line 30, in init_poolmanager ssl_context = ssl.create_default_context()
Detected blocking call to import_module with args ('.climate', 'custom_components.smartthings_custom') inside the event loop by custom integration 'smartthings_custom' at custom_components/smartthings_custom/__init__.py, line 307: platform_module = importlib.import_module( (offender: /config/custom_components/smartthings_custom/__init__.py, line 307: platform_module = importlib.import_module(), please report it to the author of the 'smartthings_custom' custom integration For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#import_module Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/__main__.py", line 227, in <module> sys.exit(main()) File "/usr/src/homeassistant/homeassistant/__main__.py", line 213, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 154, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.13/asyncio/base_events.py", line 708, in run_until_complete self.run_forever() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 679, in run_forever self._run_once() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 2027, in _run_once handle._run() File "/usr/local/lib/python3.13/asyncio/events.py", line 89, in _run self._context.run(self._callback, *self._args) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 788, in async_setup_locked await self.async_setup(hass, integration=integration) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 551, in async_setup await self.__async_setup_with_context(hass, integration) File "/usr/src/homeassistant/homeassistant/config_entries.py", line 640, in __async_setup_with_context result = await component.async_setup_entry(hass, self) File "/config/custom_components/smartthings_custom/__init__.py", line 166, in async_setup_entry broker = DeviceBroker(hass, entry, token, smart_app, devices, scenes) File "/config/custom_components/smartthings_custom/__init__.py", line 296, in __init__ self._assignments = self._assign_capabilities(devices) File "/config/custom_components/smartthings_custom/__init__.py", line 307, in _assign_capabilities platform_module = importlib.import_module(

But it's strange because @samuelecarpene fix seems to be in the latest code and I've checked the file in my installation.

My configuration:

climate:
  # hot water controller
  - platform: climate_ip
    name: Samsung EHS DHW
    config_file: /config/custom_components/climate_ip/samsung_smartthings_dhw.yaml
    ip_address: api.smartthings.com
    device_id: edited
    token: !secret smartthings_token
  # heating controller
  - platform: climate_ip
    name: Samsung EHS Heating
    config_file: /config/custom_components/climate_ip/samsung_smartthings_hvac.yaml
    ip_address: api.smartthings.com
    device_id: edited
    token: !secret smartthings_token

@flavioxavier
Copy link

Just a bump since my last comment was during the holidays

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants