summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenedict Singer <singerb@mac.com>2016-08-10 15:03:12 +0100
committerNikita Popov <nikic@php.net>2016-08-13 21:35:03 +0200
commitdfadc5a427b548cab2b7c037c05f65684e08a248 (patch)
tree921574286fe5feecfb0ea919e42f6ac9f79593ae
parent82df4e263886a0da21a00c98189649287666ba5c (diff)
downloadphp-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--NEWS4
-rw-r--r--ext/ftp/ftp.c42
2 files changed, 29 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index d91bdda54e..ccafb63991 100644
--- a/NEWS
+++ b/NEWS
@@ -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;