diff options
| author | Benedict Singer <singerb@mac.com> | 2016-08-10 15:03:12 +0100 |
|---|---|---|
| committer | Nikita Popov <nikic@php.net> | 2016-08-13 21:35:03 +0200 |
| commit | dfadc5a427b548cab2b7c037c05f65684e08a248 (patch) | |
| tree | 921574286fe5feecfb0ea919e42f6ac9f79593ae | |
| parent | 82df4e263886a0da21a00c98189649287666ba5c (diff) | |
| download | php-git-dfadc5a427b548cab2b7c037c05f65684e08a248.tar.gz | |
Bug 70195
Many FTP-S servers now require FTP clients to re-use the SSL session
from the control connection on the data connection, to prove that the
same entity controls both connections. This patch updates PHP's FTP-S
client code to allow that possibility.
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | ext/ftp/ftp.c | 42 |
2 files changed, 29 insertions, 17 deletions
@@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2016, PHP 5.6.26 +- FTP: + . Fixed bug #70195 (Cannot upload file using ftp_put to FTPES with + require_ssl_reuse). (Benedict Singer) + - MSSQL: . Fixed bug #72039 (Use of uninitialised value on mssql_guid_string). (Kalle) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index f0bfb9459c..d2f726d038 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -290,6 +290,9 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC) #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); + ftp->ssl_handle = SSL_new(ctx); if (ftp->ssl_handle == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create the SSL handle"); @@ -1495,7 +1498,8 @@ data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC) #if HAVE_OPENSSL_EXT SSL_CTX *ctx; - long ssl_ctx_options = SSL_OP_ALL; + SSL_SESSION *session; + int result; #endif if (data->fd != -1) { @@ -1516,31 +1520,40 @@ data_accepted: /* now enable ssl if we need to */ if (ftp->use_ssl && ftp->use_ssl_for_data) { - ctx = SSL_CTX_new(SSLv23_client_method()); + ctx = SSL_get_SSL_CTX(ftp->ssl_handle); if (ctx == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to create the SSL context"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to retreive the existing SSL context"); return 0; } -#if OPENSSL_VERSION_NUMBER >= 0x0090605fL - ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; -#endif - SSL_CTX_set_options(ctx, ssl_ctx_options); - data->ssl_handle = SSL_new(ctx); if (data->ssl_handle == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to create the SSL handle"); - SSL_CTX_free(ctx); return 0; } - SSL_set_fd(data->ssl_handle, data->fd); if (ftp->old_ssl) { SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle); } + /* get the session from the control connection so we can re-use it */ + session = SSL_get_session(ftp->ssl_handle); + if (session == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to retreive the existing SSL session"); + SSL_free(data->ssl_handle); + return 0; + } + + /* and set it on the data connection */ + result = SSL_set_session(data->ssl_handle, session); + if (result == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to set the existing SSL session"); + SSL_free(data->ssl_handle); + return 0; + } + if (SSL_connect(data->ssl_handle) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: SSL/TLS handshake failed"); SSL_shutdown(data->ssl_handle); @@ -1571,10 +1584,7 @@ data_close(ftpbuf_t *ftp, databuf_t *data) if (data->listener != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { - - ctx = SSL_get_SSL_CTX(data->ssl_handle); - SSL_CTX_free(ctx); - + /* don't free the data context, it's the same as the control */ SSL_shutdown(data->ssl_handle); SSL_free(data->ssl_handle); data->ssl_active = 0; @@ -1585,9 +1595,7 @@ data_close(ftpbuf_t *ftp, databuf_t *data) if (data->fd != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { - ctx = SSL_get_SSL_CTX(data->ssl_handle); - SSL_CTX_free(ctx); - + /* don't free the data context, it's the same as the control */ SSL_shutdown(data->ssl_handle); SSL_free(data->ssl_handle); data->ssl_active = 0; |
