ID:               47236
 Comment by:       ryan+phpbugs at sleevi dot com
 Reported By:      BenBE at geshi dot org
 Status:           Verified
 Bug Type:         OpenSSL related
 Operating System: *
 PHP Version:      5.*, 6CVS (2009-01-31)
 New Comment:

This is a documentation bug. I am unable to find any documentation that
explicitly states the wrapper for SSL (v2 | v3) and TLS (v1), in
addition to HTTPS and FTPS, is always 'SSL'

The documentation at
http://us.php.net/manual/en/function.stream-context-set-option.php
simply states you must supply 'wrapper', but
http://us.php.net/manual/en/context.ssl.php fails to explicitly state
that the 'wrapper' value is 'ssl' (although one may infer from the
title)

Below is the proper code, which makes a distinction between the wrapper
(used to set/retrieve options) and the mode (or protocol, which can be
'ssl', 'tls', 'sslv2' or 'sslv3' as documented at
http://us.php.net/manual/en/transports.inet.php )

<?php
$wrapper = 'ssl'; // never changes
$protocol = 'tls'; // or 'ssl' or 'sslv2' or 'sslv3'
$site_cert = NULL;
$context = stream_context_create();
$result = stream_context_set_option($context, $wrapper, 'verify_host',
true);
$result = stream_context_set_option($context, $wrapper,
'capture_peer_cert', true);
if ($fp = stream_socket_client("$protocol://ssl.example.de:443/",
$errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context)) {
    if ($options = stream_context_get_options($context)) {
        var_dump($options);
        if (isset($options[$wrapper]) &&
            isset($options[$wrapper]['peer_certificate'])) {
            $site_cert = $options[$wrapper]['peer_certificate'];
        }
    }
    fclose($fp);
}
if ($site_cert) {
    openssl_x509_export($site_cert, $str_cert);
    $pubkey = openssl_pkey_get_public($str_cert);
    $keyinfo = openssl_pkey_get_details($pubkey);
    var_dump($keyinfo);
}


Previous Comments:
------------------------------------------------------------------------

[2009-01-29 04:41:31] BenBE at geshi dot org

Description:
------------
When trying to capture the server certificate of an TLS socket
connection using the stream_socket_client API no certificate is
captured. If connecting to the same host via SSL transport everything
works fine. The remote server is known to support TLSv1 properly.

Reproduce code:
---------------
<?php $mode = "tls";
$site_cert = NULL;
$context = stream_context_create();
$result = stream_context_set_option($context, $mode, 'verify_host',
true);
$result = stream_context_set_option($context, $mode,
'capture_peer_cert', true);
if ($fp = stream_socket_client("$mode://ssl.example.de:443/", $errno,
$errstr, 30, STREAM_CLIENT_CONNECT, $context)) {
    if ($options = stream_context_get_options($context)) {
        var_dump($options);
        if (isset($options[$mode]) &&
isset($options[$mode]['peer_certificate'])) {
            $site_cert = $options[$mode]['peer_certificate'];
        }
    }
    fclose($fp);
}
if ($site_cert) {
    openssl_x509_export($site_cert, $str_cert);
    $pubkey = openssl_pkey_get_public($str_cert);
    $keyinfo = openssl_pkey_get_details($pubkey);
    var_dump($keyinfo);
}


Expected result:
----------------
The first var_dump should contain a resource for the peer_certificate,
both when $mode='ssl' AND $mode='tls'. The second dump should include
the PEM-encoded public key of the server as well as some info on the
key.

Actual result:
--------------
When $mode is set to 'tls' the 'peer_certificate' index in the first
dump is missing and no second dump is written. When $mode='ssl'
everything works as expected.


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=47236&edit=1

Reply via email to