Closed hmoffatt closed 4 years ago
Huh; that's very interesting! It does seem like a good idea to give an informative error message, but there is some more detective work to do here. Any idea why this leads to an SSL error? Does the client get redirected to a bogus host when the language is wrong, and that host has a bad SSL configuration?
If we can figure out what exactly is going on, then we could perhaps distinguish this error earlier and tell it apart from other certificate errors.
I turned on logging in urllib3 and here's what I got.
Firstly with the wrong language code:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): kic.lgthinq.com:46030
DEBUG:urllib3.connectionpool:https://kic.lgthinq.com:46030 "POST /api/common/gatewayUriList HTTP/1.1" 200 1255
Log in here:
https://us.m.lgaccount.com/login/sign_in?country=AU&language=en-US&svcCode=SVC202&authSvr=oauth2&client_id=LGAO221A02&division=ha&grant_type=password
Then paste the URL where the browser is redirected:
https://us.m.lgaccount.com/login/iabClose?access_token=<>&refresh_token=<>&oauth2_backend_url=https://kr.lgeapi.com/
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): aic.lgthinq.com:46030
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/contrib/pyopenssl.py", line 453, in wrap_socket
cnx.do_handshake()
File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1915, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1647, in _raise_ssl_error
_raise_current_error()
File "/usr/lib/python3/dist-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl_choose_client_version', 'unsupported protocol')]
then with the correct country code:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): kic.lgthinq.com:46030
DEBUG:urllib3.connectionpool:https://kic.lgthinq.com:46030 "POST /api/common/gatewayUriList HTTP/1.1" 200 1232
Log in here:
https://au.m.lgaccount.com/login/sign_in?country=AU&language=en-AU&svcCode=SVC202&authSvr=oauth2&client_id=LGAO221A02&division=ha&grant_type=password
Then paste the URL where the browser is redirected:
https://us.m.lgaccount.com/login/iabClose?access_token=<>&refresh_token=<>&oauth2_backend_url=https://kr.lgeapi.com/
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): kic.lgthinq.com:46030
DEBUG:urllib3.connectionpool:https://kic.lgthinq.com:46030 "POST /api/member/login HTTP/1.1" 200 2142
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): kic.lgthinq.com:46030
DEBUG:urllib3.connectionpool:https://kic.lgthinq.com:46030 "POST /api/device/deviceList HTTP/1.1" 200 1838
88ce8430-111a-11e8-b9bb-044eaf87a0e4: Dishwasher (DISHWASHER D2201)
However I think I'm missing something because I don't see how it decided on a different URL, when the login link was the same (literally, I just pasted it in again, didn't login again).
Hmm; Indeed—it looks like the wrong language code led to a connection to aic.lgthinq.com:46030
, whereas the right one led to contacting kic.lgthinq.com:46030
.
The underlying reason is that the LG API uses this funky gateway system where you have to ask a central service which server to connect to. You give it a country and a language code and it tells you where to log in. I wrote a function called gateway_info
in wideq.core
that wraps this lookup. You can see how the service responds for various combinations of codes:
>>> import wideq
>>> wideq.core.gateway_info('AU', 'en-US')['thinqUri']
'https://aic.lgthinq.com:46030/api'
>>> wideq.core.gateway_info('AU', 'en-AU')['thinqUri']
'https://kic.lgthinq.com:46030/api'
>>> wideq.core.gateway_info('US', 'en-US')['thinqUri']
'https://aic.lgthinq.com:46030/api'
>>> wideq.core.gateway_info('US', 'en-AU')['thinqUri']
'https://aic.lgthinq.com:46030/api'
So I guess aic
might be the US service, and specifying en-US
erroneously directs you there? Still not sure why that eventually turns into an SSL error, though.
I can't connect to the aic.lgthinq.com:46030 URL at all from Python. gnutls-cli connects OK, but reports it is using TLS 1.0. When I connect to the kic.lgthinq.com:46030 URL I get TLS 1.2.
I'm using Python on Debian buster. If I try it it from python-requests on Debian stretch, it works. I think Python or OpenSSL must be enforcing a minimum TLS version > 1.0 which is causing this failure.
$ python3
Python 3.7.3 (default, Apr 3 2019, 05:39:12)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get('https://aic.lgthinq.com:46030')
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/urllib3/contrib/pyopenssl.py", line 453, in wrap_socket
cnx.do_handshake()
File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1915, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1647, in _raise_ssl_error
_raise_current_error()
File "/usr/lib/python3/dist-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue
raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl_choose_client_version', 'unsupported protocol')]
It looks like this might be a Debian-specific change to disallow the old TLS versions by default. You might be able to re-enable them. Here's some links I found.
https://bugs.python.org/issue31453 https://stackoverflow.com/questions/50707974/force-tls-1-0-connection-with-requests?noredirect=1&lq=1
So it looks like it's nothing to do with the wrong language, just luck for me that en-AU is on a TLSv1.2-capable server and en-US is not.
Easy fix to that on debian (work on Ubuntu too, perhaps on all other linux distro). sudo nano /etc/ssl/openssl.cnf Search and replace : MinProtocol = TLSv1.X by MinProtocol = TLSv1.0
Restart your server, follow the process to install wideq, everything will work fine.
You don't need to restart, that file will be read by each program that uses OpenSSL when it starts.
I was hoping there would be a way to override this from Python so that it could be added to this library rather than the users having to reconfigure their systems. But really it must be fixed by LG.
I think this issue can be closed.
Sent from Nine
From: Cortex33 notifications@github.com Sent: Sunday, 1 December 2019 16:41 To: sampsyo/wideq Cc: Hamish Moffatt; Author Subject: Re: [sampsyo/wideq] wrong language code led to SSL error (#55)
Easy fix to that on debian (work on Ubuntu too, perhaps on all other linux distro). sudo nano /etc/ssl/openssl.cnf Search and replace : MinProtocol = TLSv1.X by MinProtocol = TLSv1.0
Restart your server, follow the process to install wideq, everything will work fine.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.
I'm in Australia and my LG account is set to Australia.
I was trying to login with country set to AU, but no language specified. I got a token from LG successfully, but then an SSL protocol error when it tried to access the API.
Eventually I tried adding the country code en-AU, didn't even login again but used the same token URL, and then it worked. Is it possible to handle this condition better than pages of SSL errors?