@@ -167,6 +167,9 @@ ftp_close(ftpbuf_t *ftp)
167167 if (ftp == NULL ) {
168168 return NULL ;
169169 }
170+ if (ftp -> last_ssl_session ) {
171+ SSL_SESSION_free (ftp -> last_ssl_session );
172+ }
170173 if (ftp -> data ) {
171174 data_close (ftp , ftp -> data );
172175 }
@@ -229,6 +232,20 @@ ftp_quit(ftpbuf_t *ftp)
229232}
230233/* }}} */
231234
235+ static int ftp_ssl_new_session_cb (SSL * ssl , SSL_SESSION * sess )
236+ {
237+ ftpbuf_t * ftp = SSL_get_app_data (ssl );
238+
239+ /* Technically there can be multiple sessions per connection, but we only care about the most recent one. */
240+ if (ftp -> last_ssl_session ) {
241+ SSL_SESSION_free (ftp -> last_ssl_session );
242+ }
243+ ftp -> last_ssl_session = SSL_get1_session (ssl );
244+
245+ /* Return 0 as we are not using OpenSSL's session cache. */
246+ return 0 ;
247+ }
248+
232249/* {{{ ftp_login */
233250int
234251ftp_login (ftpbuf_t * ftp , const char * user , const size_t user_len , const char * pass , const size_t pass_len )
@@ -279,10 +296,13 @@ ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pa
279296#endif
280297 SSL_CTX_set_options (ctx , ssl_ctx_options );
281298
282- /* allow SSL to re-use sessions */
283- SSL_CTX_set_session_cache_mode (ctx , SSL_SESS_CACHE_BOTH );
299+ /* Allow SSL to re-use sessions.
300+ * We're relying on our own session storage as only at most one session will ever be active per FTP connection. */
301+ SSL_CTX_set_session_cache_mode (ctx , SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL );
302+ SSL_CTX_sess_set_new_cb (ctx , ftp_ssl_new_session_cb );
284303
285304 ftp -> ssl_handle = SSL_new (ctx );
305+ SSL_set_app_data (ftp -> ssl_handle , ftp ); /* Needed for ftp_ssl_new_session_cb */
286306 SSL_CTX_free (ctx );
287307
288308 if (ftp -> ssl_handle == NULL ) {
@@ -1789,14 +1809,15 @@ data_accept(databuf_t *data, ftpbuf_t *ftp)
17891809 }
17901810
17911811 /* get the session from the control connection so we can re-use it */
1792- session = SSL_get_session ( ftp -> ssl_handle ) ;
1812+ session = ftp -> last_ssl_session ;
17931813 if (session == NULL ) {
17941814 php_error_docref (NULL , E_WARNING , "data_accept: failed to retrieve the existing SSL session" );
17951815 SSL_free (data -> ssl_handle );
17961816 return 0 ;
17971817 }
17981818
17991819 /* and set it on the data connection */
1820+ SSL_set_app_data (data -> ssl_handle , ftp ); /* Needed for ftp_ssl_new_session_cb */
18001821 res = SSL_set_session (data -> ssl_handle , session );
18011822 if (res == 0 ) {
18021823 php_error_docref (NULL , E_WARNING , "data_accept: failed to set the existing SSL session" );
0 commit comments