Commit ef24b6c5 authored by Christian Heimes's avatar Christian Heimes Committed by Ned Deily

bpo-31432: Clarify ssl CERT_NONE/OPTIONAL/REQUIRED docs. (GH-3530)

The documentation for CERT_NONE, CERT_OPTIONAL, and CERT_REQUIRED were
misleading and partly wrong. It fails to explain that OpenSSL behaves
differently in client and server mode. Also OpenSSL does validate the
cert chain everytime. With SSL_VERIFY_NONE a validation error is not
fatal in client mode and does not request a client cert in server mode.
Also discourage people from using CERT_OPTIONAL in client mode.
parent 4b704f29
...@@ -541,20 +541,28 @@ Constants ...@@ -541,20 +541,28 @@ Constants
.. data:: CERT_NONE .. data:: CERT_NONE
Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
parameter to :func:`wrap_socket`. In this mode (the default), no parameter to :func:`wrap_socket`. Except for :const:`PROTOCOL_TLS_CLIENT`,
certificates will be required from the other side of the socket connection. it is the default mode. With client-side sockets, just about any
If a certificate is received from the other end, no attempt to validate it cert is accepted. Validation errors, such as untrusted or expired cert,
is made. are ignored and do not abort the TLS/SSL handshake.
In server mode, no certificate is requested from the client, so the client
does not send any for client cert authentication.
See the discussion of :ref:`ssl-security` below. See the discussion of :ref:`ssl-security` below.
.. data:: CERT_OPTIONAL .. data:: CERT_OPTIONAL
Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs`` Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
parameter to :func:`wrap_socket`. In this mode no certificates will be parameter to :func:`wrap_socket`. In client mode, :const:`CERT_OPTIONAL`
required from the other side of the socket connection; but if they has the same meaning as :const:`CERT_REQUIRED`. It is recommended to
are provided, validation will be attempted and an :class:`SSLError` use :const:`CERT_REQUIRED` for client-side sockets instead.
will be raised on failure.
In server mode, a client certificate request is sent to the client. The
client may either ignore the request or send a certificate in order
perform TLS client cert authentication. If the client chooses to send
a certificate, it is verified. Any verification error immediately aborts
the TLS handshake.
Use of this setting requires a valid set of CA certificates to Use of this setting requires a valid set of CA certificates to
be passed, either to :meth:`SSLContext.load_verify_locations` or as a be passed, either to :meth:`SSLContext.load_verify_locations` or as a
...@@ -566,6 +574,15 @@ Constants ...@@ -566,6 +574,15 @@ Constants
parameter to :func:`wrap_socket`. In this mode, certificates are parameter to :func:`wrap_socket`. In this mode, certificates are
required from the other side of the socket connection; an :class:`SSLError` required from the other side of the socket connection; an :class:`SSLError`
will be raised if no certificate is provided, or if its validation fails. will be raised if no certificate is provided, or if its validation fails.
This mode is **not** sufficient to verify a certificate in client mode as
it does not match hostnames. :attr:`~SSLContext.check_hostname` must be
enabled as well to verify the authenticity of a cert.
:const:`PROTOCOL_TLS_CLIENT` uses :const:`CERT_REQUIRED` and
enables :attr:`~SSLContext.check_hostname` by default.
With server socket, this mode provides mandatory TLS client cert
authentication. A client certificate request is sent to the client and
the client must provide a valid and trusted certificate.
Use of this setting requires a valid set of CA certificates to Use of this setting requires a valid set of CA certificates to
be passed, either to :meth:`SSLContext.load_verify_locations` or as a be passed, either to :meth:`SSLContext.load_verify_locations` or as a
...@@ -2537,11 +2554,6 @@ In server mode, if you want to authenticate your clients using the SSL layer ...@@ -2537,11 +2554,6 @@ In server mode, if you want to authenticate your clients using the SSL layer
(rather than using a higher-level authentication mechanism), you'll also have (rather than using a higher-level authentication mechanism), you'll also have
to specify :const:`CERT_REQUIRED` and similarly check the client certificate. to specify :const:`CERT_REQUIRED` and similarly check the client certificate.
.. note::
In client mode, :const:`CERT_OPTIONAL` and :const:`CERT_REQUIRED` are
equivalent unless anonymous ciphers are enabled (they are disabled
by default).
Protocol versions Protocol versions
''''''''''''''''' '''''''''''''''''
......
...@@ -4074,7 +4074,9 @@ class ThreadedTests(unittest.TestCase): ...@@ -4074,7 +4074,9 @@ class ThreadedTests(unittest.TestCase):
self.assertTrue(session) self.assertTrue(session)
with self.assertRaises(TypeError) as e: with self.assertRaises(TypeError) as e:
s.session = object s.session = object
self.assertEqual(str(e.exception), 'Value is not a SSLSession.') self.assertEqual(
str(e.exception), 'Value is not an SSLSession.'
)
with client_context.wrap_socket(socket.socket(), with client_context.wrap_socket(socket.socket(),
server_hostname=hostname) as s: server_hostname=hostname) as s:
......
Clarify meaning of CERT_NONE, CERT_OPTIONAL, and CERT_REQUIRED flags for
ssl.SSLContext.verify_mode.
...@@ -2066,7 +2066,7 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value, ...@@ -2066,7 +2066,7 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value,
SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); SSL_set_SSL_CTX(self->ssl, self->ctx->ctx);
#endif #endif
} else { } else {
PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); PyErr_SetString(PyExc_TypeError, "The value must be an SSLContext.");
return -1; return -1;
} }
...@@ -2725,7 +2725,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, ...@@ -2725,7 +2725,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
int result; int result;
if (!PySSLSession_Check(value)) { if (!PySSLSession_Check(value)) {
PyErr_SetString(PyExc_TypeError, "Value is not a SSLSession."); PyErr_SetString(PyExc_TypeError, "Value is not an SSLSession.");
return -1; return -1;
} }
pysess = (PySSLSession *)value; pysess = (PySSLSession *)value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment