Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions Doc/library/ssl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -982,14 +982,26 @@ Constants

.. data:: OPENSSL_VERSION_INFO

A tuple of five integers representing version information about the
OpenSSL library::
A named tuple of five integers representing version information about the
OpenSSL library loaded by the interpreter:
*major*, *minor*, *fix*, *patch* and *status*::

>>> ssl.OPENSSL_VERSION_INFO
(1, 0, 2, 11, 15)
ssl.OPENSSL_VERSION_INFO(major=3, minor=0, fix=0, patch=13, status=0)

.. versionadded:: 3.2

.. versionchanged:: next
It is now a named tuple.

.. data:: OPENSSL_API_VERSION_INFO

A named tuple containing the version of the OpenSSL library that was used
for building the module, with the same fields as :const:`OPENSSL_VERSION_INFO`.
This may be different from the OpenSSL library actually used at runtime.

.. versionadded:: next

.. data:: OPENSSL_VERSION_NUMBER

The raw version number of the OpenSSL library, as a single integer::
Expand Down
10 changes: 10 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,16 @@ sqlite3
(Contributed by Jiseok CHOI in :gh:`150449`.)


ssl
---

* :const:`ssl.OPENSSL_VERSION_INFO` is now a named tuple.
Added :const:`~ssl.OPENSSL_API_VERSION_INFO` which provides information
about the version of the OpenSSL library that was used for building
the module.
(Contributed by Serhiy Storchaka in :gh:`157513`.)


symtable
--------

Expand Down
1 change: 1 addition & 0 deletions Lib/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,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 OPENSSL_API_VERSION_INFO
from _ssl import _SSLContext, MemoryBIO, SSLSession
from _ssl import (
SSLError, SSLZeroReturnError, SSLWantReadError, SSLWantWriteError,
Expand Down
1 change: 1 addition & 0 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ def format_attr(attr, value):
attributes = (
'OPENSSL_VERSION',
'OPENSSL_VERSION_INFO',
'OPENSSL_API_VERSION_INFO',
'HAS_SNI',
'OP_ALL',
'OP_NO_TLSv1_1',
Expand Down
10 changes: 9 additions & 1 deletion Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ def test_parse_cert_CVE_2013_4238(self):
(('emailAddress', 'python-dev@python.org'),))
self.assertEqual(p['subject'], subject)
self.assertEqual(p['issuer'], subject)
if ssl._OPENSSL_API_VERSION >= (0, 9, 8):
if ssl.OPENSSL_API_VERSION_INFO >= (0, 9, 8):
san = (('DNS', 'altnull.python.org\x00example.com'),
('email', 'null@python.org\x00user@example.org'),
('URI', 'http://null.python.org\x00http://example.org'),
Expand Down Expand Up @@ -599,6 +599,14 @@ def test_openssl_version(self):
self.assertIsInstance(n, int)
self.assertIsInstance(t, tuple)
self.assertIsInstance(s, str)
self.assertEqual(len(t), 5)
self.assertEqual(t, (t.major, t.minor, t.fix, t.patch, t.status))
a = ssl.OPENSSL_API_VERSION_INFO
self.assertIsInstance(a, tuple)
self.assertEqual(len(a), 5)
self.assertEqual(a, (a.major, a.minor, a.fix, a.patch, a.status))
self.assertIs(ssl._OPENSSL_API_VERSION, a)
self.assertEqual(a.major, t.major)
# Some sanity checks follow
# >= 1.1.1
self.assertGreaterEqual(n, 0x10101000)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:const:`ssl.OPENSSL_VERSION_INFO` is now a named tuple.
Add :const:`ssl.OPENSSL_API_VERSION_INFO` which provides information about
the version of the OpenSSL library that was used for building the module.
83 changes: 73 additions & 10 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -7242,12 +7242,62 @@ parse_openssl_version(unsigned long libver,
*major = libver & 0xFF;
}

PyDoc_STRVAR(openssl_version_info__doc__,
"ssl.OPENSSL_VERSION_INFO\n\
\n\
OpenSSL version information as a named tuple.");

static PyStructSequence_Field openssl_version_info_fields[] = {
{"major", "Major release number"},
{"minor", "Minor release number"},
{"fix", "Fix release number"},
Comment thread
picnixz marked this conversation as resolved.
{"patch", "Patch release number"},
{"status", "Release status"},
{0}
};

static PyStructSequence_Desc openssl_version_info_desc = {
"ssl.OPENSSL_VERSION_INFO", /* name */
openssl_version_info__doc__, /* doc */
openssl_version_info_fields, /* fields */
5
};

static PyObject *
make_openssl_version_info(PyTypeObject *type, unsigned long libver)
{
PyObject *version;
int pos = 0;
unsigned int major, minor, fix, patch, status;

parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
version = PyStructSequence_New(type);
if (version == NULL) {
return NULL;
}

#define SetItem(VALUE) \
PyStructSequence_SET_ITEM(version, pos++, VALUE); \
if (PyErr_Occurred()) { \
Py_DECREF(version); \
return NULL; \
}

SetItem(PyLong_FromUnsignedLong(major))
SetItem(PyLong_FromUnsignedLong(minor))
SetItem(PyLong_FromUnsignedLong(fix))
SetItem(PyLong_FromUnsignedLong(patch))
SetItem(PyLong_FromUnsignedLong(status))
#undef SetItem

return version;
}

static int
sslmodule_init_versioninfo(PyObject *m)
{
PyObject *r;
unsigned long libver;
unsigned int major, minor, fix, patch, status;

/* OpenSSL version */
/* SSLeay() gives us the version of the library linked against,
Expand All @@ -7258,20 +7308,33 @@ sslmodule_init_versioninfo(PyObject *m)
if (PyModule_Add(m, "OPENSSL_VERSION_NUMBER", r) < 0)
return -1;

parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
if (PyModule_Add(m, "OPENSSL_VERSION_INFO", r) < 0)
return -1;

r = PyUnicode_FromString(OpenSSL_version(OPENSSL_VERSION));
if (PyModule_Add(m, "OPENSSL_VERSION", r) < 0)
return -1;

libver = OPENSSL_VERSION_NUMBER;
parse_openssl_version(libver, &major, &minor, &fix, &patch, &status);
r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
if (PyModule_Add(m, "_OPENSSL_API_VERSION", r) < 0)
PyTypeObject *version_type;
version_type = PyStructSequence_NewType(&openssl_version_info_desc);
if (version_type == NULL) {
return -1;
}
if (PyModule_Add(m, "OPENSSL_VERSION_INFO",
make_openssl_version_info(version_type, libver)) < 0)
{
Py_DECREF(version_type);
return -1;
}
r = make_openssl_version_info(version_type, OPENSSL_VERSION_NUMBER);
Py_DECREF(version_type);
if (r == NULL) {
return -1;
}
if (PyModule_AddObjectRef(m, "OPENSSL_API_VERSION_INFO", r) < 0 ||
PyModule_AddObjectRef(m, "_OPENSSL_API_VERSION", r) < 0)
{
Py_DECREF(r);
return -1;
}
Py_DECREF(r);

return 0;
}
Expand Down
Loading