wpietri / sucks

Simple command-line script for the Ecovacs series of robot vacuums
GNU General Public License v3.0
281 stars 104 forks source link

Certificate expired error when trying to clean #62

Open snipem opened 5 years ago

snipem commented 5 years ago

Version of sucks built directly from master branch:

~/work/sucks  $ pip show sucks                                                                                                                                
Name: sucks                                                                                                                                                   
Version: 0.9.3                                                                                                                                                
Summary: a library for controlling certain robot vacuums                                                                                                      
Home-page: https://github.com/wpietri/sucks                                                                                                                   
Author: William Pietri                                                                                                                                        
Author-email: sucks-users@googlegroups.com                                                                                                                    
License: GPL-3.0
Location: /home/user/.local/lib/python3.6/site-packages

Config:

~/work/sucks  $ cat ~/.config/sucks.conf                                                                                                                     
email=***
password_hash=***
device_id=***
country=de
continent=eu

Error messages?

~/work/sucks  $ sucks clean 1                                                                                                                                
sleekxmpp.basexmpp WARNING  fulljid property deprecated. Use boundjid.resource
sleekxmpp.xmlstream.xmlstream ERROR    Certificate has expired.
sleekxmpp.xmlstream.xmlstream WARNING  Failed to send b"<stream:stream to='ecouser.net' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'
xml:lang='en' version='1.0'>"
sleekxmpp.xmlstream.xmlstream ERROR    Socket Error #9: Bad file descriptor
sleekxmpp.xmlstream.xmlstream ERROR    Certificate has expired.
sleekxmpp.xmlstream.xmlstream WARNING  Failed to send b"<stream:stream to='ecouser.net' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'
xml:lang='en' version='1.0'>"
sleekxmpp.xmlstream.xmlstream ERROR    Socket Error #9: Bad file descriptor
sleekxmpp.xmlstream.xmlstream ERROR    Certificate has expired.
sleekxmpp.xmlstream.xmlstream WARNING  Failed to send b"<stream:stream to='ecouser.net' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'
xml:lang='en' version='1.0'>"
sleekxmpp.xmlstream.xmlstream ERROR    Socket Error #9: Bad file descriptor
^C
Aborted!
^CException ignored in: <module 'threading' from '/usr/lib64/python3.6/threading.py'>                                                                        
Traceback (most recent call last):
  File "/usr/lib64/python3.6/threading.py", line 1294, in _shutdown
    t.join()
  File "/usr/lib64/python3.6/threading.py", line 1056, in join
    self._wait_for_tstate_lock()
  File "/usr/lib64/python3.6/threading.py", line 1072, in _wait_for_tstate_lock                                                                              
    elif lock.acquire(block, timeout):
KeyboardInterrupt

Is this a known problem? Is it restricted to just the European or German endpoint? Is there a workaround?

wpietri commented 5 years ago

Can you tell what host is involved? I think the first thing to do is to try to connect to the host in question with some other tool and see if the certificate really is expired.

snipem commented 5 years ago

Thanks for the response.

I did this by editing sleekxmp to also output the URL in question:

    if not_after <= now:
        raise CertificateError(
                'Certificate for %s has expired.' % (expected))

in file sleekxmpp/xmlstream/cert.py.

Here's the output:

$ sucks clean 1                                                                                              
sleekxmpp.basexmpp WARNING  fulljid property deprecated. Use boundjid.resource
sleekxmpp.xmlstream.xmlstream ERROR    Certificate for ecouser.net has expired.
sleekxmpp.xmlstream.xmlstream WARNING  Failed to send b"<stream:stream to='ecouser.net' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' xml:lang='en' version='1.0'>"
sleekxmpp.xmlstream.xmlstream ERROR    Socket Error #9: Bad file descriptor
sleekxmpp.xmlstream.xmlstream ERROR    Certificate for ecouser.net has expired.
sleekxmpp.xmlstream.xmlstream WARNING  Failed to send b"<stream:stream to='ecouser.net' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' xml:lang='en' version='1.0'>"
sleekxmpp.xmlstream.xmlstream ERROR    Socket Error #9: Bad file descriptor
^C
Aborted!
^CException ignored in: <module 'threading' from '/usr/lib64/python3.6/threading.py'>
Traceback (most recent call last):
  File "/usr/lib64/python3.6/threading.py", line 1294, in _shutdown
    t.join()
  File "/usr/lib64/python3.6/threading.py", line 1056, in join
    self._wait_for_tstate_lock()
  File "/usr/lib64/python3.6/threading.py", line 1072, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

So the url in question is ecouser.net. Unfortunately I can't tell if and which subdomain is used.

I tried numerous calls like curl https://msg-eu.ecouser.netall returned a valid certificate. But is the https certificate the one that is called? I would assume that the certificate error is deep down in the xmpp protocol.

wpietri commented 5 years ago

One way you could narrow it down would be to use Wireshark to capture traffic from your machine. That would let you see what's happening when; I think the certificate will be sent in the clear.

ecpunk commented 5 years ago

Same for me. I'm in the US, connecting to the US server. The cert was signed in Nov xx 2017 and expired Jan 20 2019. I actually just modified the python to print the start/end dates of the cert. I've just been working on this, so I'm not sure who the certificate issuer is yet. I am set up to capture, so please let me know if there is anything I can provide to help out. I'll keep working on it.

snipem commented 5 years ago

So it's up to Ecovacs to renew the certificate. For sucks as a 3rd party library the only option to get around this, is to not validate the certificate on connection. This would lower the security, but make the library work again.

ecpunk commented 5 years ago

Ok, looks like the bad cert is on pyasn1. Currently testing with pyasn1 0.4.5. I'll try something else after breakfast, but here is the output from the debug which is just a local cert validation, and below that is the TLS server response from ecovacs.

validity=Validity: notBefore=Time: utcTime=171123000000Z

notAfter=Time: utcTime=190122235959Z

2b487757-2e5b-4887-8e55-c4bf28c34aff
wpietri commented 5 years ago

Ah, that explains why I'm not having the problem. A warning I get when I run sucks:

sleekxmpp.xmlstream.cert WARNING  Could not find pyasn1 and pyasn1_modules. SSL certificate COULD NOT BE VERIFIED.

So a temporary workaround is perhaps to uninstall that module.

If we're sure this is a problem with the Ecovacs certificate, I can try reporting this to them as a problem.

ecpunk commented 5 years ago

It is definitely the sleekxmpp cert that is expired, so removing pyasn1 & _modules to not verify is the way to go as a workaround. I think you can close this most likely.

sleekxmpp.xmlstream.cert WARNING Could not find pyasn1 and pyasn1_modules. SSL certificate COULD NOT BE VERIFIED. sleekxmpp.xmlstream.cert WARNING Could not find pyasn1 and pyasn1_modules. SSL certificate expiration COULD NOT BE VERIFIED.

Here is my vanilla Python 3.7 install with sucks for reference:

image

wpietri commented 5 years ago

Thanks, @ecpunk. When you say it's the sleekxmpp certificate, you mean that it's not an Ecovacs certificate, but rather something in the sleekxmpp library?

snipem commented 5 years ago

This is surprising I first saw this error with this golang library https://github.com/skburgart/go-vacbot that is basically a port of sucks. Since sucks had the same issue, I thought this was related to the backend.

~  $ cleanhome 10
2019/01/28 16:17:49 login successful
2019/01/28 16:17:49 get auth code successful
2019/01/28 16:17:53 get user access token successful
2019/01/28 16:17:54 starttls handshake: x509: certificate has expired or is not yet valid

So taking this into account I would say that it's not relate to python or sucks. Do we have clear evidence on that matter?