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