From:             frase at cs dot wisc dot edu
Operating system: Windows 2000 Pro SP4
PHP version:      5.2.9
PHP Bug Type:     OpenSSL related
Bug description:  stream_socket_client(ssl:// ... STREAM_CLIENT_ASYNC_CONNECT) 
fails

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 bug report at http://bugs.php.net/?id=48182&edit=1
-- 
Try a CVS snapshot (PHP 5.2):        
http://bugs.php.net/fix.php?id=48182&r=trysnapshot52
Try a CVS snapshot (PHP 5.3):        
http://bugs.php.net/fix.php?id=48182&r=trysnapshot53
Try a CVS snapshot (PHP 6.0):        
http://bugs.php.net/fix.php?id=48182&r=trysnapshot60
Fixed in CVS:                        
http://bugs.php.net/fix.php?id=48182&r=fixedcvs
Fixed in CVS and need be documented: 
http://bugs.php.net/fix.php?id=48182&r=needdocs
Fixed in release:                    
http://bugs.php.net/fix.php?id=48182&r=alreadyfixed
Need backtrace:                      
http://bugs.php.net/fix.php?id=48182&r=needtrace
Need Reproduce Script:               
http://bugs.php.net/fix.php?id=48182&r=needscript
Try newer version:                   
http://bugs.php.net/fix.php?id=48182&r=oldversion
Not developer issue:                 
http://bugs.php.net/fix.php?id=48182&r=support
Expected behavior:                   
http://bugs.php.net/fix.php?id=48182&r=notwrong
Not enough info:                     
http://bugs.php.net/fix.php?id=48182&r=notenoughinfo
Submitted twice:                     
http://bugs.php.net/fix.php?id=48182&r=submittedtwice
register_globals:                    
http://bugs.php.net/fix.php?id=48182&r=globals
PHP 4 support discontinued:          http://bugs.php.net/fix.php?id=48182&r=php4
Daylight Savings:                    http://bugs.php.net/fix.php?id=48182&r=dst
IIS Stability:                       
http://bugs.php.net/fix.php?id=48182&r=isapi
Install GNU Sed:                     
http://bugs.php.net/fix.php?id=48182&r=gnused
Floating point limitations:          
http://bugs.php.net/fix.php?id=48182&r=float
No Zend Extensions:                  
http://bugs.php.net/fix.php?id=48182&r=nozend
MySQL Configuration Error:           
http://bugs.php.net/fix.php?id=48182&r=mysqlcfg

Reply via email to