]> granicus.if.org Git - php/commitdiff
Fixed bug #39571 (timeout ssl:// connections).
authorIlia Alshanetsky <iliaa@php.net>
Tue, 5 Dec 2006 01:39:07 +0000 (01:39 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Tue, 5 Dec 2006 01:39:07 +0000 (01:39 +0000)
NEWS
ext/openssl/xp_ssl.c

diff --git a/NEWS b/NEWS
index 7f4e28e4d0acb15f454d9f587b9ccdd3ba528af2..45728a060928780029632987b66e1710b90ae7b4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -73,6 +73,7 @@ PHP                                                                        NEWS
 - Fixed bug #39602 (Invalid session.save_handler crashes PHP). (Dmitry)
 - Fixed bug #39583 (ftp_put() does not change transfer mode to ASCII). (Tony)
 - Fixed bug #39576 (array_walk() doesn't separate userdata zval). (Tony)
+- Fixed bug #39571 (timeout ssl:// connections). (Ilia)
 - Fixed bug #39564 (PDO::errorInfo() returns inconsistent information when 
   sqlite3_step() fails). (Tony)
 - Fixed bug #39548 (ZMSG_LOG_SCRIPT_NAME not routed to OutputDebugString()
index 03d07dfae16c668affcce1df6149862bb47f40f1..b20cf0aa3e6ab06fba1cea7eb448b09a6fa8de4b 100644 (file)
@@ -99,7 +99,7 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC)
                        /* re-negotiation, or perhaps the SSL layer needs more
                         * packets: retry in next iteration */
                        errno = EAGAIN;
-                       retry = sslsock->s.is_blocked;
+                       retry = 1;
                        break;
                case SSL_ERROR_SYSCALL:
                        if (ERR_peek_error() == 0) {
@@ -386,6 +386,9 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
        int n, retry = 1;
 
        if (cparam->inputs.activate && !sslsock->ssl_active) {
+               float timeout = sslsock->s.timeout.tv_sec + sslsock->s.timeout.tv_usec / 1000000;
+               int blocked = sslsock->s.is_blocked;
+
                if (!sslsock->state_set) {
                        if (sslsock->is_client) {
                                SSL_set_connect_state(sslsock->ssl_handle);
@@ -395,9 +398,23 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
                        sslsock->state_set = 1;
                }
        
+               if (sslsock->is_client && SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
+                       sslsock->s.is_blocked = 0;
+               }
                do {
                        if (sslsock->is_client) {
+                               struct timeval tvs, tve;
+                               struct timezone tz;
+
+                               gettimeofday(&tvs, &tz);
                                n = SSL_connect(sslsock->ssl_handle);
+                               gettimeofday(&tve, &tz);
+
+                               timeout -= (tve.tv_sec + tve.tv_usec / 1000000) - (tvs.tv_sec + tvs.tv_usec / 1000000);
+                               if (timeout < 0) {
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: connection timeout");
+                                       return -1;
+                               }
                        } else {
                                n = SSL_accept(sslsock->ssl_handle);
                        }
@@ -409,6 +426,10 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
                        }
                } while (retry);
 
+               if (sslsock->is_client && sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) {
+                       sslsock->s.is_blocked = blocked;
+               }
+
                if (n == 1) {
                        X509 *peer_cert;
 
@@ -741,8 +762,8 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen,
        memset(sslsock, 0, sizeof(*sslsock));
 
        sslsock->s.is_blocked = 1;
-       sslsock->s.timeout.tv_sec = FG(default_socket_timeout);
-       sslsock->s.timeout.tv_usec = 0;
+       sslsock->s.timeout.tv_sec = timeout->tv_sec;
+       sslsock->s.timeout.tv_usec = timeout->tv_usec;
 
        /* we don't know the socket until we have determined if we are binding or
         * connecting */