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