@@ -167,6 +167,9 @@ ftp_close(ftpbuf_t *ftp)
167
167
if (ftp == NULL ) {
168
168
return NULL ;
169
169
}
170
+ if (ftp -> last_ssl_session ) {
171
+ SSL_SESSION_free (ftp -> last_ssl_session );
172
+ }
170
173
if (ftp -> data ) {
171
174
data_close (ftp , ftp -> data );
172
175
}
@@ -229,6 +232,20 @@ ftp_quit(ftpbuf_t *ftp)
229
232
}
230
233
/* }}} */
231
234
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
+
232
249
/* {{{ ftp_login */
233
250
int
234
251
ftp_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
279
296
#endif
280
297
SSL_CTX_set_options (ctx , ssl_ctx_options );
281
298
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 );
284
303
285
304
ftp -> ssl_handle = SSL_new (ctx );
305
+ SSL_set_app_data (ftp -> ssl_handle , ftp ); /* Needed for ftp_ssl_new_session_cb */
286
306
SSL_CTX_free (ctx );
287
307
288
308
if (ftp -> ssl_handle == NULL ) {
@@ -1789,14 +1809,15 @@ data_accept(databuf_t *data, ftpbuf_t *ftp)
1789
1809
}
1790
1810
1791
1811
/* 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 ;
1793
1813
if (session == NULL ) {
1794
1814
php_error_docref (NULL , E_WARNING , "data_accept: failed to retrieve the existing SSL session" );
1795
1815
SSL_free (data -> ssl_handle );
1796
1816
return 0 ;
1797
1817
}
1798
1818
1799
1819
/* and set it on the data connection */
1820
+ SSL_set_app_data (data -> ssl_handle , ftp ); /* Needed for ftp_ssl_new_session_cb */
1800
1821
res = SSL_set_session (data -> ssl_handle , session );
1801
1822
if (res == 0 ) {
1802
1823
php_error_docref (NULL , E_WARNING , "data_accept: failed to set the existing SSL session" );
0 commit comments