Skip to content

gh-117784: Only reference PHA functions ifndef SSL_VERIFY_POST_HANDSHAKE #117785

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

Merged
merged 6 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CPython now detects whether its linked TLS library supports TLSv1.3 post-handshake authentication and disables that feature if support is lacking.
28 changes: 17 additions & 11 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ extern const SSL_METHOD *TLSv1_2_method(void);
#endif


#if defined(SSL_VERIFY_POST_HANDSHAKE) && defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3)
#define PySSL_HAVE_POST_HS_AUTH
#endif


enum py_ssl_error {
/* these mirror ssl.h */
PY_SSL_ERROR_NONE,
Expand Down Expand Up @@ -231,7 +236,7 @@ enum py_proto_version {
PY_PROTO_TLSv1 = TLS1_VERSION,
PY_PROTO_TLSv1_1 = TLS1_1_VERSION,
PY_PROTO_TLSv1_2 = TLS1_2_VERSION,
#ifdef TLS1_3_VERSION
#if defined(TLS1_3_VERSION)
PY_PROTO_TLSv1_3 = TLS1_3_VERSION,
#else
PY_PROTO_TLSv1_3 = 0x304,
Expand Down Expand Up @@ -293,7 +298,7 @@ typedef struct {
*/
unsigned int hostflags;
int protocol;
#ifdef TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
int post_handshake_auth;
#endif
PyObject *msg_cb;
Expand Down Expand Up @@ -873,7 +878,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
SSL_set_mode(self->ssl,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY);

#ifdef TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
if (sslctx->post_handshake_auth == 1) {
if (socket_type == PY_SSL_SERVER) {
/* bpo-37428: OpenSSL does not ignore SSL_VERIFY_POST_HANDSHAKE.
Expand Down Expand Up @@ -1016,6 +1021,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
} while (err.ssl == SSL_ERROR_WANT_READ ||
err.ssl == SSL_ERROR_WANT_WRITE);
Py_XDECREF(sock);

if (ret < 1)
return PySSL_SetError(self, __FILE__, __LINE__);
if (PySSL_ChainExceptions(self) < 0)
Expand Down Expand Up @@ -2775,7 +2781,7 @@ static PyObject *
_ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
/*[clinic end generated code: output=532147f3b1341425 input=6bfa874810a3d889]*/
{
#ifdef TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
int err = SSL_verify_client_post_handshake(self->ssl);
if (err == 0)
return _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__);
Expand Down Expand Up @@ -3198,7 +3204,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_TRUSTED_FIRST);
X509_VERIFY_PARAM_set_hostflags(params, self->hostflags);

#ifdef TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
self->post_handshake_auth = 0;
SSL_CTX_set_post_handshake_auth(self->ctx, self->post_handshake_auth);
#endif
Expand Down Expand Up @@ -3576,7 +3582,7 @@ set_maximum_version(PySSLContext *self, PyObject *arg, void *c)
return set_min_max_proto_version(self, arg, 1);
}

#ifdef TLS1_3_VERSION
#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are tickets used only for post-handshake authentication? From the docs it looks like a separate TLSv1.3 feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, tickets are used for session resumption and are unrelated to post-handshake authentication. I believe get_num_tickets pertains to a post-handshake message added in TLSv1.3. SSL_CTX_get_num_tickets's docs indicate as much.

This change just updates that guard to honor OpenSSL's OPENSSL_NO_TLS1_3 as other parts of _ssl.c already do.

static PyObject *
get_num_tickets(PySSLContext *self, void *c)
{
Expand Down Expand Up @@ -3607,7 +3613,7 @@ set_num_tickets(PySSLContext *self, PyObject *arg, void *c)

PyDoc_STRVAR(PySSLContext_num_tickets_doc,
"Control the number of TLSv1.3 session tickets");
#endif /* TLS1_3_VERSION */
#endif /* defined(TLS1_3_VERSION) */

static PyObject *
get_security_level(PySSLContext *self, void *c)
Expand Down Expand Up @@ -3710,14 +3716,14 @@ set_check_hostname(PySSLContext *self, PyObject *arg, void *c)

static PyObject *
get_post_handshake_auth(PySSLContext *self, void *c) {
#if TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
return PyBool_FromLong(self->post_handshake_auth);
#else
Py_RETURN_NONE;
#endif
}

#if TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
static int
set_post_handshake_auth(PySSLContext *self, PyObject *arg, void *c) {
if (arg == NULL) {
Expand Down Expand Up @@ -4959,14 +4965,14 @@ static PyGetSetDef context_getsetlist[] = {
(setter) _PySSLContext_set_msg_callback, NULL},
{"sni_callback", (getter) get_sni_callback,
(setter) set_sni_callback, PySSLContext_sni_callback_doc},
#ifdef TLS1_3_VERSION
#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3)
{"num_tickets", (getter) get_num_tickets,
(setter) set_num_tickets, PySSLContext_num_tickets_doc},
#endif
{"options", (getter) get_options,
(setter) set_options, NULL},
{"post_handshake_auth", (getter) get_post_handshake_auth,
#ifdef TLS1_3_VERSION
#if defined(PySSL_HAVE_POST_HS_AUTH)
(setter) set_post_handshake_auth,
#else
NULL,
Expand Down
Loading