Merge branch 'PHP-8.4'

This commit is contained in:
Jakub Zelenka 2025-07-15 11:29:18 +02:00
commit 81d1529a13
No known key found for this signature in database
GPG key ID: 1C0779DC5C0A9DE4
2 changed files with 98 additions and 5 deletions

View file

@ -0,0 +1,83 @@
--TEST--
Bug #80770: SNI_server_certs does not inherit peer verification options
--EXTENSIONS--
openssl
--SKIPIF--
<?php
if (!function_exists("proc_open")) die("skip no proc_open");
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
?>
--FILE--
<?php
$clientCertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug80770_client.pem.tmp';
$caCertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug80770_ca.pem.tmp';
$serverCode = <<<'CODE'
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
$ctx = stream_context_create(['ssl' => [
'SNI_server_certs' => [
"cs.php.net" => __DIR__ . "/sni_server_cs.pem",
"uk.php.net" => __DIR__ . "/sni_server_uk.pem",
"us.php.net" => __DIR__ . "/sni_server_us.pem"
],
'verify_peer' => true,
'cafile' => '%s',
'capture_peer_cert' => true,
'verify_peer_name' => false,
'security_level' => 0,
]]);
$server = stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr, $flags, $ctx);
phpt_notify_server_start($server);
$client = stream_socket_accept($server, 30);
if ($client) {
$success = stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER);
if ($success) {
$options = stream_context_get_options($client);
$hasCert = isset($options['ssl']['peer_certificate']);
phpt_notify(message: $hasCert ? "CLIENT_CERT_CAPTURED" : "NO_CLIENT_CERT");
} else {
phpt_notify(message: "TLS_HANDSHAKE_FAILED");
}
} else {
phpt_notify(message: "ACCEPT_FAILED");
}
CODE;
$serverCode = sprintf($serverCode, $caCertFile);
$clientCode = <<<'CODE'
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'local_cert' => '%s',
'peer_name' => 'cs.php.net',
'security_level' => 0,
]]);
$client = stream_socket_client("tcp://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx);
if ($client) {
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
}
$result = phpt_wait();
echo trim($result);
CODE;
$clientCode = sprintf($clientCode, $clientCertFile);
include 'CertificateGenerator.inc';
// Generate CA and client certificate signed by that CA
$certificateGenerator = new CertificateGenerator();
$certificateGenerator->saveCaCert($caCertFile);
$certificateGenerator->saveNewCertAsFileWithKey('Bug80770 Test Client', $clientCertFile);
include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--CLEAN--
<?php
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug80770_client.pem.tmp');
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug80770_ca.pem.tmp');
?>
--EXPECTF--
CLIENT_CERT_CAPTURED

View file

@ -1324,7 +1324,8 @@ static SSL_CTX *php_openssl_create_sni_server_ctx(char *cert_path, char *key_pat
} }
/* }}} */ /* }}} */
static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ static zend_result php_openssl_enable_server_sni(
php_stream *stream, php_openssl_netstream_data_t *sslsock, bool verify_peer)
{ {
zval *val; zval *val;
zval *current; zval *current;
@ -1445,6 +1446,12 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl
return FAILURE; return FAILURE;
} }
if (!verify_peer) {
php_openssl_disable_peer_verification(ctx, stream);
} else if (FAILURE == php_openssl_enable_peer_verification(ctx, stream)) {
return FAILURE;
}
sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream)); sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream));
sslsock->sni_certs[i].ctx = ctx; sslsock->sni_certs[i].ctx = ctx;
++i; ++i;
@ -1455,7 +1462,6 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl
return SUCCESS; return SUCCESS;
} }
/* }}} */
static void php_openssl_enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ static void php_openssl_enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
{ {
@ -1547,6 +1553,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
char *cipherlist = NULL; char *cipherlist = NULL;
char *alpn_protocols = NULL; char *alpn_protocols = NULL;
zval *val; zval *val;
bool verify_peer = false;
if (sslsock->ssl_handle) { if (sslsock->ssl_handle) {
if (sslsock->s.is_blocked) { if (sslsock->s.is_blocked) {
@ -1594,9 +1601,12 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) { if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) {
php_openssl_disable_peer_verification(sslsock->ctx, stream); php_openssl_disable_peer_verification(sslsock->ctx, stream);
} else if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) { } else {
verify_peer = true;
if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) {
return FAILURE; return FAILURE;
} }
}
/* callback for the passphrase (for localcert) */ /* callback for the passphrase (for localcert) */
if (GET_VER_OPT("passphrase")) { if (GET_VER_OPT("passphrase")) {
@ -1694,7 +1704,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
#ifdef HAVE_TLS_SNI #ifdef HAVE_TLS_SNI
/* Enable server-side SNI */ /* Enable server-side SNI */
if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock) == FAILURE) { if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock, verify_peer) == FAILURE) {
return FAILURE; return FAILURE;
} }
#endif #endif