@@ -2245,6 +2245,17 @@ PySSL_dealloc(PySSLSocket *self)
22452245 PyTypeObject * tp = Py_TYPE (self );
22462246 PyObject_GC_UnTrack (self );
22472247 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 ));
22482259 SSL_free (self -> ssl );
22492260 }
22502261 Py_XDECREF (self -> Socket );
@@ -2789,64 +2800,13 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self)
27892800#endif
27902801}
27912802
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-
28342803static PyObject *
28352804PySSL_get_session (PySSLSocket * self , void * closure ) {
28362805 /* get_session can return sessions from a server-side connection,
28372806 * it does not check for handshake done or client socket. */
28382807 PySSLSession * pysess ;
28392808 SSL_SESSION * session ;
28402809
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- }
28502810 session = SSL_get1_session (self -> ssl );
28512811 if (session == NULL ) {
28522812 Py_RETURN_NONE ;
@@ -2865,11 +2825,8 @@ PySSL_get_session(PySSLSocket *self, void *closure) {
28652825}
28662826
28672827static int PySSL_set_session (PySSLSocket * self , PyObject * value ,
2868- void * closure )
2869- {
2828+ void * closure ) {
28702829 PySSLSession * pysess ;
2871- SSL_SESSION * session ;
2872- int result ;
28732830
28742831 if (!Py_IS_TYPE (value , get_state_sock (self )-> PySSLSession_Type )) {
28752832 PyErr_SetString (PyExc_TypeError , "Value is not a SSLSession." );
@@ -2892,14 +2849,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
28922849 "Cannot set session after handshake." );
28932850 return -1 ;
28942851 }
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 ) {
29032853 _setSSLError (get_state_sock (self ), NULL , 0 , __FILE__ , __LINE__ );
29042854 return -1 ;
29052855 }
0 commit comments