@@ -2251,6 +2251,17 @@ PySSL_dealloc(PySSLSocket *self)
2251
2251
PyTypeObject * tp = Py_TYPE (self );
2252
2252
PyObject_GC_UnTrack (self );
2253
2253
if (self -> ssl ) {
2254
+ // If we free the SSL socket object without having called SSL_shutdown,
2255
+ // OpenSSL will invalidate the linked SSL session object. While this
2256
+ // behavior is strictly RFC-compliant, it makes session reuse less
2257
+ // likely and it would also break compatibility with older stdlib
2258
+ // versions (which used an ugly workaround of duplicating the
2259
+ // SSL_SESSION object).
2260
+ // Therefore, we ensure the socket is marked as shutdown in any case.
2261
+ //
2262
+ // See elaborate explanation at
2263
+ // https://github.com/python/cpython/pull/123249#discussion_r1766164530
2264
+ SSL_set_shutdown (self -> ssl , SSL_SENT_SHUTDOWN | SSL_get_shutdown (self -> ssl ));
2254
2265
SSL_free (self -> ssl );
2255
2266
}
2256
2267
Py_XDECREF (self -> Socket );
@@ -2795,64 +2806,13 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
2795
2806
#endif
2796
2807
}
2797
2808
2798
- static SSL_SESSION *
2799
- _ssl_session_dup (SSL_SESSION * session ) {
2800
- SSL_SESSION * newsession = NULL ;
2801
- int slen ;
2802
- unsigned char * senc = NULL , * p ;
2803
- const unsigned char * const_p ;
2804
-
2805
- if (session == NULL ) {
2806
- PyErr_SetString (PyExc_ValueError , "Invalid session" );
2807
- goto error ;
2808
- }
2809
-
2810
- /* get length */
2811
- slen = i2d_SSL_SESSION (session , NULL );
2812
- if (slen == 0 || slen > 0xFF00 ) {
2813
- PyErr_SetString (PyExc_ValueError , "i2d() failed" );
2814
- goto error ;
2815
- }
2816
- if ((senc = PyMem_Malloc (slen )) == NULL ) {
2817
- PyErr_NoMemory ();
2818
- goto error ;
2819
- }
2820
- p = senc ;
2821
- if (!i2d_SSL_SESSION (session , & p )) {
2822
- PyErr_SetString (PyExc_ValueError , "i2d() failed" );
2823
- goto error ;
2824
- }
2825
- const_p = senc ;
2826
- newsession = d2i_SSL_SESSION (NULL , & const_p , slen );
2827
- if (newsession == NULL ) {
2828
- PyErr_SetString (PyExc_ValueError , "d2i() failed" );
2829
- goto error ;
2830
- }
2831
- PyMem_Free (senc );
2832
- return newsession ;
2833
- error :
2834
- if (senc != NULL ) {
2835
- PyMem_Free (senc );
2836
- }
2837
- return NULL ;
2838
- }
2839
-
2840
2809
static PyObject *
2841
2810
PySSL_get_session (PySSLSocket * self , void * closure ) {
2842
2811
/* get_session can return sessions from a server-side connection,
2843
2812
* it does not check for handshake done or client socket. */
2844
2813
PySSLSession * pysess ;
2845
2814
SSL_SESSION * session ;
2846
2815
2847
- /* duplicate session as workaround for session bug in OpenSSL 1.1.0,
2848
- * https://github.com/openssl/openssl/issues/1550 */
2849
- session = SSL_get0_session (self -> ssl ); /* borrowed reference */
2850
- if (session == NULL ) {
2851
- Py_RETURN_NONE ;
2852
- }
2853
- if ((session = _ssl_session_dup (session )) == NULL ) {
2854
- return NULL ;
2855
- }
2856
2816
session = SSL_get1_session (self -> ssl );
2857
2817
if (session == NULL ) {
2858
2818
Py_RETURN_NONE ;
@@ -2871,11 +2831,8 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
2871
2831
}
2872
2832
2873
2833
static int PySSL_set_session (PySSLSocket * self , PyObject * value ,
2874
- void * closure )
2875
- {
2834
+ void * closure ) {
2876
2835
PySSLSession * pysess ;
2877
- SSL_SESSION * session ;
2878
- int result ;
2879
2836
2880
2837
if (!Py_IS_TYPE (value , get_state_sock (self )-> PySSLSession_Type )) {
2881
2838
PyErr_SetString (PyExc_TypeError , "Value is not a SSLSession." );
@@ -2898,14 +2855,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
2898
2855
"Cannot set session after handshake." );
2899
2856
return -1 ;
2900
2857
}
2901
- /* duplicate session */
2902
- if ((session = _ssl_session_dup (pysess -> session )) == NULL ) {
2903
- return -1 ;
2904
- }
2905
- result = SSL_set_session (self -> ssl , session );
2906
- /* free duplicate, SSL_set_session() bumps ref count */
2907
- SSL_SESSION_free (session );
2908
- if (result == 0 ) {
2858
+ if (SSL_set_session (self -> ssl , pysess -> session ) == 0 ) {
2909
2859
_setSSLError (get_state_sock (self ), NULL , 0 , __FILE__ , __LINE__ );
2910
2860
return -1 ;
2911
2861
}
0 commit comments