Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 48aae57

Browse files
committed
Issue #19782: imaplib now supports SSLContext.check_hostname and server name
indication for TLS/SSL connections.
1 parent 0c924b8 commit 48aae57

4 files changed

Lines changed: 43 additions & 4 deletions

File tree

Doc/library/imaplib.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ There's also a subclass for secure connections:
8080
.. versionchanged:: 3.3
8181
*ssl_context* parameter added.
8282

83+
.. versionchanged:: 3.4
84+
The class now supports hostname check with
85+
:attr:`SSLContext.check_hostname` and *Server Name Indicator* (see
86+
:data:`~ssl.HAS_SNI`).
8387

8488
The second subclass allows for connections created by a child process:
8589

@@ -437,6 +441,10 @@ An :class:`IMAP4` instance has the following methods:
437441

438442
.. versionadded:: 3.2
439443

444+
.. versionchanged:: 3.4
445+
The method now supports hostname check with
446+
:attr:`SSLContext.check_hostname` and *Server Name Indicator* (see
447+
:data:`~ssl.HAS_SNI`).
440448

441449
.. method:: IMAP4.status(mailbox, names)
442450

Lib/imaplib.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,9 @@ def starttls(self, ssl_context=None):
745745
ssl_context = ssl._create_stdlib_context()
746746
typ, dat = self._simple_command(name)
747747
if typ == 'OK':
748-
self.sock = ssl_context.wrap_socket(self.sock)
748+
server_hostname = self.host if ssl.HAS_SNI else None
749+
self.sock = ssl_context.wrap_socket(self.sock,
750+
server_hostname=server_hostname)
749751
self.file = self.sock.makefile('rb')
750752
self._tls_established = True
751753
self._get_capabilities()
@@ -1216,7 +1218,9 @@ def __init__(self, host='', port=IMAP4_SSL_PORT, keyfile=None, certfile=None, ss
12161218

12171219
def _create_socket(self):
12181220
sock = IMAP4._create_socket(self)
1219-
return self.ssl_context.wrap_socket(sock)
1221+
server_hostname = self.host if ssl.HAS_SNI else None
1222+
return self.ssl_context.wrap_socket(sock,
1223+
server_hostname=server_hostname)
12201224

12211225
def open(self, host='', port=IMAP4_SSL_PORT):
12221226
"""Setup connection to remote server on "host:port".

Lib/test/test_imaplib.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ssl = None
2121

2222
CERTFILE = None
23+
CAFILE = None
2324

2425

2526
class TestImaplib(unittest.TestCase):
@@ -348,6 +349,25 @@ class ThreadedNetworkedTestsSSL(BaseThreadedNetworkedTests):
348349
server_class = SecureTCPServer
349350
imap_class = IMAP4_SSL
350351

352+
@reap_threads
353+
def test_ssl_verified(self):
354+
ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
355+
ssl_context.verify_mode = ssl.CERT_REQUIRED
356+
ssl_context.check_hostname = True
357+
ssl_context.load_verify_locations(CAFILE)
358+
359+
with self.assertRaisesRegex(ssl.CertificateError,
360+
"hostname '127.0.0.1' doesn't match 'localhost'"):
361+
with self.reaped_server(SimpleIMAPHandler) as server:
362+
client = self.imap_class(*server.server_address,
363+
ssl_context=ssl_context)
364+
client.shutdown()
365+
366+
with self.reaped_server(SimpleIMAPHandler) as server:
367+
client = self.imap_class("localhost", server.server_address[1],
368+
ssl_context=ssl_context)
369+
client.shutdown()
370+
351371

352372
class RemoteIMAPTest(unittest.TestCase):
353373
host = 'cyrus.andrew.cmu.edu'
@@ -460,11 +480,15 @@ def load_tests(*args):
460480

461481
if support.is_resource_enabled('network'):
462482
if ssl:
463-
global CERTFILE
483+
global CERTFILE, CAFILE
464484
CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
465-
"keycert.pem")
485+
"keycert3.pem")
466486
if not os.path.exists(CERTFILE):
467487
raise support.TestFailed("Can't read certificate files!")
488+
CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
489+
"pycacert.pem")
490+
if not os.path.exists(CAFILE):
491+
raise support.TestFailed("Can't read CA file!")
468492
tests.extend([
469493
ThreadedNetworkedTests, ThreadedNetworkedTestsSSL,
470494
RemoteIMAPTest, RemoteIMAP_SSLTest, RemoteIMAP_STARTTLSTest,

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #19782: imaplib now supports SSLContext.check_hostname and server name
22+
indication for TLS/SSL connections.
23+
2124
- Issue #19834: Support unpickling of exceptions pickled by Python 2.
2225

2326
- Issue #19781: ftplib now supports SSLContext.check_hostname and server name

0 commit comments

Comments
 (0)