Merge branch 'PHP-8.3'

* PHP-8.3:
  Fix GH-9348: FTP & SSL session reuse
This commit is contained in:
Niels Dossche 2023-12-03 00:52:15 +01:00
commit f601963d4f
2 changed files with 25 additions and 3 deletions

View File

@ -167,6 +167,9 @@ ftp_close(ftpbuf_t *ftp)
if (ftp == NULL) {
return NULL;
}
if (ftp->last_ssl_session) {
SSL_SESSION_free(ftp->last_ssl_session);
}
if (ftp->data) {
data_close(ftp, ftp->data);
}
@ -229,6 +232,20 @@ ftp_quit(ftpbuf_t *ftp)
}
/* }}} */
static int ftp_ssl_new_session_cb(SSL *ssl, SSL_SESSION *sess)
{
ftpbuf_t *ftp = SSL_get_app_data(ssl);
/* Technically there can be multiple sessions per connection, but we only care about the most recent one. */
if (ftp->last_ssl_session) {
SSL_SESSION_free(ftp->last_ssl_session);
}
ftp->last_ssl_session = SSL_get1_session(ssl);
/* Return 0 as we are not using OpenSSL's session cache. */
return 0;
}
/* {{{ ftp_login */
int
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
#endif
SSL_CTX_set_options(ctx, ssl_ctx_options);
/* allow SSL to re-use sessions */
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
/* Allow SSL to re-use sessions.
* We're relying on our own session storage as only at most one session will ever be active per FTP connection. */
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_sess_set_new_cb(ctx, ftp_ssl_new_session_cb);
ftp->ssl_handle = SSL_new(ctx);
SSL_set_app_data(ftp->ssl_handle, ftp); /* Needed for ftp_ssl_new_session_cb */
SSL_CTX_free(ctx);
if (ftp->ssl_handle == NULL) {
@ -1792,7 +1812,7 @@ data_accepted:
}
/* get the session from the control connection so we can re-use it */
session = SSL_get_session(ftp->ssl_handle);
session = ftp->last_ssl_session;
if (session == NULL) {
php_error_docref(NULL, E_WARNING, "data_accept: failed to retrieve the existing SSL session");
SSL_free(data->ssl_handle);
@ -1800,6 +1820,7 @@ data_accepted:
}
/* and set it on the data connection */
SSL_set_app_data(data->ssl_handle, ftp); /* Needed for ftp_ssl_new_session_cb */
res = SSL_set_session(data->ssl_handle, session);
if (res == 0) {
php_error_docref(NULL, E_WARNING, "data_accept: failed to set the existing SSL session");

View File

@ -82,6 +82,7 @@ typedef struct ftpbuf
int old_ssl; /* old mode = forced data encryption */
SSL *ssl_handle; /* handle for control connection */
int ssl_active; /* ssl active on control conn */
SSL_SESSION *last_ssl_session; /* last negotiated session */
#endif
} ftpbuf_t;