@@ -2251,6 +2251,17 @@ PySSL_dealloc(PySSLSocket *self)
22512251 PyTypeObject * tp = Py_TYPE (self );
22522252 PyObject_GC_UnTrack (self );
22532253 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 ));
22542265 SSL_free (self -> ssl );
22552266 }
22562267 Py_XDECREF (self -> Socket );
@@ -2795,64 +2806,13 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
27952806#endif
27962807}
27972808
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-
28402809static PyObject *
28412810PySSL_get_session (PySSLSocket * self , void * closure ) {
28422811 /* get_session can return sessions from a server-side connection,
28432812 * it does not check for handshake done or client socket. */
28442813 PySSLSession * pysess ;
28452814 SSL_SESSION * session ;
28462815
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- }
28562816 session = SSL_get1_session (self -> ssl );
28572817 if (session == NULL ) {
28582818 Py_RETURN_NONE ;
@@ -2871,11 +2831,8 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
28712831}
28722832
28732833static int PySSL_set_session (PySSLSocket * self , PyObject * value ,
2874- void * closure )
2875- {
2834+ void * closure ) {
28762835 PySSLSession * pysess ;
2877- SSL_SESSION * session ;
2878- int result ;
28792836
28802837 if (!Py_IS_TYPE (value , get_state_sock (self )-> PySSLSession_Type )) {
28812838 PyErr_SetString (PyExc_TypeError , "Value is not a SSLSession." );
@@ -2898,14 +2855,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
28982855 "Cannot set session after handshake." );
28992856 return -1 ;
29002857 }
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 ) {
29092859 _setSSLError (get_state_sock (self ), NULL , 0 , __FILE__ , __LINE__ );
29102860 return -1 ;
29112861 }
0 commit comments