summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-04-05 21:35:07 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-04-05 21:35:07 (GMT)
commitf9de534c218cfdab5b4114e6ed535c940ae6b8b5 (patch)
tree176bd640ca6f0c8d17f0a2644fcd734bc44d8580
parentfce1d31d4710c0280e2b646f72174de79a713430 (diff)
downloadcpython-f9de534c218cfdab5b4114e6ed535c940ae6b8b5.zip
cpython-f9de534c218cfdab5b4114e6ed535c940ae6b8b5.tar.gz
cpython-f9de534c218cfdab5b4114e6ed535c940ae6b8b5.tar.bz2
Issue #8321: Give access to OpenSSL version numbers from the `ssl` module,
using the new attributes `ssl.OPENSSL_VERSION`, `ssl.OPENSSL_VERSION_INFO` and `ssl.OPENSSL_VERSION_NUMBER`.
-rw-r--r--Doc/library/ssl.rst30
-rw-r--r--Lib/ssl.py1
-rw-r--r--Lib/test/test_ssl.py28
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/_ssl.c30
5 files changed, 92 insertions, 1 deletions
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index a4f911f..5d8ca3c 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -240,6 +240,36 @@ Functions, Constants, and Exceptions
modern version, and probably the best choice for maximum protection, if both
sides can speak it.
+.. data:: OPENSSL_VERSION
+
+ The version string of the OpenSSL library loaded by the interpreter::
+
+ >>> ssl.OPENSSL_VERSION
+ 'OpenSSL 0.9.8k 25 Mar 2009'
+
+ .. versionadded:: 2.7
+
+.. data:: OPENSSL_VERSION_INFO
+
+ A tuple of five integers representing version information about the
+ OpenSSL library::
+
+ >>> ssl.OPENSSL_VERSION_INFO
+ (0, 9, 8, 11, 15)
+
+ .. versionadded:: 2.7
+
+.. data:: OPENSSL_VERSION_NUMBER
+
+ The raw version number of the OpenSSL library, as a single integer::
+
+ >>> ssl.OPENSSL_VERSION_NUMBER
+ 9470143L
+ >>> hex(ssl.OPENSSL_VERSION_NUMBER)
+ '0x9080bfL'
+
+ .. versionadded:: 2.7
+
SSLSocket Objects
-----------------
diff --git a/Lib/ssl.py b/Lib/ssl.py
index 21664b9..cd1d865 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -59,6 +59,7 @@ import textwrap
import _ssl # if we can't import it, let the error propagate
+from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION
from _ssl import SSLError
from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index f299d36..0f9822a 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -110,6 +110,34 @@ class BasicTests(unittest.TestCase):
if (d1 != d2):
raise test_support.TestFailed("PEM-to-DER or DER-to-PEM translation failed")
+ def test_openssl_version(self):
+ n = ssl.OPENSSL_VERSION_NUMBER
+ t = ssl.OPENSSL_VERSION_INFO
+ s = ssl.OPENSSL_VERSION
+ self.assertIsInstance(n, (int, long))
+ self.assertIsInstance(t, tuple)
+ self.assertIsInstance(s, str)
+ # Some sanity checks follow
+ # >= 0.9
+ self.assertGreaterEqual(n, 0x900000)
+ # < 2.0
+ self.assertLess(n, 0x20000000)
+ major, minor, fix, patch, status = t
+ self.assertGreaterEqual(major, 0)
+ self.assertLess(major, 2)
+ self.assertGreaterEqual(minor, 0)
+ self.assertLess(minor, 256)
+ self.assertGreaterEqual(fix, 0)
+ self.assertLess(fix, 256)
+ self.assertGreaterEqual(patch, 0)
+ self.assertLessEqual(patch, 26)
+ self.assertGreaterEqual(status, 0)
+ self.assertLessEqual(status, 15)
+ # Version string as returned by OpenSSL, the format might change
+ self.assertTrue(s.startswith("OpenSSL {:d}.{:d}.{:d}".format(major, minor, fix)),
+ (s, t))
+
+
class NetworkedTests(unittest.TestCase):
def testConnect(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index 0ee0c07..6c9e55d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -49,6 +49,10 @@ Core and Builtins
Library
-------
+- Issue #8321: Give access to OpenSSL version numbers from the `ssl` module,
+ using the new attributes `ssl.OPENSSL_VERSION`, `ssl.OPENSSL_VERSION_INFO`
+ and `ssl.OPENSSL_VERSION_NUMBER`.
+
- Issue #8310: Allow dis to examine new style classes.
- Issue #8257: The Decimal construct now accepts a float instance
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 52fdf0f..6befbef 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1574,7 +1574,9 @@ for documentation.");
PyMODINIT_FUNC
init_ssl(void)
{
- PyObject *m, *d;
+ PyObject *m, *d, *r;
+ unsigned long libver;
+ unsigned int major, minor, fix, patch, status;
Py_TYPE(&PySSL_Type) = &PyType_Type;
@@ -1644,4 +1646,30 @@ init_ssl(void)
PY_SSL_VERSION_SSL23);
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1",
PY_SSL_VERSION_TLS1);
+
+ /* OpenSSL version */
+ /* SSLeay() gives us the version of the library linked against,
+ which could be different from the headers version.
+ */
+ libver = SSLeay();
+ r = PyLong_FromUnsignedLong(libver);
+ if (r == NULL)
+ return;
+ if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r))
+ return;
+ status = libver & 0xF;
+ libver >>= 4;
+ patch = libver & 0xFF;
+ libver >>= 8;
+ fix = libver & 0xFF;
+ libver >>= 8;
+ minor = libver & 0xFF;
+ libver >>= 8;
+ major = libver & 0xFF;
+ r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
+ if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r))
+ return;
+ r = PyString_FromString(SSLeay_version(SSLEAY_VERSION));
+ if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r))
+ return;
}