Re: Bug with imap.gmail.com and getmail TLS validation
Daniel Kahn Gillmor <[email protected]>
| Newsgroups | gmane.mail.getmail.user |
|---|---|
| Message-ID | <[email protected]> |
On Mon 2019-02-11 09:47:09 -0600, Charles Cazabon wrote: > Daniel Kahn Gillmor <[email protected]> wrote: >> On Thu 2019-02-07 16:09:37 -0600, Charles Cazabon wrote: >> > I was able to hack in something to cause the SNI field to be sent with the >> > request to verify the problem, >> >> Could you publish this particular hack so that other people can try it out? > > It's in the test script I posted elsewhere in this thread. Thanks. I've just crafted the following (lightly-tested) patch, which enables SNI by default if the local copy of python's ssl module supports it, and adds a use_sni boolean config variable which defaults to True. Please let me know if you think it's missing anything. I'm considering applying it to Debian before we run into more gmail users having problems on that platform. --dkg
0001-Send-SNI-on-IMAP-and-POP-connections-by-default.patch
(text/x-diff, 12.3 KB)
From bb1d505140a626f5acc4feb9fdf64c404294f722 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <[email protected]> Date: Mon, 11 Feb 2019 14:36:13 -0500 Subject: [PATCH] Send SNI on IMAP and POP connections by default. This introduces a new "use_sni" configuration option that users can disable if they need to, but modern TLS connections should probably be sending SNI. --- docs/configuration.html | 37 ++++++++++++++++++++++++++++++++++ docs/configuration.txt | 13 ++++++++++++ getmailcore/_retrieverbases.py | 35 ++++++++++++++++++++++++++------ getmailcore/retrievers.py | 5 +++++ 4 files changed, 84 insertions(+), 6 deletions(-) diff --git a/docs/configuration.html b/docs/configuration.html index 10d2424..01e34d6 100644 --- a/docs/configuration.html +++ b/docs/configuration.html @@ -790,6 +790,13 @@ openssl s_client -showcerts -connect HOST:PORT < /dev/null 2>/dev/null \ server's certificate; otherwise, getmail will error out with a hostname mismatch. </li> + <li> + ssl_cert_hostname + (<a href="#parameter-boolean">boolean</a>) + — Set to <span class="file">False</span> to disable sending the TLS + Server Name Indication extension. Some servers require the client to send + SNI to function correctly. The default is <span class="file">True</span>. + </li> </ul> <h4 id="retriever-simplepop3">SimplePOP3Retriever</h4> @@ -927,6 +934,12 @@ openssl s_client -showcerts -connect HOST:PORT < /dev/null 2>/dev/null \ — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> for definition </li> + <li> + use_sni + (<a href="#parameter-boolean">boolean</a>) + — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> + for definition + </li> </ul> <h4 id="retriever-brokenpop3ssl">BrokenUIDLPOP3SSLRetriever</h4> @@ -981,6 +994,12 @@ openssl s_client -showcerts -connect HOST:PORT < /dev/null 2>/dev/null \ — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> for definition </li> + <li> + use_sni + (<a href="#parameter-boolean">boolean</a>) + — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> + for definition + </li> </ul> <h4 id="retriever-simpleimapssl">SimpleIMAPSSLRetriever</h4> @@ -1042,6 +1061,12 @@ openssl s_client -showcerts -connect HOST:PORT < /dev/null 2>/dev/null \ — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> for definition </li> + <li> + use_sni + (<a href="#parameter-boolean">boolean</a>) + — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> + for definition + </li> </ul> <h4 id="retriever-multidroppop3">MultidropPOP3Retriever</h4> @@ -1152,6 +1177,12 @@ envelope_recipient = delivered-to:1 — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> for definition </li> + <li> + use_sni + (<a href="#parameter-boolean">boolean</a>) + — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> + for definition + </li> </ul> <h4 id="retriever-multidropsdps">MultidropSDPSRetriever</h4> @@ -1285,6 +1316,12 @@ envelope_recipient = delivered-to:1 — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> for definition </li> + <li> + use_sni + (<a href="#parameter-boolean">boolean</a>) + — see <a href="#retriever-ssl-extra">SSL Certificate Validation and Server Parameters</a> + for definition + </li> </ul> <h3 id="retriever-examples">Retriever examples</h3> diff --git a/docs/configuration.txt b/docs/configuration.txt index 43c588b..33e7a17 100644 --- a/docs/configuration.txt +++ b/docs/configuration.txt @@ -515,6 +515,9 @@ openssl s_client -showcerts -connect HOST:PORT < /dev/null 2>/dev/null \ connect to the server is known not to match the hostname in the server's certificate; otherwise, getmail will error out with a hostname mismatch. + * use_sni (boolean) - Set to False to disable sending the TLS + Server Name Indication extension. Some servers require the + client to send SNI to function correctly. The default is True. SimplePOP3Retriever @@ -577,6 +580,8 @@ SimplePOP3SSLRetriever Parameters for definition * ssl_fingerprints (tuple of quoted strings) — see SSL Certificate Validation and Server Parameters for definition + * use_sni (boolean) — see SSL Certificate Validation and Server + Parameters for definition BrokenUIDLPOP3SSLRetriever @@ -593,6 +598,8 @@ BrokenUIDLPOP3SSLRetriever Parameters for definition * ssl_fingerprints (tuple of quoted strings) — see SSL Certificate Validation and Server Parameters for definition + * use_sni (boolean) — see SSL Certificate Validation and Server + Parameters for definition SimpleIMAPSSLRetriever @@ -611,6 +618,8 @@ SimpleIMAPSSLRetriever Parameters for definition * ssl_fingerprints (tuple of quoted strings) — see SSL Certificate Validation and Server Parameters for definition + * use_sni (boolean) — see SSL Certificate Validation and Server + Parameters for definition MultidropPOP3Retriever @@ -647,6 +656,8 @@ MultidropPOP3SSLRetriever Parameters for definition * ssl_fingerprints (tuple of quoted strings) — see SSL Certificate Validation and Server Parameters for definition + * use_sni (boolean) — see SSL Certificate Validation and Server + Parameters for definition MultidropSDPSRetriever @@ -690,6 +701,8 @@ MultidropIMAPSSLRetriever Parameters for definition * ssl_fingerprints (tuple of quoted strings) — see SSL Certificate Validation and Server Parameters for definition + * use_sni (boolean) — see SSL Certificate Validation and Server + Parameters for definition Retriever examples diff --git a/getmailcore/_retrieverbases.py b/getmailcore/_retrieverbases.py index 67f1367..56c5d98 100755 --- a/getmailcore/_retrieverbases.py +++ b/getmailcore/_retrieverbases.py @@ -66,6 +66,23 @@ except ImportError: # If we have an ssl module: if ssl: + if getattr(ssl, 'HAS_SNI', False): + def _wrap_socket(sock, keyfile=None, certfile=None, + server_side=False, cert_reqs=ssl.CERT_NONE, + ssl_version=ssl.PROTOCOL_TLS, ca_certs=None, + do_handshake_on_connect=True, + suppress_ragged_eofs=True, + ciphers=None, server_hostname=None): + return ssl.SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, + server_side=server_side, cert_reqs=cert_reqs, + ssl_version=ssl_version, ca_certs=ca_certs, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs, + ciphers=ciphers, server_hostname=server_hostname) + else: + def _wrap_socket(sock, **kwargs): + return ssl.wrap_socket(sock, **kwargs) + # Is it recent enough to have hostname matching (Python 3.2+)? try: ssl_match_hostname = ssl.match_hostname @@ -278,7 +295,7 @@ class POP3_SSL_EXTENDED(poplib.POP3_SSL): def __init__(self, host, port=POP3_SSL_PORT, keyfile=None, certfile=None, ssl_version=None, ca_certs=None, - ssl_ciphers=None): + ssl_ciphers=None, use_sni=True): self.host = host self.port = port self.keyfile = keyfile @@ -286,6 +303,7 @@ class POP3_SSL_EXTENDED(poplib.POP3_SSL): self.ssl_version = ssl_version self.ca_certs = ca_certs self.ssl_ciphers = ssl_ciphers + self.use_sni = use_sni self.buffer = '' msg = "getaddrinfo returns an empty list" @@ -312,10 +330,12 @@ class POP3_SSL_EXTENDED(poplib.POP3_SSL): extra_args['ca_certs'] = self.ca_certs if self.ssl_ciphers: extra_args['ciphers'] = self.ssl_ciphers + if self.use_sni: + extra_args['server_hostname'] = self.host self.file = self.sock.makefile('rb') - self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, - self.certfile, **extra_args) + self.sslobj = _wrap_socket(self.sock, self.keyfile, + self.certfile, **extra_args) self._debugging = 0 self.welcome = self._getresp() @@ -534,10 +554,11 @@ class IMAP4_SSL_EXTENDED(imaplib.IMAP4_SSL): # fingerprints, etc. def __init__(self, host='', port=imaplib.IMAP4_SSL_PORT, keyfile=None, certfile=None, ssl_version=None, ca_certs=None, - ssl_ciphers=None): + ssl_ciphers=None, use_sni=True): self.ssl_version = ssl_version self.ca_certs = ca_certs self.ssl_ciphers = ssl_ciphers + self.use_sni = use_sni imaplib.IMAP4_SSL.__init__(self, host, port, keyfile, certfile) def open(self, host='', port=imaplib.IMAP4_SSL_PORT): @@ -552,9 +573,11 @@ class IMAP4_SSL_EXTENDED(imaplib.IMAP4_SSL): extra_args['ca_certs'] = self.ca_certs if self.ssl_ciphers: extra_args['ciphers'] = self.ssl_ciphers + if self.use_sni: + extra_args['server_hostname'] = self.host - self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, - **extra_args) + self.sslobj = _wrap_socket(self.sock, self.keyfile, self.certfile, + **extra_args) self.file = self.sslobj.makefile('rb') diff --git a/getmailcore/retrievers.py b/getmailcore/retrievers.py index ecb83e5..7fca807 100755 --- a/getmailcore/retrievers.py +++ b/getmailcore/retrievers.py @@ -106,6 +106,7 @@ class SimplePOP3SSLRetriever(POP3RetrieverBase, POP3SSLinitMixIn): ConfString(name='ssl_version', required=False, default=None), ConfString(name='ssl_ciphers', required=False, default=None), ConfString(name='ssl_cert_hostname', required=False, default=None), + ConfString(name='use_sni', required=False, default=True), ) received_from = None received_with = 'POP3-SSL' @@ -214,6 +215,7 @@ class BrokenUIDLPOP3SSLRetriever(BrokenUIDLPOP3RetrieverBase, POP3SSLinitMixIn): ConfString(name='ssl_version', required=False, default=None), ConfString(name='ssl_ciphers', required=False, default=None), ConfString(name='ssl_cert_hostname', required=False, default=None), + ConfString(name='use_sni', required=False, default=True), ) received_with = 'POP3-SSL' @@ -287,6 +289,7 @@ class MultidropPOP3SSLRetriever(MultidropPOP3RetrieverBase, POP3SSLinitMixIn): ConfString(name='ssl_version', required=False, default=None), ConfString(name='ssl_ciphers', required=False, default=None), ConfString(name='ssl_cert_hostname', required=False, default=None), + ConfString(name='use_sni', required=False, default=True), ) received_from = None received_with = 'POP3-SSL' @@ -440,6 +443,7 @@ class SimpleIMAPSSLRetriever(IMAPRetrieverBase, IMAPSSLinitMixIn): ConfBool(name='use_kerberos', required=False, default=False), ConfBool(name='use_xoauth2', required=False, default=False), ConfString(name='ssl_cert_hostname', required=False, default=None), + ConfString(name='use_sni', required=False, default=True), ) received_from = None received_with = 'IMAP4-SSL' @@ -535,6 +539,7 @@ class MultidropIMAPSSLRetriever(MultidropIMAPRetrieverBase, IMAPSSLinitMixIn): ConfBool(name='use_xoauth2', required=False, default=False), ConfString(name='envelope_recipient'), ConfString(name='ssl_cert_hostname', required=False, default=None), + ConfString(name='use_sni', required=False, default=True), ) received_from = None received_with = 'IMAP4-SSL' -- 2.20.1
signature.asc
(application/pgp-signature, 227 B)
-----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQTJDm02IAobkioVCed2GBllKa5f+AUCXGHYXgAKCRB2GBllKa5f +G3zAP0dfLAMaW+OvAHHYVWDrWy+k0xB9xUBPkl0y0sdnHpIKwEA8ZalG7qxsyMj xZQZzDsoUK8hyUQVq2sZdwII3zsSygQ= =YaMy -----END PGP SIGNATURE-----