From 8e836bb21ce73f0794fd769db5883c29680dfe47 Mon Sep 17 00:00:00 2001 From: matthewhughes934 <34972397+matthewhughes934@users.noreply.github.com> Date: Fri, 17 Jul 2020 09:59:15 +0100 Subject: bpo-41195: Add getter for Openssl security level (GH-21282) Add an accessor under SSLContext.security_level as a wrapper around SSL_CTX_get_security_level, see: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_get_security_level.html ------ This is my first time contributing, so please pull me up on all the things I missed or did incorrectly. Automerge-Triggered-By: @tiran --- Doc/library/ssl.rst | 10 ++++++++++ Lib/test/test_ssl.py | 19 +++++++++++++++++++ .../Library/2020-07-02-15-03-04.bpo-41195.cEnpO3.rst | 2 ++ Modules/_ssl.c | 13 +++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-07-02-15-03-04.bpo-41195.cEnpO3.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 852091c..1cfd165 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2032,6 +2032,16 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.7 +.. attribute:: SSLContext.security_level + + An integer representing the `security level + `_ + for the context. This attribute is read-only. + + .. availability:: OpenSSL 1.1.0 or newer + + .. versionadded:: 3.10 + .. attribute:: SSLContext.verify_flags The flags for certificate verification operations. You can set flags like diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index ecb6049..de778d3 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1270,6 +1270,25 @@ class ContextTests(unittest.TestCase): ctx.maximum_version = ssl.TLSVersion.TLSv1 + @unittest.skipUnless( + hasattr(ssl.SSLContext, 'security_level'), + "requires OpenSSL >= 1.1.0" + ) + def test_security_level(self): + ctx = ssl.SSLContext() + # The default security callback allows for levels between 0-5 + # with OpenSSL defaulting to 1, however some vendors override the + # default value (e.g. Debian defaults to 2) + security_level_range = { + 0, + 1, # OpenSSL default + 2, # Debian + 3, + 4, + 5, + } + self.assertIn(ctx.security_level, security_level_range) + @unittest.skipUnless(have_verify_flags(), "verify_flags need OpenSSL > 0.9.8") def test_verify_flags(self): diff --git a/Misc/NEWS.d/next/Library/2020-07-02-15-03-04.bpo-41195.cEnpO3.rst b/Misc/NEWS.d/next/Library/2020-07-02-15-03-04.bpo-41195.cEnpO3.rst new file mode 100644 index 0000000..f96d5fa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-02-15-03-04.bpo-41195.cEnpO3.rst @@ -0,0 +1,2 @@ +Add read-only ssl.SSLContext.security_level attribute to retrieve the +context's security level. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index a8c339d..55a95dd 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3746,6 +3746,15 @@ PyDoc_STRVAR(PySSLContext_num_tickets_doc, "Control the number of TLSv1.3 session tickets"); #endif /* OpenSSL 1.1.1 */ +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) +static PyObject * +get_security_level(PySSLContext *self, void *c) +{ + return PyLong_FromLong(SSL_CTX_get_security_level(self->ctx)); +} +PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level"); +#endif /* OpenSSL 1.1.0 */ + static PyObject * get_options(PySSLContext *self, void *c) { @@ -4793,6 +4802,10 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_verify_flags, NULL}, {"verify_mode", (getter) get_verify_mode, (setter) set_verify_mode, NULL}, +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) + {"security_level", (getter) get_security_level, + NULL, PySSLContext_security_level_doc}, +#endif {NULL}, /* sentinel */ }; -- cgit v0.12