Browse Source

interface: nicer error for CA-signed "Hostname mismatch" certs

Previously when encountering a CA-signed cert that failed verification with "Hostname mismatch",
we would
1. erroneously mark it as self-signed
2. save its cert to pin it
3. when connecting to it later, and being served a CA-signed cert, we would reject the connection
  - I think this is because we use the saved cert (the peer cert, just the last cert in the chain) as if it was a root CA,
    and then during the connection we try to verify against that root. This fails as we are served a different root then.
Error logged in step(3):
```
  3.85 | W | i/interface.[wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion:50002] | Cannot connect to main server due to SSL error (maybe cert changed compared to "/home/user/.electrum/testnet/certs/wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion"). Exc: ConnectError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)'))
```

This commit fixes step(1), we won't mark the cert as self-signed, instead the error is propagated out and the connection closed.
```
 35.05 | I | i/interface.[wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion:50002] | disconnecting due to: ErrorGettingSSLCertFromServer(ConnectError(SSLCertVerificationError(1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion'. (_ssl.c:1007)")))
```

Compare:
- SSLCertVerificationError(1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'wirg2tsto7rme7n26lkd3ivbvxmjyy2pktlozwjuep22jcsfsghfqbqd.onion'. (_ssl.c:1007)")
  - verify_code=62
- SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1007)')
  - verify_code=18

Note: the verify_code constants look stable, though they might be openssl-specific. I guess that's ok(?)
140540189c/include/openssl/x509_vfy.h.in (L224)
master
SomberNight 2 years ago
parent
commit
02a9ab80be
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 8
      electrum/interface.py

8
electrum/interface.py

@ -443,10 +443,14 @@ class Interface(Logger):
await self.open_session(ca_ssl_context, exit_early=True)
except ConnectError as e:
cause = e.__cause__
if isinstance(cause, ssl.SSLError) and cause.reason == 'CERTIFICATE_VERIFY_FAILED':
# failures due to self-signed certs are normal
if (isinstance(cause, ssl.SSLCertVerificationError)
and cause.reason == 'CERTIFICATE_VERIFY_FAILED'
and cause.verify_code == 18): # "self signed certificate"
# Good. We will use this server as self-signed.
return False
# Not good. Cannot use this server.
raise
# Good. We will use this server as CA-signed.
return True
async def _try_saving_ssl_cert_for_first_time(self, ca_ssl_context):

Loading…
Cancel
Save