Message399231
Hello everyone, and thank you as usual for all your hard work keeping the python ecosystem going.
I saw that the start of this thread said it was going to
> - make ftplib, imaplib, nntplib, pop3lib, smtplib etc. validate certs by default.
but this hasn't been done, at least not for imaplib. imaplib is still calling the undocumented "ssl._create_stdlib_context":
https://github.com/python/cpython/blob/2b496e79293a8b80e8ba0e514e186b3b1467b64b/Lib/imaplib.py#L1320
which is actually "ssl._create_unverified_context":
https://github.com/python/cpython/blob/2b496e79293a8b80e8ba0e514e186b3b1467b64b/Lib/ssl.py#L842
which is indeed unverified: despite defaulting to PROTOCOL_TLS_CLIENT, which "enables CERT_REQUIRED and check_hostname by default.", it overrides that by setting check_hostname=False:
https://github.com/python/cpython/blob/2b496e79293a8b80e8ba0e514e186b3b1467b64b/Lib/ssl.py#L811
To demonstrate, check out this tester script:
$ cat a.py
import os, imaplib
with imaplib.IMAP4_SSL(os.environ.get('HOSTNAME')) as S:
print(S.login(os.environ.get('USERNAME'), os.environ.get('PASSWORD')))
$ HOSTNAME=46.23.90.174 USERNAME=test1 PASSWORD=test1test1 python3 a.py
('OK', [b'Logged in'])
I don't have a cert for 46.23.90.174 (no one will give out certs for IPs!), so this is wrong!
In order to actually enable verification you need to know the incantation. It's not that long but it is subtle and frighteningly easy to get wrong. Here it is:
$ cat a.py
import os, ssl, imaplib
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.load_default_certs()
with imaplib.IMAP4_SSL(os.environ.get('HOSTNAME'), ssl_context=ctx) as S:
print(S.login(os.environ.get('USERNAME'), os.environ.get('PASSWORD')))
$ HOSTNAME=46.23.90.174 USERNAME=test1 PASSWORD=test1test1 python3 a.py
Traceback (most recent call last):
File "a.py", line 6, in <module>
with imaplib.IMAP4_SSL(os.environ.get('HOSTNAME'), ssl_context=ctx) as S:
File "/usr/lib/python3.6/imaplib.py", line 1288, in __init__
IMAP4.__init__(self, host, port)
File "/usr/lib/python3.6/imaplib.py", line 198, in __init__
self.open(host, port)
File "/usr/lib/python3.6/imaplib.py", line 1301, in open
IMAP4.open(self, host, port)
File "/usr/lib/python3.6/imaplib.py", line 299, in open
self.sock = self._create_socket()
File "/usr/lib/python3.6/imaplib.py", line 1293, in _create_socket
server_hostname=self.host)
File "/usr/lib/python3.6/ssl.py", line 407, in wrap_socket
_context=self, _session=session)
File "/usr/lib/python3.6/ssl.py", line 817, in __init__
self.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 694, in do_handshake
match_hostname(self.getpeercert(), self.server_hostname)
File "/usr/lib/python3.6/ssl.py", line 327, in match_hostname
% (hostname, ', '.join(map(repr, dnsnames))))
ssl.CertificateError: hostname '46.23.90.174' doesn't match either of 'comms.kousu.ca', 'comms3.kousu.ca'
I can see from this thread there were some concerns about breaking people's self-signed certs back in 2016. But it's five years later now and letsencrypt is super common now, and most servers and clients are enforcing TLS, especially when credentials are involved.
Could this be revisited?
Thanks for any attention you have gifted to this :) |
|
Date |
User |
Action |
Args |
2021-08-08 18:58:29 | kousu | set | recipients:
+ kousu, ncoghlan, janssen, orsenthil, vstinner, giampaolo.rodola, christian.heimes, alex, python-dev, martin.panter, serhiy.storchaka, dstufft, Lukasa |
2021-08-08 18:58:29 | kousu | set | messageid: <1628449109.02.0.753390831824.issue28022@roundup.psfhosted.org> |
2021-08-08 18:58:29 | kousu | link | issue28022 messages |
2021-08-08 18:58:28 | kousu | create | |
|