mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #13721: SSLSocket.getpeercert() and SSLSocket.do_handshake() now raise an OSError with ENOTCONN, instead of an AttributeError, when the SSLSocket is not connected.
This commit is contained in:
parent
f6ca26fbff
commit
242db728e2
3 changed files with 41 additions and 12 deletions
34
Lib/ssl.py
34
Lib/ssl.py
|
@ -299,7 +299,6 @@ class SSLSocket(socket):
|
||||||
self.server_hostname = server_hostname
|
self.server_hostname = server_hostname
|
||||||
self.do_handshake_on_connect = do_handshake_on_connect
|
self.do_handshake_on_connect = do_handshake_on_connect
|
||||||
self.suppress_ragged_eofs = suppress_ragged_eofs
|
self.suppress_ragged_eofs = suppress_ragged_eofs
|
||||||
connected = False
|
|
||||||
if sock is not None:
|
if sock is not None:
|
||||||
socket.__init__(self,
|
socket.__init__(self,
|
||||||
family=sock.family,
|
family=sock.family,
|
||||||
|
@ -307,20 +306,22 @@ class SSLSocket(socket):
|
||||||
proto=sock.proto,
|
proto=sock.proto,
|
||||||
fileno=sock.fileno())
|
fileno=sock.fileno())
|
||||||
self.settimeout(sock.gettimeout())
|
self.settimeout(sock.gettimeout())
|
||||||
# see if it's connected
|
|
||||||
try:
|
|
||||||
sock.getpeername()
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno != errno.ENOTCONN:
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
connected = True
|
|
||||||
sock.detach()
|
sock.detach()
|
||||||
elif fileno is not None:
|
elif fileno is not None:
|
||||||
socket.__init__(self, fileno=fileno)
|
socket.__init__(self, fileno=fileno)
|
||||||
else:
|
else:
|
||||||
socket.__init__(self, family=family, type=type, proto=proto)
|
socket.__init__(self, family=family, type=type, proto=proto)
|
||||||
|
|
||||||
|
# See if we are connected
|
||||||
|
try:
|
||||||
|
self.getpeername()
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno != errno.ENOTCONN:
|
||||||
|
raise
|
||||||
|
connected = False
|
||||||
|
else:
|
||||||
|
connected = True
|
||||||
|
|
||||||
self._closed = False
|
self._closed = False
|
||||||
self._sslobj = None
|
self._sslobj = None
|
||||||
self._connected = connected
|
self._connected = connected
|
||||||
|
@ -339,6 +340,7 @@ class SSLSocket(socket):
|
||||||
except OSError as x:
|
except OSError as x:
|
||||||
self.close()
|
self.close()
|
||||||
raise x
|
raise x
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def context(self):
|
def context(self):
|
||||||
return self._context
|
return self._context
|
||||||
|
@ -356,6 +358,14 @@ class SSLSocket(socket):
|
||||||
# raise an exception here if you wish to check for spurious closes
|
# raise an exception here if you wish to check for spurious closes
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _check_connected(self):
|
||||||
|
if not self._connected:
|
||||||
|
# getpeername() will raise ENOTCONN if the socket is really
|
||||||
|
# not connected; note that we can be connected even without
|
||||||
|
# _connected being set, e.g. if connect() first returned
|
||||||
|
# EAGAIN.
|
||||||
|
self.getpeername()
|
||||||
|
|
||||||
def read(self, len=0, buffer=None):
|
def read(self, len=0, buffer=None):
|
||||||
"""Read up to LEN bytes and return them.
|
"""Read up to LEN bytes and return them.
|
||||||
Return zero-length string on EOF."""
|
Return zero-length string on EOF."""
|
||||||
|
@ -390,6 +400,7 @@ class SSLSocket(socket):
|
||||||
certificate was provided, but not validated."""
|
certificate was provided, but not validated."""
|
||||||
|
|
||||||
self._checkClosed()
|
self._checkClosed()
|
||||||
|
self._check_connected()
|
||||||
return self._sslobj.peer_certificate(binary_form)
|
return self._sslobj.peer_certificate(binary_form)
|
||||||
|
|
||||||
def selected_npn_protocol(self):
|
def selected_npn_protocol(self):
|
||||||
|
@ -538,12 +549,11 @@ class SSLSocket(socket):
|
||||||
|
|
||||||
def _real_close(self):
|
def _real_close(self):
|
||||||
self._sslobj = None
|
self._sslobj = None
|
||||||
# self._closed = True
|
|
||||||
socket._real_close(self)
|
socket._real_close(self)
|
||||||
|
|
||||||
def do_handshake(self, block=False):
|
def do_handshake(self, block=False):
|
||||||
"""Perform a TLS/SSL handshake."""
|
"""Perform a TLS/SSL handshake."""
|
||||||
|
self._check_connected()
|
||||||
timeout = self.gettimeout()
|
timeout = self.gettimeout()
|
||||||
try:
|
try:
|
||||||
if timeout == 0.0 and block:
|
if timeout == 0.0 and block:
|
||||||
|
@ -567,9 +577,9 @@ class SSLSocket(socket):
|
||||||
rc = None
|
rc = None
|
||||||
socket.connect(self, addr)
|
socket.connect(self, addr)
|
||||||
if not rc:
|
if not rc:
|
||||||
|
self._connected = True
|
||||||
if self.do_handshake_on_connect:
|
if self.do_handshake_on_connect:
|
||||||
self.do_handshake()
|
self.do_handshake()
|
||||||
self._connected = True
|
|
||||||
return rc
|
return rc
|
||||||
except OSError:
|
except OSError:
|
||||||
self._sslobj = None
|
self._sslobj = None
|
||||||
|
|
|
@ -17,6 +17,7 @@ import asyncore
|
||||||
import weakref
|
import weakref
|
||||||
import platform
|
import platform
|
||||||
import functools
|
import functools
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
ssl = support.import_module("ssl")
|
ssl = support.import_module("ssl")
|
||||||
|
|
||||||
|
@ -1931,6 +1932,20 @@ else:
|
||||||
self.assertIsInstance(remote, ssl.SSLSocket)
|
self.assertIsInstance(remote, ssl.SSLSocket)
|
||||||
self.assertEqual(peer, client_addr)
|
self.assertEqual(peer, client_addr)
|
||||||
|
|
||||||
|
def test_getpeercert_enotconn(self):
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||||
|
with context.wrap_socket(socket.socket()) as sock:
|
||||||
|
with self.assertRaises(OSError) as cm:
|
||||||
|
sock.getpeercert()
|
||||||
|
self.assertEqual(cm.exception.errno, errno.ENOTCONN)
|
||||||
|
|
||||||
|
def test_do_handshake_enotconn(self):
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||||
|
with context.wrap_socket(socket.socket()) as sock:
|
||||||
|
with self.assertRaises(OSError) as cm:
|
||||||
|
sock.do_handshake()
|
||||||
|
self.assertEqual(cm.exception.errno, errno.ENOTCONN)
|
||||||
|
|
||||||
def test_default_ciphers(self):
|
def test_default_ciphers(self):
|
||||||
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -60,6 +60,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #13721: SSLSocket.getpeercert() and SSLSocket.do_handshake() now
|
||||||
|
raise an OSError with ENOTCONN, instead of an AttributeError, when the
|
||||||
|
SSLSocket is not connected.
|
||||||
|
|
||||||
- Issue #14679: add an __all__ (that contains only HTMLParser) to html.parser.
|
- Issue #14679: add an __all__ (that contains only HTMLParser) to html.parser.
|
||||||
|
|
||||||
- Issue #17802: Fix an UnboundLocalError in html.parser. Initial tests by
|
- Issue #17802: Fix an UnboundLocalError in html.parser. Initial tests by
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue