diff --git a/README.md b/README.md index 5347c31c..350a9482 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,19 @@ $server = new Server('tls://127.0.0.1:8000', $loop, array( )); ``` +By default, this server supports TLSv1.0+ and excludes support for legacy +SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you +want to negotiate with the remote side: + +```php +$server = new Server('tls://127.0.0.1:8000', $loop, array( + 'tls' => array( + 'local_cert' => 'server.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER + ) +)); +``` + > Note that available [TLS context options](http://php.net/manual/en/context.ssl.php), their defaults and effects of changing these may vary depending on your system and/or PHP version. @@ -612,6 +625,18 @@ $server = new SecureServer($server, $loop, array( )); ``` +By default, this server supports TLSv1.0+ and excludes support for legacy +SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you +want to negotiate with the remote side: + +```php +$server = new TcpServer(8000, $loop); +$server = new SecureServer($server, $loop, array( + 'local_cert' => 'server.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_SERVER +)); +``` + > Note that available [TLS context options](http://php.net/manual/en/context.ssl.php), their defaults and effects of changing these may vary depending on your system and/or PHP version. @@ -1000,6 +1025,18 @@ $connector->connect('tls://localhost:443')->then(function (ConnectionInterface $ }); ``` +By default, this connector supports TLSv1.0+ and excludes support for legacy +SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you +want to negotiate with the remote side: + +```php +$connector = new Connector($loop, array( + 'tls' => array( + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT + ) +)); +``` + > For more details about context options, please refer to the PHP documentation about [socket context options](http://php.net/manual/en/context.socket.php) and [SSL context options](http://php.net/manual/en/context.ssl.php). @@ -1189,7 +1226,7 @@ $promise->cancel(); ``` Calling `cancel()` on a pending promise will cancel the underlying TCP/IP -connection and/or the SSL/TLS negonation and reject the resulting promise. +connection and/or the SSL/TLS negotiation and reject the resulting promise. You can optionally pass additional [SSL context options](http://php.net/manual/en/context.ssl.php) @@ -1202,6 +1239,16 @@ $secureConnector = new React\Socket\SecureConnector($dnsConnector, $loop, array( )); ``` +By default, this connector supports TLSv1.0+ and excludes support for legacy +SSLv2/SSLv3. As of PHP 5.6+ you can also explicitly choose the TLS version you +want to negotiate with the remote side: + +```php +$secureConnector = new React\Socket\SecureConnector($dnsConnector, $loop, array( + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT +)); +``` + > Advanced usage: Internally, the `SecureConnector` relies on setting up the required *context options* on the underlying stream resource. It should therefor be used with a `TcpConnector` somewhere in the connector diff --git a/src/StreamEncryption.php b/src/StreamEncryption.php index bb3356ca..ceb29348 100644 --- a/src/StreamEncryption.php +++ b/src/StreamEncryption.php @@ -26,6 +26,13 @@ public function __construct(LoopInterface $loop, $server = true) $this->loop = $loop; $this->server = $server; + // support TLSv1.0+ by default and exclude legacy SSLv2/SSLv3. + // PHP 5.6+ supports bitmasks, legacy PHP only supports predefined + // constants, so apply accordingly below. + // Also, since PHP 5.6.7 up until before PHP 7.2.0 the main constant did + // only support TLSv1.0, so we explicitly apply all versions. + // @link http://php.net/manual/en/migration56.openssl.php#migration56.openssl.crypto-method + // @link https://3v4l.org/plbFn if ($server) { $this->method = STREAM_CRYPTO_METHOD_TLS_SERVER; @@ -78,9 +85,16 @@ public function toggle(Connection $stream, $toggle) // get actual stream socket from stream instance $socket = $stream->stream; + // get crypto method from context options or use global setting from constructor + $method = $this->method; + $context = stream_context_get_options($socket); + if (isset($context['ssl']['crypto_method'])) { + $method = $context['ssl']['crypto_method']; + } + $that = $this; - $toggleCrypto = function () use ($socket, $deferred, $toggle, $that) { - $that->toggleCrypto($socket, $deferred, $toggle); + $toggleCrypto = function () use ($socket, $deferred, $toggle, $method, $that) { + $that->toggleCrypto($socket, $deferred, $toggle, $method); }; $this->loop->addReadStream($socket, $toggleCrypto); @@ -105,10 +119,10 @@ public function toggle(Connection $stream, $toggle) }); } - public function toggleCrypto($socket, Deferred $deferred, $toggle) + public function toggleCrypto($socket, Deferred $deferred, $toggle, $method) { set_error_handler(array($this, 'handleError')); - $result = stream_socket_enable_crypto($socket, $toggle, $this->method); + $result = stream_socket_enable_crypto($socket, $toggle, $method); restore_error_handler(); if (true === $result) { diff --git a/tests/FunctionalSecureServerTest.php b/tests/FunctionalSecureServerTest.php index b15755cc..78a59d00 100644 --- a/tests/FunctionalSecureServerTest.php +++ b/tests/FunctionalSecureServerTest.php @@ -224,6 +224,54 @@ public function testPipesDataBackInMultipleChunksFromConnection() $this->assertEquals(400000, $received); } + /** + * @requires PHP 5.6 + */ + public function testEmitsConnectionForNewTlsv11Connection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER + )); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT + )); + $promise = $connector->connect($server->getAddress()); + + Block\await($promise, $loop, self::TIMEOUT); + } + + /** + * @requires PHP 5.6 + */ + public function testEmitsErrorForClientWithTlsVersionMismatch() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER|STREAM_CRYPTO_METHOD_TLSv1_2_SERVER + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT + )); + $promise = $connector->connect($server->getAddress()); + + $this->setExpectedException('RuntimeException', 'handshake'); + Block\await($promise, $loop, self::TIMEOUT); + } + public function testEmitsConnectionForNewConnectionWithEncryptedCertificate() { $loop = Factory::create(); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy