From d5f2b4b398f1307074b69f9e35fc6ed5f3a69b23 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 11 Mar 2015 15:07:44 +0100 Subject: [PATCH] fix ftp_login with ssl enabled --- ext/ftp/ftp.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 20f8cb930f..3f01ea7896 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -248,6 +248,8 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass) #ifdef HAVE_FTP_SSL SSL_CTX *ctx = NULL; long ssl_ctx_options = SSL_OP_ALL; + int err, res; + zend_bool retry; #endif if (ftp == NULL) { return 0; @@ -298,13 +300,42 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass) SSL_set_fd(ftp->ssl_handle, ftp->fd); - /* TODO check SSL_get_error() and poll on failure */ - if (SSL_connect(ftp->ssl_handle) <= 0) { - php_error_docref(NULL, E_WARNING, "SSL/TLS handshake failed"); - SSL_shutdown(ftp->ssl_handle); - SSL_free(ftp->ssl_handle); - return 0; - } + do { + res = SSL_connect(ftp->ssl_handle); + err = SSL_get_error(ftp->ssl_handle, res); + + /* TODO check if handling other error codes would make sense */ + switch (err) { + case SSL_ERROR_NONE: + retry = 0; + 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); + + if (i > 0) { + retry = 1; + } else { + retry = 0; + } + } + break; + + default: + php_error_docref(NULL, E_WARNING, "SSL/TLS handshake failed"); + SSL_shutdown(ftp->ssl_handle); + SSL_free(ftp->ssl_handle); + return 0; + } + } while (retry); ftp->ssl_active = 1; -- 2.50.1