Skip to content

Commit ef24b6c

Browse files
tiranned-deily
authored andcommitted
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.
1 parent 4b704f2 commit ef24b6c

File tree

4 files changed

+32
-16
lines changed

4 files changed

+32
-16
lines changed

Doc/library/ssl.rst

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -541,20 +541,28 @@ Constants
541541
.. data:: CERT_NONE
542542

543543
Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
544-
parameter to :func:`wrap_socket`. In this mode (the default), no
545-
certificates will be required from the other side of the socket connection.
546-
If a certificate is received from the other end, no attempt to validate it
547-
is made.
544+
parameter to :func:`wrap_socket`. Except for :const:`PROTOCOL_TLS_CLIENT`,
545+
it is the default mode. With client-side sockets, just about any
546+
cert is accepted. Validation errors, such as untrusted or expired cert,
547+
are ignored and do not abort the TLS/SSL handshake.
548+
549+
In server mode, no certificate is requested from the client, so the client
550+
does not send any for client cert authentication.
548551

549552
See the discussion of :ref:`ssl-security` below.
550553

551554
.. data:: CERT_OPTIONAL
552555

553556
Possible value for :attr:`SSLContext.verify_mode`, or the ``cert_reqs``
554-
parameter to :func:`wrap_socket`. In this mode no certificates will be
555-
required from the other side of the socket connection; but if they
556-
are provided, validation will be attempted and an :class:`SSLError`
557-
will be raised on failure.
557+
parameter to :func:`wrap_socket`. In client mode, :const:`CERT_OPTIONAL`
558+
has the same meaning as :const:`CERT_REQUIRED`. It is recommended to
559+
use :const:`CERT_REQUIRED` for client-side sockets instead.
560+
561+
In server mode, a client certificate request is sent to the client. The
562+
client may either ignore the request or send a certificate in order
563+
perform TLS client cert authentication. If the client chooses to send
564+
a certificate, it is verified. Any verification error immediately aborts
565+
the TLS handshake.
558566

559567
Use of this setting requires a valid set of CA certificates to
560568
be passed, either to :meth:`SSLContext.load_verify_locations` or as a
@@ -566,6 +574,15 @@ Constants
566574
parameter to :func:`wrap_socket`. In this mode, certificates are
567575
required from the other side of the socket connection; an :class:`SSLError`
568576
will be raised if no certificate is provided, or if its validation fails.
577+
This mode is **not** sufficient to verify a certificate in client mode as
578+
it does not match hostnames. :attr:`~SSLContext.check_hostname` must be
579+
enabled as well to verify the authenticity of a cert.
580+
:const:`PROTOCOL_TLS_CLIENT` uses :const:`CERT_REQUIRED` and
581+
enables :attr:`~SSLContext.check_hostname` by default.
582+
583+
With server socket, this mode provides mandatory TLS client cert
584+
authentication. A client certificate request is sent to the client and
585+
the client must provide a valid and trusted certificate.
569586

570587
Use of this setting requires a valid set of CA certificates to
571588
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
25372554
(rather than using a higher-level authentication mechanism), you'll also have
25382555
to specify :const:`CERT_REQUIRED` and similarly check the client certificate.
25392556

2540-
.. note::
2541-
2542-
In client mode, :const:`CERT_OPTIONAL` and :const:`CERT_REQUIRED` are
2543-
equivalent unless anonymous ciphers are enabled (they are disabled
2544-
by default).
25452557

25462558
Protocol versions
25472559
'''''''''''''''''

Lib/test/test_ssl.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4074,7 +4074,9 @@ def test_session_handling(self):
40744074
self.assertTrue(session)
40754075
with self.assertRaises(TypeError) as e:
40764076
s.session = object
4077-
self.assertEqual(str(e.exception), 'Value is not a SSLSession.')
4077+
self.assertEqual(
4078+
str(e.exception), 'Value is not an SSLSession.'
4079+
)
40784080

40794081
with client_context.wrap_socket(socket.socket(),
40804082
server_hostname=hostname) as s:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Clarify meaning of CERT_NONE, CERT_OPTIONAL, and CERT_REQUIRED flags for
2+
ssl.SSLContext.verify_mode.

Modules/_ssl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,7 +2066,7 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value,
20662066
SSL_set_SSL_CTX(self->ssl, self->ctx->ctx);
20672067
#endif
20682068
} else {
2069-
PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext");
2069+
PyErr_SetString(PyExc_TypeError, "The value must be an SSLContext.");
20702070
return -1;
20712071
}
20722072

@@ -2725,7 +2725,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
27252725
int result;
27262726

27272727
if (!PySSLSession_Check(value)) {
2728-
PyErr_SetString(PyExc_TypeError, "Value is not a SSLSession.");
2728+
PyErr_SetString(PyExc_TypeError, "Value is not an SSLSession.");
27292729
return -1;
27302730
}
27312731
pysess = (PySSLSession *)value;

0 commit comments

Comments
 (0)