|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2007-06-08 01:15 UTC] david at acz dot org
Description: ------------ The default socket timeout does not work with SSL streams. An strace shows PHP calls read(2) and blocks forever. Reproduce code: --------------- Create sleepforever.php: <? for(;;) sleep(1); ?> Try it with HTTP: $ php -n -r 'ini_set("default_socket_timeout", 1); fopen("http://127.0.0.1/sleepforever.php", "r");' Now try it with HTTPS: $ time php -n -r 'ini_set("default_socket_timeout", 1); fopen("https://127.0.0.1/sleepforever.php", "r");' Expected result: ---------------- Warning: fopen(http://127.0.0.1/sleepforever.php): failed to open stream: HTTP request failed! in Command line code on line 1 real 0m2.052s user 0m0.020s sys 0m0.010s Actual result: -------------- The process blocks forever. An strace shows this: connect(3, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 1000) = 1 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 fcntl64(3, F_SETFL, O_RDWR) = 0 write(3, "\200j\1\3\1\0Q\0\0\0\20\0\0\26\0\0\23\0\0\n\7\0\300\0\0"..., 108) = 108 read(3, "\26\3\1\0J\2\0", 7) = 7 *** ELIDED *** write(3, "\27\3\1\0\30N~h\231u\31S]94^\253\235\26t\324\214\t/\261"..., 29) = 29 poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 read(3, *** THIS BLOCKS FOREVER *** Patchesssl_read_timeout-5.4.32.patch (last revision 2014-09-29 18:44 UTC by askalski at synacor dot com)bug41631.patch (last revision 2014-09-19 15:13 UTC by rdlowrey@php.net) Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Nov 09 04:00:01 2025 UTC |
I have a (partial?) fix: Index: main/streams/xp_socket.c =================================================================== RCS file: /repository/php-src/main/streams/xp_socket.c,v retrieving revision 1.33.2.2.2.4 diff -u -p -d -r1.33.2.2.2.4 xp_socket.c --- main/streams/xp_socket.c 1 Jan 2007 09:36:12 -0000 1.33.2.2.2.4 +++ main/streams/xp_socket.c 8 Jun 2007 15:55:57 -0000 @@ -103,7 +103,7 @@ retry: return didwrite; } -static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) +void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) { int retval; struct timeval *ptimeout; Index: ext/openssl/xp_ssl.c =================================================================== RCS file: /repository/php-src/ext/openssl/xp_ssl.c,v retrieving revision 1.22.2.3.2.8 diff -u -p -d -r1.22.2.3.2.8 xp_ssl.c --- ext/openssl/xp_ssl.c 27 May 2007 17:05:51 -0000 1.22.2.3.2.8 +++ ext/openssl/xp_ssl.c 8 Jun 2007 15:55:57 -0000 @@ -35,6 +35,8 @@ #include <sys/select.h> #endif +void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC); + int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC); SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC); int php_openssl_get_x509_list_id(void); @@ -219,6 +221,12 @@ static size_t php_openssl_sockop_read(ph php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; int nr_bytes = 0; + if (sslsock->s.is_blocked) { + php_sock_stream_wait_for_data(stream, &(sslsock->s) TSRMLS_CC); + if (sslsock->s.timeout_event) + return 0; + } + if (sslsock->ssl_active) { int retry = 1;Had this issue over the weekend with 5.2.10. Essentially this means our entire service is vulnerable to Denial of Service. Linux localhost.localdomain 2.6.18-164.el5 #1 SMP Thu Sep 3 03:33:56 EDT 2009 i686 i686 i386 GNU/Linux CentOS release 5.3 (Final) PHP 5.2.10 (cli) (built: Jun 21 2009 11:10:43) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend TechnologiesA simple solution is to use HAProxy to proxy SSL partner services. Works for me. defaults mode tcp contimeout 5000 clitimeout 30000 srvtimeout 30000 listen service.gjensidigebaltic.lv 127.0.0.1:10001 dispatch 193.111.247.167:443 listen services.seesam.lv 127.0.0.1:10007 dispatch 217.28.49.7:443Hi, i've tested on 5.2.17 and 5.3.2 with the same result. As described i've used this script: time php -n -r 'ini_set("default_socket_timeout", 1); fopen("https://mydomain.it/sleep.php", "r");' but it doesn't wait 1 sec but 15 as into sleep.php page.This Problem also affects Roundcube Webmail 1.0.2 PHP 5.5.17-1~dotdeb.1 (cli) (built: Sep 19 2014 01:56:56) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies [26-Sep-2014 16:02:55 Europe/Berlin] PHP Warning: fgets(): SSL read operation timed out in [...]/program/lib/Roundcube/rcube_imap_generic.php on line 200 /** * Reads line from the connection stream * * @param int $size Buffer size * * @return string Line of text response */ function readLine($size=1024) { $line = ''; if (!$size) { $size = 1024; } do { if ($this->eof()) { return $line ? $line : NULL; } // Line 200: SSL read operation timed out $buffer = fgets($this->fp, $size); if ($buffer === false) { $this->closeSocket(); break; } if ($this->_debug) { $this->debug('S: '. rtrim($buffer)); } $line .= $buffer; } while (substr($buffer, -1) != "\n"); return $line; }Both versions of the patch (bug41631.patch and ssl_read_timeout-5.4.32.patch) need more rigorous testing before they can be released. I'm willing to help devise a set of tests we can use to validate the implementation. To illustrate the point without getting to deep into things (it's still the weekend!), here's a test which fails on bug41631.patch, and gives an endless stream of warnings: <?php /* nonblocking-write.php */ $ssl = fsockopen("ssl://localhost", 6767); stream_set_blocking($ssl, 0); while (fwrite($ssl, str_repeat("x", 65536)) !== false); ?> # Window 1 $ sudo tc qdisc add dev lo root netem delay 100ms $ openssl s_server -cert server.pem -key server.key -accept 6767 >/dev/null ... $ sudo tc qdisc del dev lo root netem delay 100ms # Window 2 $ php nonblocking-write.php Warning: fwrite(): SSL operation failed with code 1. OpenSSL Error messages: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry in /home/askalski/work/php-bug41631/nonblocking-write.php on line 4 The artificial network delay via the NetEm driver is not required to reproduce the error, but rather makes it more reliable to reproduce. Don't forget to remove the delay after you're done testing. You can verify it's removed by checking the ping times of "ping localhost". If you need to generate a self-signed key for testing with "openssl s_server", here's a quick and dirty way: $ openssl genrsa -out server.key $ yes "" | openssl req -new -key server.key -out certreq.csr ; echo $ openssl x509 -req -days 3650 -in certreq.csr -signkey server.key -out server.pemI have a problem with SOAP over SSL after the fix in 5.4.33 on FreeBSD. 5.4.32 works fine, but this test case does not work in 5.4.33: $client = new SoapClient('test.wsdl', array('cache_wsdl' => WSDL_CACHE_NONE, 'trace' => true, 'exceptions' => false, 'connection_timeout' => 15)); $data = $client->get_long_soap_response_over_https($param); echo "__getLastRequest:\n"; echo $client->__getLastRequest(); echo "\n\n__getLastRequestHeaders:\n"; echo $client->__getLastRequestHeaders(); echo "\n\n__getLastResponse:\n"; echo $client->__getLastResponse(); After the timeout the output for last request and last request headers looks fine, but the response is truncated after a certain size. I didn't save the failed output, but the expected response size was 76800 bytes (+ header), but was truncated I think around 72000 bytes. The same test done over http or with 5.4.32 works fine, so I can only assume that the "fix" for this bug is causing this.