-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-31432: Clarify CERT_NONE/OPTIONAL/REQUIRED doc #3530
Conversation
d5084da
to
58d89be
Compare
Memo to me: drop |
58d89be
to
0243bd5
Compare
Modules/_ssl.c
Outdated
@@ -3228,8 +3228,8 @@ set_check_hostname(PySSLContext *self, PyObject *arg, void *c) | |||
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 needs a SSLContext with " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should be an SSLContext
0243bd5
to
2f4126a
Compare
597b493
to
0f3916d
Compare
0f3916d
to
6dde39e
Compare
are provided, validation will be attempted and an :class:`SSLError` | ||
will be raised on failure. | ||
parameter to :func:`wrap_socket`. In client mode, :const:`CERT_OPTIONAL` | ||
has the same meaning as :const:`CERT_REQUIRED`. It is recommended to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if “anonymous ciphers are enabled”, mentioned under https://docs.python.org/dev/library/ssl.html#verifying-certificates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not explain anonymous cipher suites and just remove them from the documentation completely. Anonymous cipher suites is a misleading term. They don't provide anonymity for the user but allow the server to stay anonymous by not providing any authentication. It's totally insecure and no longer supported in TLS 1.3 for a very good reason.
If a certificate is received from the other end, no attempt to validate it | ||
is made. | ||
parameter to :func:`wrap_socket`. Except for :const:`PROTOCOL_TLS_CLIENT`, | ||
it is the default mode. With client-side sockets, just about any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does cert_reqs default to if I call wrap_socket(..., ssl_version=PROTOCOL_TLS_CLIENT)? Judging by the signature and documentation for wrap_socket, CERT_NONE seems to be the default regardless of the protocol setting. If you are only talking about the default value for verify_mode after an SSLContext is constructed, I suggest to mention that under the entry for SSLContext.verify_mode, or the SSLContext constructor, instead of here. (Otherwise, maybe adjust the description of the top-level wrap_socket function.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a moment I feared that you have discovered a security bug.
Thankfully the code is robust and doesn't allow you to use PROTOCOL_TLS_CLIENT
with default arguments of wrap_socket
and SSLSocket
. Both ssl.wrap_socket(ssl_version=ssl.PROTOCOL_TLS_CLIENT)
and ssl.SSLSocket(ssl_version=ssl.PROTOCOL_TLS_CLIENT)
will both fail with error Cannot set verify_mode to CERT_NONE when check_hostname is enabled.
.
So the insecure default doesn't work here. I consider it a feature. :) I'm going to deprecate ssl.wrap_socket
and ssl.SSLSocket()
default constructor because they have more fundamental issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, now I realize that the PROTOCOL_TLS_CLIENT mode is newer than the old wrap_socket function. It was not clear that wrap_socket doesn’t support this new mode, but that is separate to what you are trying to do here.
6dde39e
to
7cb02cf
Compare
@vadmium I have removed the misleading note about anonymous ciphers. |
Hi @vadmium, It looks like this is ready to be merged. Is there anything that prevents doing so at this point? Thanks. |
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. Signed-off-by: Christian Heimes <christian@python.org>
The documentation no longer mentions anonymous ciphers. They are totally insecure and irrelevant for virtually all users. The documentation was also wrong. For anonymous ciphers, CERT_NONE, CERT_OPTIONAL and CERT_REQUIRED all behaved the same. Internally, CERT_REQUIRED = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT but the last flag is ignored in client mode. When a anonymous cipher is used, clients ignore missing server certs. Signed-off-by: Christian Heimes <christian@python.org>
Thanks @tiran for the PR, and @ned-deily for merging it 🌮🎉.. I'm working now to backport this PR to: 2.7, 3.6, 3.7. |
GH-7649 is a backport of this pull request to the 3.7 branch. |
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. (cherry picked from commit ef24b6c) Co-authored-by: Christian Heimes <christian@python.org>
Sorry, @tiran and @ned-deily, I could not cleanly backport this to |
Sorry, @tiran and @ned-deily, I could not cleanly backport this to |
…H-7649) 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. (cherry picked from commit ef24b6c) Co-authored-by: Christian Heimes <christian@python.org>
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.
GH-7652 is a backport of this pull request to the 3.6 branch. |
…H-7652) 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.
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.
Signed-off-by: Christian Heimes christian@python.org
https://bugs.python.org/issue31432