Skip to content

Commit 04d4542

Browse files
committed
1 parent 4fe54f4 commit 04d4542

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

Modules/_ssl.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ static void _PySSLFixErrno(void) {
167167
# define PY_OPENSSL_1_1_API 1
168168
#endif
169169

170+
#if (OPENSSL_VERSION_NUMBER >= 0x30300000L) && !defined(LIBRESSL_VERSION_NUMBER)
171+
# define OPENSSL_VERSION_3_3 1
172+
#endif
173+
170174
/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
171175
* This includes the SSL_set_SSL_CTX() function.
172176
*/
@@ -207,6 +211,16 @@ static void _PySSLFixErrno(void) {
207211
#define HAVE_OPENSSL_CRYPTO_LOCK
208212
#endif
209213

214+
/* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */
215+
#ifdef OPENSSL_VERSION_1_1
216+
#define HAVE_OPENSSL_X509_STORE_LOCK
217+
#endif
218+
219+
/* OpenSSL 3.3 added the X509_STORE_get1_objects API */
220+
#ifdef OPENSSL_VERSION_3_3
221+
#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
222+
#endif
223+
210224
#if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2)
211225
#define OPENSSL_NO_SSL2
212226
#endif
@@ -4517,6 +4531,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
45174531
#endif
45184532
}
45194533

4534+
/* Shim of X509_STORE_get1_objects API from OpenSSL 3.3
4535+
* Only available with the X509_STORE_lock() API */
4536+
#if defined(HAVE_OPENSSL_X509_STORE_LOCK) && !defined(OPENSSL_VERSION_3_3)
4537+
#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
4538+
4539+
static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj)
4540+
{
4541+
int ok;
4542+
X509_OBJECT *ret = X509_OBJECT_new();
4543+
if (ret == NULL) {
4544+
return NULL;
4545+
}
4546+
switch (X509_OBJECT_get_type(obj)) {
4547+
case X509_LU_X509:
4548+
ok = X509_OBJECT_set1_X509(ret, X509_OBJECT_get0_X509(obj));
4549+
break;
4550+
case X509_LU_CRL:
4551+
/* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/
4552+
ok = X509_OBJECT_set1_X509_CRL(
4553+
ret, X509_OBJECT_get0_X509_CRL((X509_OBJECT *)obj));
4554+
break;
4555+
default:
4556+
/* We cannot duplicate unrecognized types in a polyfill, but it is
4557+
* safe to leave an empty object. The caller will ignore it. */
4558+
ok = 1;
4559+
break;
4560+
}
4561+
if (!ok) {
4562+
X509_OBJECT_free(ret);
4563+
return NULL;
4564+
}
4565+
return ret;
4566+
}
4567+
4568+
static STACK_OF(X509_OBJECT) *
4569+
X509_STORE_get1_objects(X509_STORE *store)
4570+
{
4571+
STACK_OF(X509_OBJECT) *ret;
4572+
if (!X509_STORE_lock(store)) {
4573+
return NULL;
4574+
}
4575+
ret = sk_X509_OBJECT_deep_copy(X509_STORE_get0_objects(store),
4576+
x509_object_dup, X509_OBJECT_free);
4577+
X509_STORE_unlock(store);
4578+
return ret;
4579+
}
4580+
#endif
4581+
45204582
PyDoc_STRVAR(PySSLContext_sni_callback_doc,
45214583
"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
45224584
\n\
@@ -4546,7 +4608,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
45464608
int x509 = 0, crl = 0, ca = 0, i;
45474609

45484610
store = SSL_CTX_get_cert_store(self->ctx);
4611+
#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4612+
objs = X509_STORE_get1_objects(store);
4613+
if (objs == NULL) {
4614+
PyErr_SetString(PyExc_MemoryError, "failed to query cert store");
4615+
return NULL;
4616+
}
4617+
#else
45494618
objs = X509_STORE_get0_objects(store);
4619+
#endif
45504620
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
45514621
obj = sk_X509_OBJECT_value(objs, i);
45524622
switch (X509_OBJECT_get_type(obj)) {
@@ -4563,9 +4633,14 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
45634633
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
45644634
* As far as I can tell they are internal states and never
45654635
* stored in a cert store */
4636+
/* Ignore unrecognized types. */
45664637
break;
45674638
}
45684639
}
4640+
4641+
#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4642+
sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
4643+
#endif
45694644
return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl,
45704645
"x509_ca", ca);
45714646
}
@@ -4597,7 +4672,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
45974672
}
45984673

45994674
store = SSL_CTX_get_cert_store(self->ctx);
4675+
#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4676+
objs = X509_STORE_get1_objects(store);
4677+
if (objs == NULL) {
4678+
PyErr_SetString(PyExc_MemoryError, "failed to query cert store");
4679+
return NULL;
4680+
}
4681+
#else
46004682
objs = X509_STORE_get0_objects(store);
4683+
#endif
46014684
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
46024685
X509_OBJECT *obj;
46034686
X509 *cert;
@@ -4625,9 +4708,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
46254708
}
46264709
Py_CLEAR(ci);
46274710
}
4711+
#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4712+
sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
4713+
#endif
46284714
return rlist;
46294715

46304716
error:
4717+
#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4718+
sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
4719+
#endif
46314720
Py_XDECREF(ci);
46324721
Py_XDECREF(rlist);
46334722
return NULL;

0 commit comments

Comments
 (0)