bpo-31431: SSLContext.check_hostname auto-sets CERT_REQUIRED (#3531)
Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
parent
a170fa162d
commit
e82c034496
|
@ -1674,7 +1674,10 @@ to speed up repeated connections from the same clients.
|
|||
:meth:`SSLSocket.do_handshake`. The context's
|
||||
:attr:`~SSLContext.verify_mode` must be set to :data:`CERT_OPTIONAL` or
|
||||
:data:`CERT_REQUIRED`, and you must pass *server_hostname* to
|
||||
:meth:`~SSLContext.wrap_socket` in order to match the hostname.
|
||||
:meth:`~SSLContext.wrap_socket` in order to match the hostname. Enabling
|
||||
hostname checking automatically sets :attr:`~SSLContext.verify_mode` from
|
||||
:data:`CERT_NONE` to :data:`CERT_REQUIRED`. It cannot be set back to
|
||||
:data:`CERT_NONE` as long as hostname checking is enabled.
|
||||
|
||||
Example::
|
||||
|
||||
|
@ -1691,6 +1694,13 @@ to speed up repeated connections from the same clients.
|
|||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. versionchanged:: 3.7
|
||||
|
||||
:attr:`~SSLContext.verify_mode` is now automatically changed
|
||||
to :data:`CERT_REQUIRED` when hostname checking is enabled and
|
||||
:attr:`~SSLContext.verify_mode` is :data:`CERT_NONE`. Previously
|
||||
the same operation would have failed with a :exc:`ValueError`.
|
||||
|
||||
.. note::
|
||||
|
||||
This features requires OpenSSL 0.9.8f or newer.
|
||||
|
|
|
@ -1363,24 +1363,45 @@ class ContextTests(unittest.TestCase):
|
|||
def test_check_hostname(self):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||
self.assertFalse(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
|
||||
|
||||
# Requires CERT_REQUIRED or CERT_OPTIONAL
|
||||
with self.assertRaises(ValueError):
|
||||
# Auto set CERT_REQUIRED
|
||||
ctx.check_hostname = True
|
||||
self.assertTrue(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_REQUIRED
|
||||
self.assertFalse(ctx.check_hostname)
|
||||
ctx.check_hostname = True
|
||||
self.assertTrue(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||
|
||||
ctx.verify_mode = ssl.CERT_OPTIONAL
|
||||
# Changing verify_mode does not affect check_hostname
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
ctx.check_hostname = False
|
||||
self.assertFalse(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
|
||||
# Auto set
|
||||
ctx.check_hostname = True
|
||||
self.assertTrue(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_OPTIONAL
|
||||
ctx.check_hostname = False
|
||||
self.assertFalse(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
|
||||
# keep CERT_OPTIONAL
|
||||
ctx.check_hostname = True
|
||||
self.assertTrue(ctx.check_hostname)
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_OPTIONAL)
|
||||
|
||||
# Cannot set CERT_NONE with check_hostname enabled
|
||||
with self.assertRaises(ValueError):
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
ctx.check_hostname = False
|
||||
self.assertFalse(ctx.check_hostname)
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
|
||||
|
||||
def test_context_client_server(self):
|
||||
# PROTOCOL_TLS_CLIENT has sane defaults
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
SSLContext.check_hostname now automatically sets SSLContext.verify_mode to
|
||||
ssl.CERT_REQUIRED instead of failing with a ValueError.
|
|
@ -3227,11 +3227,11 @@ set_check_hostname(PySSLContext *self, PyObject *arg, void *c)
|
|||
return -1;
|
||||
if (check_hostname &&
|
||||
SSL_CTX_get_verify_mode(self->ctx) == SSL_VERIFY_NONE) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"check_hostname needs a SSL context with either "
|
||||
"CERT_OPTIONAL or CERT_REQUIRED");
|
||||
/* check_hostname = True sets verify_mode = CERT_REQUIRED */
|
||||
if (_set_verify_mode(self->ctx, PY_SSL_CERT_REQUIRED) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
self->check_hostname = check_hostname;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue