Index: Doc/library/ssl.rst =================================================================== --- Doc/library/ssl.rst (révision 79811) +++ Doc/library/ssl.rst (copie de travail) @@ -240,7 +240,37 @@ 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 ----------------- Index: Lib/ssl.py =================================================================== --- Lib/ssl.py (révision 79811) +++ Lib/ssl.py (copie de travail) @@ -59,6 +59,7 @@ 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 Index: Lib/test/test_ssl.py =================================================================== --- Lib/test/test_ssl.py (révision 79811) +++ Lib/test/test_ssl.py (copie de travail) @@ -110,6 +110,34 @@ 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): Index: Modules/_ssl.c =================================================================== --- Modules/_ssl.c (révision 79811) +++ Modules/_ssl.c (copie de travail) @@ -1574,7 +1574,9 @@ 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 @@ 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; }