@@ -106,6 +106,10 @@ struct py_ssl_library_code {
106
106
# define PY_OPENSSL_1_1_API 1
107
107
#endif
108
108
109
+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
110
+ # define OPENSSL_VERSION_3_3 1
111
+ #endif
112
+
109
113
/* LibreSSL 2.7.0 provides necessary OpenSSL 1.1.0 APIs */
110
114
#if defined(LIBRESSL_VERSION_NUMBER ) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL
111
115
# define PY_OPENSSL_1_1_API 1
@@ -161,6 +165,16 @@ struct py_ssl_library_code {
161
165
#define HAVE_OPENSSL_CRYPTO_LOCK
162
166
#endif
163
167
168
+ /* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */
169
+ #ifdef OPENSSL_VERSION_1_1
170
+ #define HAVE_OPENSSL_X509_STORE_LOCK
171
+ #endif
172
+
173
+ /* OpenSSL 3.3 added the X509_STORE_get1_objects API */
174
+ #ifdef OPENSSL_VERSION_3_3
175
+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
176
+ #endif
177
+
164
178
#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
165
179
#define OPENSSL_NO_SSL2
166
180
#endif
@@ -3504,7 +3518,15 @@ cert_store_stats(PySSLContext *self)
3504
3518
int x509 = 0 , crl = 0 , ca = 0 , i ;
3505
3519
3506
3520
store = SSL_CTX_get_cert_store (self -> ctx );
3507
- objs = X509_STORE_get0_objects (store );
3521
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
3522
+ objs = X509_STORE_get1_objects (store );
3523
+ if (objs == NULL ) {
3524
+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
3525
+ return NULL ;
3526
+ }
3527
+ #else
3528
+ objs = X509_STORE_get0_objects (store );
3529
+ #endif
3508
3530
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
3509
3531
obj = sk_X509_OBJECT_value (objs , i );
3510
3532
switch (X509_OBJECT_get_type (obj )) {
@@ -3521,9 +3543,15 @@ cert_store_stats(PySSLContext *self)
3521
3543
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
3522
3544
* As far as I can tell they are internal states and never
3523
3545
* stored in a cert store */
3546
+ /* Ignore enrecognized types */
3524
3547
break ;
3525
3548
}
3526
3549
}
3550
+
3551
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
3552
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
3553
+ #endif
3554
+
3527
3555
return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
3528
3556
"x509_ca" , ca );
3529
3557
}
@@ -3558,9 +3586,16 @@ get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds)
3558
3586
if ((rlist = PyList_New (0 )) == NULL ) {
3559
3587
return NULL ;
3560
3588
}
3561
-
3562
3589
store = SSL_CTX_get_cert_store (self -> ctx );
3590
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
3591
+ objs = X509_STORE_get1_objects (store );
3592
+ if (objs == NULL ) {
3593
+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
3594
+ return NULL ;
3595
+ }
3596
+ #else
3563
3597
objs = X509_STORE_get0_objects (store );
3598
+ #endif
3564
3599
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
3565
3600
X509_OBJECT * obj ;
3566
3601
X509 * cert ;
@@ -3588,9 +3623,15 @@ get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwds)
3588
3623
}
3589
3624
Py_CLEAR (ci );
3590
3625
}
3626
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
3627
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
3628
+ #endif
3591
3629
return rlist ;
3592
3630
3593
3631
error :
3632
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
3633
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
3634
+ #endif
3594
3635
Py_XDECREF (ci );
3595
3636
Py_XDECREF (rlist );
3596
3637
return NULL ;
@@ -4642,3 +4683,51 @@ init_ssl(void)
4642
4683
return ;
4643
4684
}
4644
4685
4686
+ /* Shim of X509_STORE_get1_objects API from OpenSSL 3.3
4687
+ * Only available with the X509_STORE_lock() API */
4688
+ #if defined(HAVE_OPENSSL_X509_STORE_LOCK ) && !defined(OPENSSL_VERSION_3_3 )
4689
+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
4690
+
4691
+ static X509_OBJECT * x509_object_dup (const X509_OBJECT * obj )
4692
+ {
4693
+ int ok ;
4694
+ X509_OBJECT * ret = X509_OBJECT_new ();
4695
+ if (ret == NULL ) {
4696
+ return NULL ;
4697
+ }
4698
+ switch (X509_OBJECT_get_type (obj )) {
4699
+ case X509_LU_X509 :
4700
+ ok = X509_OBJECT_set1_X509 (ret , X509_OBJECT_get0_X509 (obj ));
4701
+ break ;
4702
+ case X509_LU_CRL :
4703
+ /* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/
4704
+ ok = X509_OBJECT_set1_X509_CRL (
4705
+ ret , X509_OBJECT_get0_X509_CRL ((X509_OBJECT * )obj ));
4706
+ break ;
4707
+ default :
4708
+ /* We cannot duplicate unrecognized types in a polyfill, but it is
4709
+ * safe to leave an empty object. The caller will ignore it. */
4710
+ ok = 1 ;
4711
+ break ;
4712
+ }
4713
+ if (!ok ) {
4714
+ X509_OBJECT_free (ret );
4715
+ return NULL ;
4716
+ }
4717
+ return ret ;
4718
+ }
4719
+
4720
+ static STACK_OF (X509_OBJECT ) *
4721
+ X509_STORE_get1_objects (X509_STORE * store )
4722
+ {
4723
+ STACK_OF (X509_OBJECT ) * ret ;
4724
+ if (!X509_STORE_lock (store )) {
4725
+ return NULL ;
4726
+ }
4727
+ ret = sk_X509_OBJECT_deep_copy (X509_STORE_get0_objects (store ),
4728
+ x509_object_dup , X509_OBJECT_free );
4729
+ X509_STORE_unlock (store );
4730
+ return ret ;
4731
+ }
4732
+ #endif
4733
+
0 commit comments