mirror of
https://github.com/php/php-src.git
synced 2025-01-12 05:54:13 +08:00
1fab01be5b
The idea is to create an easy way to provide a certificate that never expires. In order to make it cross-platform, PHP is used rather than openssl CLI app. Using openssl to generate certificates for tests that test openssl might be not the best idea but pros seem to outweight cons that this "recursice dependency" adds
105 lines
3.2 KiB
PHP
105 lines
3.2 KiB
PHP
--TEST--
|
|
TLS server rate-limits client-initiated renegotiation
|
|
--SKIPIF--
|
|
<?php
|
|
if (!extension_loaded("openssl")) die("skip openssl not loaded");
|
|
if (!function_exists("proc_open")) die("skip no proc_open");
|
|
exec('openssl help', $out, $code);
|
|
if ($code > 0) die("skip couldn't locate openssl binary");
|
|
if(substr(PHP_OS, 0, 3) == 'WIN') {
|
|
die('skip not suitable for Windows');
|
|
}
|
|
?>
|
|
--FILE--
|
|
<?php
|
|
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'stream_server_reneg_limit.pem.tmp';
|
|
|
|
/**
|
|
* This test uses the openssl binary directly to initiate renegotiation. At this time it's not
|
|
* possible renegotiate the TLS handshake in PHP userland, so using the openssl s_client binary
|
|
* command is the only feasible way to test renegotiation limiting functionality. It's not an ideal
|
|
* solution, but it's really the only way to get test coverage on the rate-limiting functionality
|
|
* given current limitations.
|
|
*/
|
|
|
|
$serverCode = <<<'CODE'
|
|
$printed = false;
|
|
$serverUri = "ssl://127.0.0.1:64321";
|
|
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
|
|
$serverCtx = stream_context_create(['ssl' => [
|
|
'local_cert' => '%s',
|
|
'reneg_limit' => 0,
|
|
'reneg_window' => 30,
|
|
'reneg_limit_callback' => function($stream) use (&$printed) {
|
|
if (!$printed) {
|
|
$printed = true;
|
|
var_dump($stream);
|
|
}
|
|
}
|
|
]]);
|
|
|
|
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
|
|
phpt_notify();
|
|
|
|
$clients = [];
|
|
while (1) {
|
|
$r = array_merge([$server], $clients);
|
|
$w = $e = [];
|
|
|
|
stream_select($r, $w, $e, $timeout=42);
|
|
|
|
foreach ($r as $sock) {
|
|
if ($sock === $server && ($client = stream_socket_accept($server, $timeout = 42))) {
|
|
$clientId = (int) $client;
|
|
$clients[$clientId] = $client;
|
|
} elseif ($sock !== $server) {
|
|
$clientId = (int) $sock;
|
|
$buffer = fread($sock, 1024);
|
|
if (strlen($buffer)) {
|
|
continue;
|
|
} elseif (!is_resource($sock) || feof($sock)) {
|
|
unset($clients[$clientId]);
|
|
break 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CODE;
|
|
$serverCode = sprintf($serverCode, $certFile);
|
|
|
|
$clientCode = <<<'CODE'
|
|
$cmd = 'openssl s_client -connect 127.0.0.1:64321';
|
|
$descriptorSpec = [["pipe", "r"], ["pipe", "w"], ["pipe", "w"]];
|
|
$process = proc_open($cmd, $descriptorSpec, $pipes);
|
|
|
|
list($stdin, $stdout, $stderr) = $pipes;
|
|
|
|
// Trigger renegotiation twice
|
|
// Server settings only allow one per second (should result in disconnection)
|
|
fwrite($stdin, "R\nR\nR\nR\n");
|
|
|
|
$lines = [];
|
|
while(!feof($stderr)) {
|
|
fgets($stderr);
|
|
}
|
|
|
|
fclose($stdin);
|
|
fclose($stdout);
|
|
fclose($stderr);
|
|
proc_terminate($process);
|
|
CODE;
|
|
|
|
include 'CertificateGenerator.inc';
|
|
$certificateGenerator = new CertificateGenerator();
|
|
$certificateGenerator->saveNewCertAsFileWithKey('stream_security_level', $certFile);
|
|
|
|
include 'ServerClientTestCase.inc';
|
|
ServerClientTestCase::getInstance()->run($serverCode, $clientCode);
|
|
?>
|
|
--CLEAN--
|
|
<?php
|
|
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'stream_server_reneg_limit.pem.tmp');
|
|
?>
|
|
--EXPECTF--
|
|
resource(%d) of type (stream)
|