@@ -166,6 +166,10 @@ extern const SSL_METHOD *TLSv1_2_method(void);
166
166
# define PY_OPENSSL_1_1_API 1
167
167
#endif
168
168
169
+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
170
+ # define OPENSSL_VERSION_3_3 1
171
+ #endif
172
+
169
173
/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
170
174
* This includes the SSL_set_SSL_CTX() function.
171
175
*/
@@ -210,6 +214,16 @@ extern const SSL_METHOD *TLSv1_2_method(void);
210
214
#define HAVE_OPENSSL_CRYPTO_LOCK
211
215
#endif
212
216
217
+ /* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */
218
+ #ifdef OPENSSL_VERSION_1_1
219
+ #define HAVE_OPENSSL_X509_STORE_LOCK
220
+ #endif
221
+
222
+ /* OpenSSL 3.3 added the X509_STORE_get1_objects API */
223
+ #ifdef OPENSSL_VERSION_3_3
224
+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
225
+ #endif
226
+
213
227
#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
214
228
#define OPENSSL_NO_SSL2
215
229
#endif
@@ -4675,6 +4689,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
4675
4689
#endif
4676
4690
}
4677
4691
4692
+ /* Shim of X509_STORE_get1_objects API from OpenSSL 3.3
4693
+ * Only available with the X509_STORE_lock() API */
4694
+ #if defined(HAVE_OPENSSL_X509_STORE_LOCK ) && !defined(OPENSSL_VERSION_3_3 )
4695
+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
4696
+
4697
+ static X509_OBJECT * x509_object_dup (const X509_OBJECT * obj )
4698
+ {
4699
+ int ok ;
4700
+ X509_OBJECT * ret = X509_OBJECT_new ();
4701
+ if (ret == NULL ) {
4702
+ return NULL ;
4703
+ }
4704
+ switch (X509_OBJECT_get_type (obj )) {
4705
+ case X509_LU_X509 :
4706
+ ok = X509_OBJECT_set1_X509 (ret , X509_OBJECT_get0_X509 (obj ));
4707
+ break ;
4708
+ case X509_LU_CRL :
4709
+ /* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/
4710
+ ok = X509_OBJECT_set1_X509_CRL (
4711
+ ret , X509_OBJECT_get0_X509_CRL ((X509_OBJECT * )obj ));
4712
+ break ;
4713
+ default :
4714
+ /* We cannot duplicate unrecognized types in a polyfill, but it is
4715
+ * safe to leave an empty object. The caller will ignore it. */
4716
+ ok = 1 ;
4717
+ break ;
4718
+ }
4719
+ if (!ok ) {
4720
+ X509_OBJECT_free (ret );
4721
+ return NULL ;
4722
+ }
4723
+ return ret ;
4724
+ }
4725
+
4726
+ static STACK_OF (X509_OBJECT ) *
4727
+ X509_STORE_get1_objects (X509_STORE * store )
4728
+ {
4729
+ STACK_OF (X509_OBJECT ) * ret ;
4730
+ if (!X509_STORE_lock (store )) {
4731
+ return NULL ;
4732
+ }
4733
+ ret = sk_X509_OBJECT_deep_copy (X509_STORE_get0_objects (store ),
4734
+ x509_object_dup , X509_OBJECT_free );
4735
+ X509_STORE_unlock (store );
4736
+ return ret ;
4737
+ }
4738
+ #endif
4739
+
4678
4740
PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
4679
4741
"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
4680
4742
\n\
@@ -4704,7 +4766,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
4704
4766
int x509 = 0 , crl = 0 , ca = 0 , i ;
4705
4767
4706
4768
store = SSL_CTX_get_cert_store (self -> ctx );
4769
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4770
+ objs = X509_STORE_get1_objects (store );
4771
+ if (objs == NULL ) {
4772
+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
4773
+ return NULL ;
4774
+ }
4775
+ #else
4707
4776
objs = X509_STORE_get0_objects (store );
4777
+ #endif
4708
4778
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
4709
4779
obj = sk_X509_OBJECT_value (objs , i );
4710
4780
switch (X509_OBJECT_get_type (obj )) {
@@ -4718,12 +4788,13 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
4718
4788
crl ++ ;
4719
4789
break ;
4720
4790
default :
4721
- /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
4722
- * As far as I can tell they are internal states and never
4723
- * stored in a cert store */
4791
+ /* Ignore unrecognized types. */
4724
4792
break ;
4725
4793
}
4726
4794
}
4795
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4796
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4797
+ #endif
4727
4798
return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
4728
4799
"x509_ca" , ca );
4729
4800
}
@@ -4755,7 +4826,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
4755
4826
}
4756
4827
4757
4828
store = SSL_CTX_get_cert_store (self -> ctx );
4829
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4830
+ objs = X509_STORE_get1_objects (store );
4831
+ if (objs == NULL ) {
4832
+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
4833
+ return NULL ;
4834
+ }
4835
+ #else
4758
4836
objs = X509_STORE_get0_objects (store );
4837
+ #endif
4759
4838
for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
4760
4839
X509_OBJECT * obj ;
4761
4840
X509 * cert ;
@@ -4783,9 +4862,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
4783
4862
}
4784
4863
Py_CLEAR (ci );
4785
4864
}
4865
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4866
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4867
+ #endif
4786
4868
return rlist ;
4787
4869
4788
4870
error :
4871
+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4872
+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4873
+ #endif
4789
4874
Py_XDECREF (ci );
4790
4875
Py_XDECREF (rlist );
4791
4876
return NULL ;
0 commit comments