@@ -168,6 +168,10 @@ extern const SSL_METHOD *TLSv1_2_method(void);
168168# define PY_OPENSSL_1_1_API 1
169169#endif
170170
171+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
172+ # define OPENSSL_VERSION_3_3 1
173+ #endif
174+
171175/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
172176 * This includes the SSL_set_SSL_CTX() function.
173177 */
@@ -212,6 +216,16 @@ extern const SSL_METHOD *TLSv1_2_method(void);
212216#define HAVE_OPENSSL_CRYPTO_LOCK
213217#endif
214218
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+
215229#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
216230#define OPENSSL_NO_SSL2
217231#endif
@@ -4678,6 +4692,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
46784692#endif
46794693}
46804694
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+
46814743PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
46824744"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
46834745\n\
@@ -4707,7 +4769,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
47074769int x509 = 0 , crl = 0 , ca = 0 , i ;
47084770
47094771store = 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
47104779objs = X509_STORE_get0_objects (store );
4780+ #endif
47114781for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ){
47124782obj = sk_X509_OBJECT_value (objs , i );
47134783switch (X509_OBJECT_get_type (obj )){
@@ -4721,12 +4791,13 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
47214791crl ++ ;
47224792break ;
47234793default :
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. */
47274795break ;
47284796 }
47294797 }
4798+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4799+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4800+ #endif
47304801return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
47314802"x509_ca" , ca );
47324803}
@@ -4758,7 +4829,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
47584829 }
47594830
47604831store = 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
47614839objs = X509_STORE_get0_objects (store );
4840+ #endif
47624841for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ){
47634842X509_OBJECT * obj ;
47644843X509 * cert ;
@@ -4786,9 +4865,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
47864865 }
47874866Py_CLEAR (ci );
47884867 }
4868+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4869+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4870+ #endif
47894871return rlist ;
47904872
47914873error :
4874+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4875+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4876+ #endif
47924877Py_XDECREF (ci );
47934878Py_XDECREF (rlist );
47944879return NULL ;
0 commit comments