mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue #14837: SSL errors now have library
and reason
attributes describing precisely what happened and in which OpenSSL submodule.
The str() of a SSLError is also enhanced accordingly. NOTE: this commit creates a reference leak. The leak seems tied to the use of PyType_FromSpec() to create the SSLError type. The leak is on the type object when it is instantiated: >>> e = ssl.SSLError() >>> sys.getrefcount(ssl.SSLError) 35 >>> e = ssl.SSLError() >>> sys.getrefcount(ssl.SSLError) 36 >>> e = ssl.SSLError() >>> sys.getrefcount(ssl.SSLError) 37
This commit is contained in:
parent
31227ca514
commit
3b36fb1f53
4 changed files with 262 additions and 65 deletions
|
@ -552,7 +552,7 @@ class ContextTests(unittest.TestCase):
|
|||
with self.assertRaises(FileNotFoundError) as cm:
|
||||
ctx.load_dh_params(WRONGCERT)
|
||||
self.assertEqual(cm.exception.errno, errno.ENOENT)
|
||||
with self.assertRaisesRegex(ssl.SSLError, "PEM routines"):
|
||||
with self.assertRaises(ssl.SSLError) as cm:
|
||||
ctx.load_dh_params(CERTFILE)
|
||||
|
||||
@skip_if_broken_ubuntu_ssl
|
||||
|
@ -590,6 +590,47 @@ class ContextTests(unittest.TestCase):
|
|||
self.assertRaises(ValueError, ctx.set_ecdh_curve, b"foo")
|
||||
|
||||
|
||||
class SSLErrorTests(unittest.TestCase):
|
||||
|
||||
def test_str(self):
|
||||
# The str() of a SSLError doesn't include the errno
|
||||
e = ssl.SSLError(1, "foo")
|
||||
self.assertEqual(str(e), "foo")
|
||||
self.assertEqual(e.errno, 1)
|
||||
# Same for a subclass
|
||||
e = ssl.SSLZeroReturnError(1, "foo")
|
||||
self.assertEqual(str(e), "foo")
|
||||
self.assertEqual(e.errno, 1)
|
||||
|
||||
def test_lib_reason(self):
|
||||
# Test the library and reason attributes
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
with self.assertRaises(ssl.SSLError) as cm:
|
||||
ctx.load_dh_params(CERTFILE)
|
||||
self.assertEqual(cm.exception.library, 'PEM')
|
||||
self.assertEqual(cm.exception.reason, 'NO_START_LINE')
|
||||
s = str(cm.exception)
|
||||
self.assertTrue(s.startswith("[PEM: NO_START_LINE] no start line"), s)
|
||||
|
||||
def test_subclass(self):
|
||||
# Check that the appropriate SSLError subclass is raised
|
||||
# (this only tests one of them)
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
with socket.socket() as s:
|
||||
s.bind(("127.0.0.1", 0))
|
||||
s.listen(5)
|
||||
with socket.socket() as c:
|
||||
c.connect(s.getsockname())
|
||||
c.setblocking(False)
|
||||
c = ctx.wrap_socket(c, False, do_handshake_on_connect=False)
|
||||
with self.assertRaises(ssl.SSLWantReadError) as cm:
|
||||
c.do_handshake()
|
||||
s = str(cm.exception)
|
||||
self.assertTrue(s.startswith("The operation did not complete (read)"), s)
|
||||
# For compatibility
|
||||
self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ)
|
||||
|
||||
|
||||
class NetworkedTests(unittest.TestCase):
|
||||
|
||||
def test_connect(self):
|
||||
|
@ -1931,7 +1972,7 @@ def test_main(verbose=False):
|
|||
if not os.path.exists(filename):
|
||||
raise support.TestFailed("Can't read certificate file %r" % filename)
|
||||
|
||||
tests = [ContextTests, BasicSocketTests]
|
||||
tests = [ContextTests, BasicSocketTests, SSLErrorTests]
|
||||
|
||||
if support.is_resource_enabled('network'):
|
||||
tests.append(NetworkedTests)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue