@@ -124,6 +124,10 @@ struct py_ssl_library_code {
124124# define HAVE_TLSv1_2 0
125125#endif
126126
127+ #if (OPENSSL_VERSION_NUMBER >= 0x30300000L ) && !defined(LIBRESSL_VERSION_NUMBER )
128+ # define OPENSSL_VERSION_3_3 1
129+ #endif
130+
127131/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f
128132 * This includes the SSL_set_SSL_CTX() function.
129133 */
@@ -164,6 +168,16 @@ struct py_ssl_library_code {
164168#define HAVE_OPENSSL_CRYPTO_LOCK
165169#endif
166170
171+ /* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */
172+ #ifdef OPENSSL_VERSION_1_1
173+ #define HAVE_OPENSSL_X509_STORE_LOCK
174+ #endif
175+
176+ /* OpenSSL 3.3 added the X509_STORE_get1_objects API */
177+ #ifdef OPENSSL_VERSION_3_3
178+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
179+ #endif
180+
167181#if defined(OPENSSL_VERSION_1_1 ) && !defined(OPENSSL_NO_SSL2 )
168182#define OPENSSL_NO_SSL2
169183#endif
@@ -4096,6 +4110,61 @@ _ssl__SSLContext_set_servername_callback(PySSLContext *self, PyObject *cb)
40964110#endif
40974111}
40984112
4113+ /* Shim of X509_STORE_get1_objects API from OpenSSL 3.3
4114+ * Only available with the X509_STORE_lock() API */
4115+ #if defined(HAVE_OPENSSL_X509_STORE_LOCK ) && !defined(OPENSSL_VERSION_3_3 )
4116+ #define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1
4117+
4118+ static X509_OBJECT * x509_object_dup (const X509_OBJECT * obj )
4119+ {
4120+ int ok ;
4121+ X509_OBJECT * ret = X509_OBJECT_new ();
4122+ if (ret == NULL ) {
4123+ return NULL ;
4124+ }
4125+ switch (X509_OBJECT_get_type (obj )) {
4126+ case X509_LU_X509 :
4127+ ok = X509_OBJECT_set1_X509 (ret , X509_OBJECT_get0_X509 (obj ));
4128+ break ;
4129+ case X509_LU_CRL :
4130+ /* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/
4131+ ok = X509_OBJECT_set1_X509_CRL (
4132+ ret , X509_OBJECT_get0_X509_CRL ((X509_OBJECT * )obj ));
4133+ break ;
4134+ default :
4135+ /* We cannot duplicate unrecognized types in a polyfill, but it is
4136+ * safe to leave an empty object. The caller will ignore it. */
4137+ ok = 1 ;
4138+ break ;
4139+ }
4140+ if (!ok ) {
4141+ X509_OBJECT_free (ret );
4142+ return NULL ;
4143+ }
4144+ return ret ;
4145+ }
4146+
4147+ static STACK_OF (X509_OBJECT ) *
4148+ X509_STORE_get1_objects (X509_STORE * store )
4149+ {
4150+ STACK_OF (X509_OBJECT ) * ret ;
4151+ if (!X509_STORE_lock (store )) {
4152+ return NULL ;
4153+ }
4154+ ret = sk_X509_OBJECT_deep_copy (X509_STORE_get0_objects (store ),
4155+ x509_object_dup , X509_OBJECT_free );
4156+ X509_STORE_unlock (store );
4157+ return ret ;
4158+ }
4159+ #endif
4160+
4161+ PyDoc_STRVAR (PySSLContext_sni_callback_doc ,
4162+ "Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\
4163+ \n\
4164+ If the argument is None then the callback is disabled. The method is called\n\
4165+ with the SSLSocket, the server name as a string, and the SSLContext object.\n\
4166+ See RFC 6066 for details of the SNI extension." );
4167+
40994168/*[clinic input]
41004169_ssl._SSLContext.cert_store_stats
41014170
@@ -4118,7 +4187,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
41184187 int x509 = 0 , crl = 0 , ca = 0 , i ;
41194188
41204189 store = SSL_CTX_get_cert_store (self -> ctx );
4190+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4191+ objs = X509_STORE_get1_objects (store );
4192+ if (objs == NULL ) {
4193+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
4194+ return NULL ;
4195+ }
4196+ #else
41214197 objs = X509_STORE_get0_objects (store );
4198+ #endif
41224199 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
41234200 obj = sk_X509_OBJECT_value (objs , i );
41244201 switch (X509_OBJECT_get_type (obj )) {
@@ -4132,12 +4209,13 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self)
41324209 crl ++ ;
41334210 break ;
41344211 default :
4135- /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
4136- * As far as I can tell they are internal states and never
4137- * stored in a cert store */
4212+ /* Ignore unrecognized types. */
41384213 break ;
41394214 }
41404215 }
4216+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4217+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4218+ #endif
41414219 return Py_BuildValue ("{sisisi}" , "x509" , x509 , "crl" , crl ,
41424220 "x509_ca" , ca );
41434221}
@@ -4169,7 +4247,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
41694247 }
41704248
41714249 store = SSL_CTX_get_cert_store (self -> ctx );
4250+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4251+ objs = X509_STORE_get1_objects (store );
4252+ if (objs == NULL ) {
4253+ PyErr_SetString (PyExc_MemoryError , "failed to query cert store" );
4254+ return NULL ;
4255+ }
4256+ #else
41724257 objs = X509_STORE_get0_objects (store );
4258+ #endif
41734259 for (i = 0 ; i < sk_X509_OBJECT_num (objs ); i ++ ) {
41744260 X509_OBJECT * obj ;
41754261 X509 * cert ;
@@ -4197,9 +4283,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
41974283 }
41984284 Py_CLEAR (ci );
41994285 }
4286+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4287+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4288+ #endif
42004289 return rlist ;
42014290
42024291 error :
4292+ #if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS
4293+ sk_X509_OBJECT_pop_free (objs , X509_OBJECT_free );
4294+ #endif
42034295 Py_XDECREF (ci );
42044296 Py_XDECREF (rlist );
42054297 return NULL ;
0 commit comments