php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69345 tls:// wrapper disables TLS 1.1+
Submitted: 2015-04-01 10:39 UTC Modified: 2015-04-01 13:18 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:2 (100.0%)
From: cf0hay at gmail dot com Assigned: rdlowrey (profile)
Status: Wont fix Package: Sockets related
PHP Version: 5.6.7 OS: Linux 64bit
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: cf0hay at gmail dot com
New email:
PHP Version: OS:

 

 [2015-04-01 10:39 UTC] cf0hay at gmail dot com
Description:
------------
When creating a socket through tls:// wrapper, any TLS version over TLS 1.0 is disabled, even with the library supports higher versions. Only TLS 1.0 accepted. With ssl:// this problem does not occur.

tls:// should enable everything over TLS 1.0 too. At the present moment it's impossible to to create a socket with TLS 1.2 support but without SSL 3 (because of POODLE).

Test script:
---------------
<?php
stream_socket_accept(
    stream_socket_server(
        "tls://127.0.0.1:4433",
        $errno,
        $errstr,
        STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
        stream_context_create([
            "ssl" => [
                 "ciphers" => "AECDH-AES256-SHA",
            ],
        ])
    )
);



Expected result:
----------------
start the test script in one console, and issue this in another:
$ openssl s_client -tls1_2 -cipher AECDH-AES256-SHA
[...]
    Cipher    : AECDH-AES256-SHA
[...]
The PHP script should end silently.

Actual result:
--------------
start the test script in one console, and issue this in another:
$ openssl s_client -tls1_2 -cipher AECDH-AES256-SHA
[...]
[...]error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number[...]
[...]
The PHP script throws warnings before exiting:
PHP Warning:  stream_socket_accept(): SSL operation failed with code 1. OpenSSL Error messages:
error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version

PHP Warning:  stream_socket_accept(): Failed to enable crypto

PHP Warning:  stream_socket_accept(): accept failed: Success


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-04-01 13:18 UTC] rdlowrey@php.net
-Status: Open +Status: Analyzed -Assigned To: +Assigned To: rdlowrey
 [2015-04-01 13:18 UTC] rdlowrey@php.net
Prior to PHP 5.6 the tls:// wrapper specifically used the TLSv1 handshake method because at the time the code was written that was the only TLS protocol supported by the underlying openssl lib. As of 5.6.0 this behavior was changed to use the broadly compatible SSLv23 handshake method (but only allow the negotiation of TLSv1, TLSv1.1 or TLSv1.2). Likewise the ssl:// wrapper was modified to only negotiate SSL protocols with the goal being to encourage users to move to the more semantically appropriate tls:// wrapper going forward.

However, after a lengthy discussion about this on the security mailing list these changes were deemed too much of a BC break and it was determined that the behavior should be reverted to use the old handshake method in 5.6.7. This means that all code wishing to support multiple protocol handshakes should use the ssl:// wrapper going forward. If you wish to only allow the negotiation of TLS protocols in your handshake you should use the "crypto_method" ssl context option to specify the protocols you wish to support as shown here:


<?php
$methodBitmask = STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | STREAM_CRYPTO_METHOD_TLSv1_1_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
$context = stream_context_create(["ssl" => [
    "ciphers" => "AECDH-AES256-SHA",
    "crypto_method" => $methodBitmask
]]);
stream_socket_server(
    "tls://127.0.0.1:4433",
    $errno,
    $errstr,
    STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    $context
);

Assigning a specific "crypto_method" bitmask is the only way to exercise fine-grained control over which SSL/TLS protocols are allowed in your encrypted clients/servers regardless of which stream wrapper is in use.

For the record, I agree that tls://should attempt to negotiate any TLS protocol. However, due to the reason listed above I'm marking this as "won't fix" for now. If enough people find this problematic we can instigate a change.
 [2015-04-01 13:18 UTC] rdlowrey@php.net
-Status: Analyzed +Status: Wont fix
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 20 02:01:29 2024 UTC