@@ -167,6 +167,10 @@ static void _PySSLFixErrno(void) {
167
167
# define PY_OPENSSL_1_1_API 1
168
168
#endif
169
169
170
+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
171
+ # define OPENSSL_VERSION_3_3 1
172
+ #endif
173
+
170
174
/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
171
175
* This includes the SSL_set_SSL_CTX() function.
172
176
*/
@@ -207,6 +211,16 @@ static void _PySSLFixErrno(void) {
207
211
#define HAVE_OPENSSL_CRYPTO_LOCK
208
212
#endif
209
213
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
+
210
224
#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
211
225
#define OPENSSL_NO_SSL2
212
226
#endif
@@ -4517,6 +4531,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
4517
4531
#endif
4518
4532
}
4519
4533
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
+
4520
4582
PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
4521
4583
"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
4522
4584
\n\
@@ -4546,7 +4608,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
4546
4608
int x509 = 0 , crl = 0 , ca = 0 , i ;
4547
4609
4548
4610
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
4549
4618
objs = X509_STORE_get0_objects (store );
4619
+ #endif
4550
4620
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
4551
4621
obj = sk_X509_OBJECT_value (objs , i );
4552
4622
switch (X509_OBJECT_get_type (obj )) {
@@ -4563,9 +4633,14 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
4563
4633
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
4564
4634
* As far as I can tell they are internal states and never
4565
4635
* stored in a cert store */
4636
+ /* Ignore unrecognized types. */
4566
4637
break ;
4567
4638
}
4568
4639
}
4640
+
4641
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4642
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4643
+ #endif
4569
4644
return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
4570
4645
"x509_ca" , ca );
4571
4646
}
@@ -4597,7 +4672,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
4597
4672
}
4598
4673
4599
4674
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
4600
4682
objs = X509_STORE_get0_objects (store );
4683
+ #endif
4601
4684
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
4602
4685
X509_OBJECT * obj ;
4603
4686
X509 * cert ;
@@ -4625,9 +4708,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
4625
4708
}
4626
4709
Py_CLEAR (ci );
4627
4710
}
4711
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4712
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4713
+ #endif
4628
4714
return rlist ;
4629
4715
4630
4716
error :
4717
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4718
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4719
+ #endif
4631
4720
Py_XDECREF (ci );
4632
4721
Py_XDECREF (rlist );
4633
4722
return NULL ;
0 commit comments