@@ -167,6 +167,10 @@ static void _PySSLFixErrno(void) {
167167# define PY_OPENSSL_1_1_API 1
168168#endif
169169
170+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
171+ # define OPENSSL_VERSION_3_3 1
172+ #endif
173+
170174/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
171175 * This includes the SSL_set_SSL_CTX() function.
172176 */
@@ -207,6 +211,16 @@ static void _PySSLFixErrno(void) {
207211#define HAVE_OPENSSL_CRYPTO_LOCK
208212#endif
209213
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+
210224#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
211225#define OPENSSL_NO_SSL2
212226#endif
@@ -4517,6 +4531,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c)
45174531#endif
45184532}
45194533
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+
45204582PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
45214583"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
45224584\n\
@@ -4546,7 +4608,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
45464608 int x509 = 0 , crl = 0 , ca = 0 , i ;
45474609
45484610 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
45494618 objs = X509_STORE_get0_objects (store );
4619+ #endif
45504620 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
45514621 obj = sk_X509_OBJECT_value (objs , i );
45524622 switch (X509_OBJECT_get_type (obj )) {
@@ -4563,9 +4633,14 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
45634633 /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
45644634 * As far as I can tell they are internal states and never
45654635 * stored in a cert store */
4636+ /* Ignore unrecognized types. */
45664637 break ;
45674638 }
45684639 }
4640+
4641+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4642+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4643+ #endif
45694644 return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
45704645 "x509_ca" , ca );
45714646}
@@ -4597,7 +4672,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
45974672 }
45984673
45994674 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
46004682 objs = X509_STORE_get0_objects (store );
4683+ #endif
46014684 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
46024685 X509_OBJECT * obj ;
46034686 X509 * cert ;
@@ -4625,9 +4708,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
46254708 }
46264709 Py_CLEAR (ci );
46274710 }
4711+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4712+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4713+ #endif
46284714 return rlist ;
46294715
46304716 error :
4717+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4718+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4719+ #endif
46314720 Py_XDECREF (ci );
46324721 Py_XDECREF (rlist );
46334722 return NULL ;
0 commit comments