php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #41631
Patch ssl_read_timeout-5.4.32.patch revision 2014-09-29 18:44 UTC by askalski at synacor dot com
revision 2014-09-26 18:38 UTC by askalski at synacor dot com
Patch bug41631.patch revision 2014-09-19 15:13 UTC by rdlowrey@php.net

Patch bug41631.patch for OpenSSL related Bug #41631

Patch version 2014-09-19 15:13 UTC

Return to Bug #41631 | Download this patch
Patch Revisions:

Developer: rdlowrey@php.net

From c033ddc428ed2954ecdfb9b78346458d655719f6 Mon Sep 17 00:00:00 2001
From: Daniel Lowrey <rdlowrey@php.net>
Date: Fri, 19 Sep 2014 10:46:13 -0400
Subject: [PATCH] Bug #41631: Fix EOF case when polling to observe socket timeout

---
 ext/openssl/xp_ssl.c |   32 ++++++++++++++++++++++----------
 1 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index b2a939d..b4de3d7 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -204,33 +204,45 @@ static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size
        return didwrite;
 }

-static void php_openssl_stream_wait_for_data(php_netstream_data_t *sock)
+static void php_openssl_stream_wait_for_data(SSL *ssl, php_netstream_data_t *sock TSRMLS_DC)
 {
        int retval;
+       int np_bytes = 0;
+       char peekbuf[128];
        struct timeval *ptimeout;

        if (sock->socket == -1) {
                return;
        }
-
+
        sock->timeout_event = 0;

-       if (sock->timeout.tv_sec == -1)
-               ptimeout = NULL;
-       else
-               ptimeout = &sock->timeout;
+       /* We need to do a non-blocking peek first so we can avoid polling in the case of EOF
+        * but still observe the socket timeout otherwise.
+        */
+       php_set_sock_blocking(sock->socket, 0 TSRMLS_CC);
+       np_bytes = SSL_peek(ssl, peekbuf, sizeof(peekbuf));
+       php_set_sock_blocking(sock->socket, 1 TSRMLS_CC);
+       if (np_bytes <= 0) {
+               return;
+       }
+
+       ptimeout = (sock->timeout.tv_sec == -1) ? NULL : &sock->timeout;

        while(1) {
                retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout);

-               if (retval == 0)
+               if (retval == 0) {
                        sock->timeout_event = 1;
+               }

-               if (retval >= 0)
+               if (retval >= 0) {
                        break;
+               }

-               if (php_socket_errno() != EINTR)
+               if (php_socket_errno() != EINTR) {
                        break;
+               }
        }
 }

@@ -250,7 +262,7 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun
                   the actual read. If it times out we're finished.
                */
                if (sock->is_blocked && SSL_pending(sslsock->ssl_handle) == 0) {
-                       php_openssl_stream_wait_for_data(sock);
+                       php_openssl_stream_wait_for_data(sslsock->ssl_handle, sock);
                        if (sock->timeout_event) {
                                stream->eof = 1;
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL read operation timed out");
--
1.7.1
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC