diff -r 3280d012eb11 Lib/ssl.py --- a/Lib/ssl.py Mon Apr 05 21:04:23 2010 +0200 +++ b/Lib/ssl.py Mon Apr 05 22:42:01 2010 +0200 @@ -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 -r 3280d012eb11 Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py Mon Apr 05 21:04:23 2010 +0200 +++ b/Lib/test/test_ssl.py Mon Apr 05 22:42:01 2010 +0200 @@ -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 -r 3280d012eb11 Modules/_ssl.c --- a/Modules/_ssl.c Mon Apr 05 21:04:23 2010 +0200 +++ b/Modules/_ssl.c Mon Apr 05 22:42:01 2010 +0200 @@ -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; }