@@ -166,6 +166,10 @@ extern const SSL_METHOD *TLSv1_2_method(void);
166166# define PY_OPENSSL_1_1_API 1
167167#endif
168168
169+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
170+ # define OPENSSL_VERSION_3_3 1
171+ #endif
172+
169173/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
170174 * This includes the SSL_set_SSL_CTX() function.
171175 */
@@ -210,6 +214,16 @@ extern const SSL_METHOD *TLSv1_2_method(void);
210214#define HAVE_OPENSSL_CRYPTO_LOCK
211215#endif
212216
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+
213227#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
214228#define OPENSSL_NO_SSL2
215229#endif
@@ -4675,6 +4689,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
46754689#endif
46764690}
46774691
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+
46784740PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
46794741"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
46804742\n\
@@ -4704,7 +4766,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
47044766 int x509 = 0 , crl = 0 , ca = 0 , i ;
47054767
47064768 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
47074776 objs = X509_STORE_get0_objects (store );
4777+ #endif
47084778 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
47094779 obj = sk_X509_OBJECT_value (objs , i );
47104780 switch (X509_OBJECT_get_type (obj )) {
@@ -4718,12 +4788,13 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
47184788 crl ++ ;
47194789 break ;
47204790 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. */
47244792 break ;
47254793 }
47264794 }
4795+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4796+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4797+ #endif
47274798 return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
47284799 "x509_ca" , ca );
47294800}
@@ -4755,7 +4826,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
47554826 }
47564827
47574828 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
47584836 objs = X509_STORE_get0_objects (store );
4837+ #endif
47594838 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
47604839 X509_OBJECT * obj ;
47614840 X509 * cert ;
@@ -4783,9 +4862,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
47834862 }
47844863 Py_CLEAR (ci );
47854864 }
4865+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4866+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4867+ #endif
47864868 return rlist ;
47874869
47884870 error :
4871+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4872+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4873+ #endif
47894874 Py_XDECREF (ci );
47904875 Py_XDECREF (rlist );
47914876 return NULL ;
0 commit comments