diff -r a812de69b493 Lib/ftplib.py --- a/Lib/ftplib.py Mon Aug 20 23:02:28 2012 +1000 +++ b/Lib/ftplib.py Wed Aug 22 00:46:31 2012 +1000 @@ -697,12 +697,16 @@ resp = self.voidcmd('AUTH TLS') else: resp = self.voidcmd('AUTH SSL') - if self.context is not None: - self.sock = self.context.wrap_socket(self.sock) - else: - self.sock = ssl.wrap_socket(self.sock, self.keyfile, - self.certfile, - ssl_version=self.ssl_version) + + if self.context is None: + self.context = ssl.SSLContext(self.ssl_version) + self.context.options |= ssl.OP_NO_SSLv2 + if self.certfile or self.keyfile: + self.context.load_cert_chain(self.certfile, self.keyfile) + + server_hostname = self.host if ssl.HAS_SNI and self.host else None + self.sock = self.context.wrap_socket(self.sock, + server_hostname=server_hostname) self.file = self.sock.makefile(mode='r', encoding=self.encoding) return resp @@ -741,11 +745,13 @@ def ntransfercmd(self, cmd, rest=None): conn, size = FTP.ntransfercmd(self, cmd, rest) if self._prot_p: - if self.context is not None: - conn = self.context.wrap_socket(conn) - else: - conn = ssl.wrap_socket(conn, self.keyfile, self.certfile, - ssl_version=self.ssl_version) + if self.context is None: + self.context = ssl.SSLContext(self.ssl_version) + self.context.options |= ssl.OP_NO_SSLv2 + self.context.load_cert_chain(self.certfile, self.keyfile) + + server_hostname = self.host if ssl.HAS_SNI and self.host else None + conn = self.context.wrap_socket(conn, server_hostname=server_hostname) return conn, size def retrbinary(self, cmd, callback, blocksize=8192, rest=None): diff -r a812de69b493 Lib/imaplib.py --- a/Lib/imaplib.py Mon Aug 20 23:02:28 2012 +1000 +++ b/Lib/imaplib.py Wed Aug 22 00:46:31 2012 +1000 @@ -731,7 +731,9 @@ ssl_context.options |= ssl.OP_NO_SSLv2 typ, dat = self._simple_command(name) if typ == 'OK': - self.sock = ssl_context.wrap_socket(self.sock) + server_hostname = self.host if ssl.HAS_SNI else None + self.sock = ssl_context.wrap_socket(self.sock, + server_hostname=server_hostname) self.file = self.sock.makefile('rb') self._tls_established = True self._get_capabilities() @@ -1199,10 +1201,16 @@ def _create_socket(self): sock = IMAP4._create_socket(self) - if self.ssl_context: - return self.ssl_context.wrap_socket(sock) - else: - return ssl.wrap_socket(sock, self.keyfile, self.certfile) + if self.ssl_context is None: + self.ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + self.ssl_context.options |= ssl.OP_NO_SSLv2 + if self.keyfile or self.certfile: + self.ssl_context.load_cert_chain(self.certfile, self.keyfile) + + server_hostname = self.host if ssl.HAS_SNI else None + + return self.ssl_context.wrap_socket(sock, + server_hostname=server_hostname) def open(self, host='', port=IMAP4_SSL_PORT): """Setup connection to remote server on "host:port". diff -r a812de69b493 Lib/nntplib.py --- a/Lib/nntplib.py Mon Aug 20 23:02:28 2012 +1000 +++ b/Lib/nntplib.py Wed Aug 22 00:46:31 2012 +1000 @@ -272,10 +272,11 @@ if _have_ssl: - def _encrypt_on(sock, context): + def _encrypt_on(sock, context, server_hostname=None): """Wrap a socket in SSL/TLS. Arguments: - sock: Socket to wrap - context: SSL context to use for the encrypted connection + - server_hostname: The SNI server hostname to use if SNI is possible Returns: - sock: New, encrypted socket. """ @@ -284,7 +285,8 @@ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) # SSLv2 considered harmful. context.options |= ssl.OP_NO_SSLv2 - return context.wrap_socket(sock) + server_hostname = server_hostname if ssl.HAS_SNI else None + return context.wrap_socket(sock, server_hostname=server_hostname) # The classes themselves @@ -998,7 +1000,7 @@ resp = self._shortcmd('STARTTLS') if resp.startswith('382'): self.file.close() - self.sock = _encrypt_on(self.sock, context) + self.sock = _encrypt_on(self.sock, context, self.host) self.file = self.sock.makefile("rwb") self.tls_on = True # Capabilities may change after TLS starts up, so ask for them @@ -1058,7 +1060,7 @@ in default port and the `ssl_context` argument for SSL connections. """ self.sock = socket.create_connection((host, port), timeout) - self.sock = _encrypt_on(self.sock, ssl_context) + self.sock = _encrypt_on(self.sock, ssl_context,host) file = self.sock.makefile("rwb") _NNTPBase.__init__(self, file, host, readermode=readermode, timeout=timeout) diff -r a812de69b493 Lib/poplib.py --- a/Lib/poplib.py Mon Aug 20 23:02:28 2012 +1000 +++ b/Lib/poplib.py Wed Aug 22 00:46:31 2012 +1000 @@ -349,10 +349,13 @@ def _create_socket(self, timeout): sock = POP3._create_socket(self, timeout) - if self.context is not None: - sock = self.context.wrap_socket(sock) - else: - sock = ssl.wrap_socket(sock, self.keyfile, self.certfile) + if self.context is None: + self.context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + self.context.options |= ssl.OP_NO_SSLv2 + + server_hostname = self.host if ssl.HAS_SNI else None + sock = self.context.wrap_socket(sock, + server_hostname=server_hostname) return sock __all__.append("POP3_SSL") diff -r a812de69b493 Lib/smtplib.py --- a/Lib/smtplib.py Mon Aug 20 23:02:28 2012 +1000 +++ b/Lib/smtplib.py Wed Aug 22 00:46:31 2012 +1000 @@ -233,6 +233,7 @@ self.timeout = timeout self.esmtp_features = {} self.source_address = source_address + self.host = host if host: (code, msg) = self.connect(host, port) @@ -662,10 +663,13 @@ if context is not None and certfile is not None: raise ValueError("context and certfile arguments are mutually " "exclusive") - if context is not None: - self.sock = context.wrap_socket(self.sock) - else: - self.sock = ssl.wrap_socket(self.sock, keyfile, certfile) + if context is None: + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + context.options |= ssl.OP_NO_SSLv2 + + server_hostname = self.host if ssl.HAS_SNI else None + self.sock = context.wrap_socket(self.sock, + server_hostname=server_hostname) self.file = None # RFC 3207: # The client MUST discard any knowledge obtained from @@ -876,10 +880,16 @@ print('connect:', (host, port), file=stderr) new_socket = socket.create_connection((host, port), timeout, self.source_address) - if self.context is not None: - new_socket = self.context.wrap_socket(new_socket) - else: - new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile) + if self.context is None: + self.context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + self.context.options |= ssl.OP_NO_SSLv2 + + if self.keyfile or self.certfile: + self.context.load_cert_chain(self.certfile, self.keyfile) + + server_hostname = self.host if ssl.HAS_SNI else None + new_socket = self.context.wrap_socket(new_socket, + server_hostname=server_hostname) return new_socket __all__.append("SMTP_SSL")