#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");
+ php_error_docref(NULL, E_WARNING, "failed to create the SSL handle");
SSL_CTX_free(ctx);
return 0;
}
php_sockaddr_storage addr;
socklen_t size;
-#if HAVE_OPENSSL_EXT
+#ifdef HAVE_FTP_SSL
SSL_CTX *ctx;
- zend_long ssl_ctx_options = SSL_OP_ALL;
+ SSL_SESSION *session;
- int result;
+ int err, res;
+ zend_bool retry;
#endif
if (data->fd != -1) {
/* 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, 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");
++ php_error_docref(NULL, 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");
+ php_error_docref(NULL, E_WARNING, "data_accept: failed to create the SSL handle");
- SSL_CTX_free(ctx);
return 0;
}
SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle);
}
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: failed to retreive the existing SSL session");
+ /* get the session from the control connection so we can re-use it */
+ session = SSL_get_session(ftp->ssl_handle);
+ if (session == NULL) {
- 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");
++ php_error_docref(NULL, 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 */
- 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);
- SSL_free(data->ssl_handle);
- return 0;
- }
++ 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");
+ SSL_free(data->ssl_handle);
+ return 0;
+ }
+
+ do {
+ res = SSL_connect(data->ssl_handle);
+ err = SSL_get_error(data->ssl_handle, res);
+
+ switch (err) {
+ case SSL_ERROR_NONE:
+ retry = 0;
+ break;
+
+ case SSL_ERROR_ZERO_RETURN:
+ retry = 0;
+ SSL_shutdown(data->ssl_handle);
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE: {
+ php_pollfd p;
+ int i;
+
+ p.fd = ftp->fd;
+ p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
+ p.revents = 0;
+
+ i = php_poll2(&p, 1, 300);
+
+ retry = i > 0;
+ }
+ break;
+
+ default:
+ php_error_docref(NULL, E_WARNING, "data_accept: SSL/TLS handshake failed");
+ SSL_shutdown(data->ssl_handle);
+ SSL_free(data->ssl_handle);
+ return 0;
+ }
+ } while (retry);
data->ssl_active = 1;
}
return NULL;
}
if (data->listener != -1) {
-#if HAVE_OPENSSL_EXT
+#ifdef HAVE_FTP_SSL
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;
closesocket(data->listener);
}
if (data->fd != -1) {
-#if HAVE_OPENSSL_EXT
+#ifdef HAVE_FTP_SSL
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;