diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 73d3e3bbcdaeb8..e71d5d1f10258e 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1097,6 +1097,7 @@ def test_min_max_version(self): ctx.maximum_version, {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3} ) + ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED self.assertIn( @@ -1104,6 +1105,23 @@ def test_min_max_version(self): {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3} ) + with self.assertRaises(ValueError): + ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + + ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + + with self.assertRaises(ValueError): + ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED + + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + with self.assertRaises(ValueError): ctx.minimum_version = 42 @@ -3572,8 +3590,8 @@ def test_min_max_version(self): self.assertEqual(s.version(), 'TLSv1.1') # client 1.0, server 1.2 (mismatch) - server_context.minimum_version = ssl.TLSVersion.TLSv1_2 server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + server_context.minimum_version = ssl.TLSVersion.TLSv1_2 client_context.minimum_version = ssl.TLSVersion.TLSv1 client_context.maximum_version = ssl.TLSVersion.TLSv1 with ThreadedEchoServer(context=server_context) as server: diff --git a/Misc/NEWS.d/next/Library/2018-07-02-18-22-19.bpo-34001.e5KBtP.rst b/Misc/NEWS.d/next/Library/2018-07-02-18-22-19.bpo-34001.e5KBtP.rst new file mode 100644 index 00000000000000..bfe937aec0fce5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-07-02-18-22-19.bpo-34001.e5KBtP.rst @@ -0,0 +1,2 @@ +Add checks for protocol version bounds when the ssl module is built using +LibreSSL. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 2bce4816d26fe7..027ebf60380b98 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3383,7 +3383,11 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c) static int set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) { + long min; + long max; long v; + long prev; + long new; int result; if (!PyArg_Parse(arg, "l", &v)) @@ -3408,6 +3412,7 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) } if (what == 0) { + /* set_minimum_version */ switch(v) { case PY_PROTO_MINIMUM_SUPPORTED: v = 0; @@ -3419,9 +3424,31 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) default: break; } + max = SSL_CTX_get_max_proto_version(self->ctx); + if(v > PY_PROTO_MAXIMUM_AVAILABLE || + (max != 0 && v > max)) { + PyErr_SetString( + PyExc_ValueError, + "SSLContext.minimum_version cannot be greater than " + "SSLContext.maximum_version." + ); + return -1; + } + prev = SSL_CTX_get_min_proto_version(self->ctx); result = SSL_CTX_set_min_proto_version(self->ctx, v); + new = SSL_CTX_get_min_proto_version(self->ctx); +#if defined(LIBRESSL_VERSION_NUMBER) + if((v != 0 && v != new) || + (v == 0 && PY_PROTO_MINIMUM_AVAILABLE != new)) { + PyErr_Format(PyExc_ValueError, + "Unsupported protocol version 0x%x", v); + SSL_CTX_set_min_proto_version(self->ctx, prev); + return -1; + } +#endif } else { + /* set_maximum_version */ switch(v) { case PY_PROTO_MAXIMUM_SUPPORTED: v = 0; @@ -3433,7 +3460,28 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) default: break; } + min = SSL_CTX_get_min_proto_version(self->ctx); + if(v != 0 && (v < PY_PROTO_MINIMUM_AVAILABLE || + (min != 0 && v < min))) { + PyErr_SetString( + PyExc_ValueError, + "SSLContext.minimum_version cannot be greater than " + "SSLContext.maximum_version." + ); + return -1; + } + prev = SSL_CTX_get_max_proto_version(self->ctx); result = SSL_CTX_set_max_proto_version(self->ctx, v); + new = SSL_CTX_get_max_proto_version(self->ctx); +#if defined(LIBRESSL_VERSION_NUMBER) + if((v != 0 && v != SSL_CTX_get_max_proto_version(self->ctx)) || + (v == 0 && PY_PROTO_MAXIMUM_AVAILABLE != SSL_CTX_get_max_proto_version(self->ctx))) { + PyErr_Format(PyExc_ValueError, + "Unsupported protocol version 0x%x", v); + result = SSL_CTX_set_max_proto_version(self->ctx, prev); + return -1; + } +#endif } if (result == 0) { PyErr_Format(PyExc_ValueError,