From 78c7d527799dacca91b9ed67057cb996efe526b0 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 3 Jun 2019 21:00:10 +0200 Subject: [PATCH] bpo-37120: Add SSLContext.num_tickets (GH-13719) Signed-off-by: Christian Heimes --- Doc/library/ssl.rst | 13 +++++++ Lib/test/test_ssl.py | 18 +++++++++ .../2019-06-01-09-03-32.bpo-37120.FOKQLU.rst | 1 + Modules/_ssl.c | 37 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-06-01-09-03-32.bpo-37120.FOKQLU.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index be09f38f7d..279af57289 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1959,6 +1959,19 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.7 +.. attribute:: SSLContext.num_tickets + + Control the number of TLS 1.3 session tickets of a + :attr:`TLS_PROTOCOL_SERVER` context. The setting has no impact on TLS + 1.0 to 1.2 connections. + + .. note:: + + This attribute is not available unless the ssl module is compiled + with OpenSSL 1.1.1 or newer. + + .. versionadded:: 3.8 + .. attribute:: SSLContext.options An integer representing the set of SSL options enabled on this context. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 455a12ea7f..7ba8156eef 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1634,6 +1634,24 @@ class ContextTests(unittest.TestCase): obj = ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO()) self.assertIsInstance(obj, MySSLObject) + @unittest.skipUnless(IS_OPENSSL_1_1_1, "Test requires OpenSSL 1.1.1") + def test_num_tickest(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + self.assertEqual(ctx.num_tickets, 2) + ctx.num_tickets = 1 + self.assertEqual(ctx.num_tickets, 1) + ctx.num_tickets = 0 + self.assertEqual(ctx.num_tickets, 0) + with self.assertRaises(ValueError): + ctx.num_tickets = -1 + with self.assertRaises(TypeError): + ctx.num_tickets = None + + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + self.assertEqual(ctx.num_tickets, 2) + with self.assertRaises(ValueError): + ctx.num_tickets = 1 + class SSLErrorTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-06-01-09-03-32.bpo-37120.FOKQLU.rst b/Misc/NEWS.d/next/Library/2019-06-01-09-03-32.bpo-37120.FOKQLU.rst new file mode 100644 index 0000000000..6bea492e6a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-01-09-03-32.bpo-37120.FOKQLU.rst @@ -0,0 +1 @@ +Add SSLContext.num_tickets to control the number of TLSv1.3 session tickets. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f40127d3d9..2331c58ad7 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3617,6 +3617,39 @@ set_maximum_version(PySSLContext *self, PyObject *arg, void *c) } #endif /* SSL_CTRL_GET_MAX_PROTO_VERSION */ +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +static PyObject * +get_num_tickets(PySSLContext *self, void *c) +{ + return PyLong_FromLong(SSL_CTX_get_num_tickets(self->ctx)); +} + +static int +set_num_tickets(PySSLContext *self, PyObject *arg, void *c) +{ + long num; + if (!PyArg_Parse(arg, "l", &num)) + return -1; + if (num < 0) { + PyErr_SetString(PyExc_ValueError, "value must be non-negative"); + return -1; + } + if (self->protocol != PY_SSL_VERSION_TLS_SERVER) { + PyErr_SetString(PyExc_ValueError, + "SSLContext is not a server context."); + return -1; + } + if (SSL_CTX_set_num_tickets(self->ctx, num) != 1) { + PyErr_SetString(PyExc_ValueError, "failed to set num tickets."); + return -1; + } + return 0; +} + +PyDoc_STRVAR(PySSLContext_num_tickets_doc, +"Control the number of TLSv1.3 session tickets"); +#endif /* OpenSSL 1.1.1 */ + static PyObject * get_options(PySSLContext *self, void *c) { @@ -4654,6 +4687,10 @@ static PyGetSetDef context_getsetlist[] = { (setter) _PySSLContext_set_msg_callback, NULL}, {"sni_callback", (getter) get_sni_callback, (setter) set_sni_callback, PySSLContext_sni_callback_doc}, +#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) + {"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, -- 2.50.1