Skip to content

Commit 9c0ff17

Browse files
bpo-30008: Fix OpenSSL no-deprecated compilation (GH-20397)
Fix :mod:`ssl`` code to be compatible with OpenSSL 1.1.x builds that use ``no-deprecated`` and ``--api=1.1.0``. Note: Tests assume full OpenSSL API and fail with limited API. Signed-off-by: Christian Heimes <[email protected]> Co-authored-by: Mark Wright <[email protected]> (cherry picked from commit a871f69) Co-authored-by: Christian Heimes <[email protected]>
1 parent ba1c2c8 commit 9c0ff17

File tree

3 files changed

+48
-11
lines changed

3 files changed

+48
-11
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :mod:`ssl` code to be compatible with OpenSSL 1.1.x builds that use
2+
``no-deprecated`` and ``--api=1.1.0``.

Modules/_ssl.c

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,24 @@ static void _PySSLFixErrno(void) {
144144
# define PY_OPENSSL_1_1_API 1
145145
#endif
146146

147+
/* OpenSSL API compat */
148+
#ifdef OPENSSL_API_COMPAT
149+
#if OPENSSL_API_COMPAT >= 0x10100000L
150+
151+
/* OpenSSL API 1.1.0+ does not include version methods */
152+
#ifndef OPENSSL_NO_TLS1_METHOD
153+
#define OPENSSL_NO_TLS1_METHOD 1
154+
#endif
155+
#ifndef OPENSSL_NO_TLS1_1_METHOD
156+
#define OPENSSL_NO_TLS1_1_METHOD 1
157+
#endif
158+
#ifndef OPENSSL_NO_TLS1_2_METHOD
159+
#define OPENSSL_NO_TLS1_2_METHOD 1
160+
#endif
161+
162+
#endif /* >= 1.1.0 compcat */
163+
#endif /* OPENSSL_API_COMPAT */
164+
147165
/* LibreSSL 2.7.0 provides necessary OpenSSL 1.1.0 APIs */
148166
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL
149167
# define PY_OPENSSL_1_1_API 1
@@ -203,6 +221,12 @@ static void _PySSLFixErrno(void) {
203221
#define TLS_method SSLv23_method
204222
#define TLS_client_method SSLv23_client_method
205223
#define TLS_server_method SSLv23_server_method
224+
#define ASN1_STRING_get0_data ASN1_STRING_data
225+
#define X509_get0_notBefore X509_get_notBefore
226+
#define X509_get0_notAfter X509_get_notAfter
227+
#define OpenSSL_version_num SSLeay
228+
#define OpenSSL_version SSLeay_version
229+
#define OPENSSL_VERSION SSLEAY_VERSION
206230

207231
static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
208232
{
@@ -887,7 +911,7 @@ _ssl_configure_hostname(PySSLSocket *self, const char* server_hostname)
887911
goto error;
888912
}
889913
} else {
890-
if (!X509_VERIFY_PARAM_set1_ip(param, ASN1_STRING_data(ip),
914+
if (!X509_VERIFY_PARAM_set1_ip(param, ASN1_STRING_get0_data(ip),
891915
ASN1_STRING_length(ip))) {
892916
_setSSLError(NULL, 0, __FILE__, __LINE__);
893917
goto error;
@@ -1363,7 +1387,7 @@ _get_peer_alt_names (X509 *certificate) {
13631387
goto fail;
13641388
}
13651389
PyTuple_SET_ITEM(t, 0, v);
1366-
v = PyUnicode_FromStringAndSize((char *)ASN1_STRING_data(as),
1390+
v = PyUnicode_FromStringAndSize((char *)ASN1_STRING_get0_data(as),
13671391
ASN1_STRING_length(as));
13681392
if (v == NULL) {
13691393
Py_DECREF(t);
@@ -1659,7 +1683,7 @@ _decode_certificate(X509 *certificate) {
16591683
ASN1_INTEGER *serialNumber;
16601684
char buf[2048];
16611685
int len, result;
1662-
ASN1_TIME *notBefore, *notAfter;
1686+
const ASN1_TIME *notBefore, *notAfter;
16631687
PyObject *pnotBefore, *pnotAfter;
16641688

16651689
retval = PyDict_New();
@@ -1721,7 +1745,7 @@ _decode_certificate(X509 *certificate) {
17211745
Py_DECREF(sn_obj);
17221746

17231747
(void) BIO_reset(biobuf);
1724-
notBefore = X509_get_notBefore(certificate);
1748+
notBefore = X509_get0_notBefore(certificate);
17251749
ASN1_TIME_print(biobuf, notBefore);
17261750
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
17271751
if (len < 0) {
@@ -1738,7 +1762,7 @@ _decode_certificate(X509 *certificate) {
17381762
Py_DECREF(pnotBefore);
17391763

17401764
(void) BIO_reset(biobuf);
1741-
notAfter = X509_get_notAfter(certificate);
1765+
notAfter = X509_get0_notAfter(certificate);
17421766
ASN1_TIME_print(biobuf, notAfter);
17431767
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
17441768
if (len < 0) {
@@ -3081,17 +3105,23 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
30813105
ctx = SSL_CTX_new(SSLv3_method());
30823106
break;
30833107
#endif
3084-
#if defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1)
3108+
#if (defined(TLS1_VERSION) && \
3109+
!defined(OPENSSL_NO_TLS1) && \
3110+
!defined(OPENSSL_NO_TLS1_METHOD))
30853111
case PY_SSL_VERSION_TLS1:
30863112
ctx = SSL_CTX_new(TLSv1_method());
30873113
break;
30883114
#endif
3089-
#if defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1)
3115+
#if (defined(TLS1_1_VERSION) && \
3116+
!defined(OPENSSL_NO_TLS1_1) && \
3117+
!defined(OPENSSL_NO_TLS1_1_METHOD))
30903118
case PY_SSL_VERSION_TLS1_1:
30913119
ctx = SSL_CTX_new(TLSv1_1_method());
30923120
break;
30933121
#endif
3094-
#if defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2)
3122+
#if (defined(TLS1_2_VERSION) && \
3123+
!defined(OPENSSL_NO_TLS1_2) && \
3124+
!defined(OPENSSL_NO_TLS1_2_METHOD))
30953125
case PY_SSL_VERSION_TLS1_2:
30963126
ctx = SSL_CTX_new(TLSv1_2_method());
30973127
break;
@@ -3209,7 +3239,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
32093239
conservative and assume it wasn't fixed until release. We do this check
32103240
at runtime to avoid problems from the dynamic linker.
32113241
See #25672 for more on this. */
3212-
libver = SSLeay();
3242+
libver = OpenSSL_version_num();
32133243
if (!(libver >= 0x10001000UL && libver < 0x1000108fUL) &&
32143244
!(libver >= 0x10000000UL && libver < 0x100000dfUL)) {
32153245
SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
@@ -5289,7 +5319,11 @@ PySSL_RAND(int len, int pseudo)
52895319
if (bytes == NULL)
52905320
return NULL;
52915321
if (pseudo) {
5322+
#ifdef PY_OPENSSL_1_1_API
5323+
ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
5324+
#else
52925325
ok = RAND_pseudo_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
5326+
#endif
52935327
if (ok == 0 || ok == 1)
52945328
return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False);
52955329
}
@@ -6376,7 +6410,7 @@ PyInit__ssl(void)
63766410
/* SSLeay() gives us the version of the library linked against,
63776411
which could be different from the headers version.
63786412
*/
6379-
libver = SSLeay();
6413+
libver = OpenSSL_version_num();
63806414
r = PyLong_FromUnsignedLong(libver);
63816415
if (r == NULL)
63826416
return NULL;
@@ -6386,7 +6420,7 @@ PyInit__ssl(void)
63866420
r = Py_BuildValue("IIIII", major, minor, fix, patch, status);
63876421
if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r))
63886422
return NULL;
6389-
r = PyUnicode_FromString(SSLeay_version(SSLEAY_VERSION));
6423+
r = PyUnicode_FromString(OpenSSL_version(OPENSSL_VERSION));
63906424
if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r))
63916425
return NULL;
63926426

Tools/ssl/multissltests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ def _build_src(self):
314314
"shared", "--debug",
315315
"--prefix={}".format(self.install_dir)
316316
]
317+
# cmd.extend(["no-deprecated", "--api=1.1.0"])
317318
env = os.environ.copy()
318319
# set rpath
319320
env["LD_RUN_PATH"] = self.lib_dir

0 commit comments

Comments
 (0)