ID: 48182 User updated by: frase at cs dot wisc dot edu -Summary: stream_socket_client(ssl:// ... STREAM_CLIENT_ASYNC_CONNECT) fails Reported By: frase at cs dot wisc dot edu Status: Open -Bug Type: OpenSSL related +Bug Type: Sockets related Operating System: * -PHP Version: 5.2.9, 5.3.0RC4 +PHP Version: 5.2.10, 5.3.0 New Comment:
This bug remains also in 5.2.10. Let's try a new summary and changing the category to "Sockets", maybe it will get someone's attention. Previous Comments: ------------------------------------------------------------------------ [2009-06-30 14:28:01] frase at cs dot wisc dot edu This bug remains in 5.3.0 final. ------------------------------------------------------------------------ [2009-06-19 13:38:53] frase at cs dot wisc dot edu This bug is still present in 5.3.0 as of RC4, and also affects Linux hosts. ------------------------------------------------------------------------ [2009-06-08 14:14:30] frase at cs dot wisc dot edu Hate to bump my own bug, but it's been a month. Nobody's concerned that ssl:// streams + ASYNC_CONNECT has this silent failure? And that there's a chance it's causing data intended for ssl:// to instead be transmitted in plaintext? ------------------------------------------------------------------------ [2009-05-07 16:23:49] frase at cs dot wisc dot edu Description: ------------ When opening a socket connection with stream_socket_client() and the ssl:// wrapper, the connect-asynchronously flag (STREAM_CLIENT_ASYNC_CONNECT) causes ssl encryption to fail. Connecting asynchronously with tcp:// works, as does connecting synchronously with ssl://. If I remove the ASYNC flag from the example code, I get normal HTTP headers and HTML content. If I leave the flag but change the scheme to tcp:// and port to 80, launchpad.net gives me a normal HTTP/HTML redirect to the encrypted url (https://...). But as written, I instead get an error from the server indicating that my request could not be decrypted via SSL, and no HTTP headers whatsoever. I'm not sure if this bug is more properly "OpenSSL related" or "Sockets related", so I've guessed the former. But I wonder if maybe stream_select() considers the socket writable once it's opened, but before the SSL handshake is complete; that might cause this code to fwrite() too early, possibly going out plaintext. Then I suppose the solution is for stream_select() to not return ssl:// sockets until the handshake is complete, in addition to simply being opened. Reproduce code: --------------- <?php header('Content-type: text/plain'); $scheme = 'ssl://'; $host = 'launchpad.net'; $port = 443; $path = '/'; $begin = microtime(true); $flags = STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT; echo "resolving ".$host."...\n"; $ip = gethostbyname($host); echo "connecting to ".$ip."...\n"; $errno = null; $errstr = null; $socket = stream_socket_client($scheme.$ip.':'.$port, $errno, $errstr, 10, $flags); stream_set_blocking($socket, 0); echo "sending HTTP GET ".$path."...\n"; $data = "GET ".$path." HTTP/1.0\r\n" . "Host: ".$host."\r\n" . "Connection: close\r\n" . "\r\n"; $selR = null; $selW = array($socket); $selE = null; while ($data) { $selW[0] = $socket; if (stream_select($selR, $selW, $selE, 0, 50000)) { $wrote = fwrite($socket, $data, strlen($data)); $data = substr($data, $wrote); } } echo "waiting for data...\n"; $html = ""; $selR = array($socket); $selW = null; $selE = null; $timeout = microtime(true) + 30; while (!feof($socket)) { $selR[0] = $socket; if (stream_select($selR, $selW, $selE, 0, 50000)) $html .= fread($socket, 8192); } fclose($socket); echo "got ".strlen($html)." bytes in ".(microtime(true)-$begin)." seconds\n"; echo "----------\n".$html; Expected result: ---------------- The HTTP headers and HTML source for launchpad.net's main page, i.e.: HTTP/1.1 200 OK ... <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"> <head> <title>Launchpad</title> ... etc Actual result: -------------- An HTML source error message: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>400 Bad Request</title> </head><body> <h1>Bad Request</h1> <p>Your browser sent a request that this server could not understand.<br /> Reason: You're speaking plain HTTP to an SSL-enabled server port.<br /> Instead use the HTTPS scheme to access this URL, please.<br /> <blockquote>Hint: <a href="https://launchpad.net/"><b>https://launchpad.net/</b></a></blockquote></p> <hr> <address>Apache/2.2.8 (Ubuntu) mod_ssl/2.2.8 OpenSSL/0.9.8g Server at launchpad.net Port 443</address> </body></html> ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=48182&edit=1