Skip to content

Commit 0d19984

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
2 parents 9abb0fb + 6b2b60f commit 0d19984

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ PHP NEWS
4141
. Fixed bug GH-18898 (SEGV zend_jit_op_array_hot with property hooks
4242
and preloading). (nielsdos)
4343

44+
- OpenSSL:
45+
. Fixed bug #80770 (It is not possible to get client peer certificate with
46+
stream_socket_server). (Jakub Zelenka)
47+
4448
- PCNTL:
4549
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
4650
pcntl_forkx() with zend-max-execution-timers). (Arnaud)

ext/openssl/tests/bug80770.phpt

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
--TEST--
2+
Bug #80770: SNI_server_certs does not inherit peer verification options
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists("proc_open")) die("skip no proc_open");
8+
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
9+
?>
10+
--FILE--
11+
<?php
12+
$clientCertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug80770_client.pem.tmp';
13+
$caCertFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug80770_ca.pem.tmp';
14+
15+
$serverCode = <<<'CODE'
16+
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
17+
$ctx = stream_context_create(['ssl' => [
18+
'SNI_server_certs' => [
19+
"cs.php.net" => __DIR__ . "/sni_server_cs.pem",
20+
"uk.php.net" => __DIR__ . "/sni_server_uk.pem",
21+
"us.php.net" => __DIR__ . "/sni_server_us.pem"
22+
],
23+
'verify_peer' => true,
24+
'cafile' => '%s',
25+
'capture_peer_cert' => true,
26+
'verify_peer_name' => false,
27+
'security_level' => 0,
28+
]]);
29+
$server = stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr, $flags, $ctx);
30+
phpt_notify_server_start($server);
31+
32+
$client = stream_socket_accept($server, 30);
33+
if ($client) {
34+
$success = stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER);
35+
if ($success) {
36+
$options = stream_context_get_options($client);
37+
$hasCert = isset($options['ssl']['peer_certificate']);
38+
phpt_notify(message: $hasCert ? "CLIENT_CERT_CAPTURED" : "NO_CLIENT_CERT");
39+
} else {
40+
phpt_notify(message: "TLS_HANDSHAKE_FAILED");
41+
}
42+
} else {
43+
phpt_notify(message: "ACCEPT_FAILED");
44+
}
45+
CODE;
46+
$serverCode = sprintf($serverCode, $caCertFile);
47+
48+
$clientCode = <<<'CODE'
49+
$flags = STREAM_CLIENT_CONNECT;
50+
$ctx = stream_context_create(['ssl' => [
51+
'verify_peer' => false,
52+
'verify_peer_name' => false,
53+
'local_cert' => '%s',
54+
'peer_name' => 'cs.php.net',
55+
'security_level' => 0,
56+
]]);
57+
$client = stream_socket_client("tcp://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx);
58+
if ($client) {
59+
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
60+
}
61+
62+
$result = phpt_wait();
63+
echo trim($result);
64+
CODE;
65+
$clientCode = sprintf($clientCode, $clientCertFile);
66+
67+
include 'CertificateGenerator.inc';
68+
69+
// Generate CA and client certificate signed by that CA
70+
$certificateGenerator = new CertificateGenerator();
71+
$certificateGenerator->saveCaCert($caCertFile);
72+
$certificateGenerator->saveNewCertAsFileWithKey('Bug80770 Test Client', $clientCertFile);
73+
74+
include 'ServerClientTestCase.inc';
75+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
76+
?>
77+
--CLEAN--
78+
<?php
79+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug80770_client.pem.tmp');
80+
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug80770_ca.pem.tmp');
81+
?>
82+
--EXPECTF--
83+
CLIENT_CERT_CAPTURED

ext/openssl/xp_ssl.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,8 @@ static SSL_CTX *php_openssl_create_sni_server_ctx(char *cert_path, char *key_pat
14391439
}
14401440
/* }}} */
14411441

1442-
static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
1442+
static zend_result php_openssl_enable_server_sni(
1443+
php_stream *stream, php_openssl_netstream_data_t *sslsock, bool verify_peer)
14431444
{
14441445
zval *val;
14451446
zval *current;
@@ -1560,6 +1561,12 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl
15601561
return FAILURE;
15611562
}
15621563

1564+
if (!verify_peer) {
1565+
php_openssl_disable_peer_verification(ctx, stream);
1566+
} else if (FAILURE == php_openssl_enable_peer_verification(ctx, stream)) {
1567+
return FAILURE;
1568+
}
1569+
15631570
sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream));
15641571
sslsock->sni_certs[i].ctx = ctx;
15651572
++i;
@@ -1570,7 +1577,6 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl
15701577

15711578
return SUCCESS;
15721579
}
1573-
/* }}} */
15741580

15751581
static void php_openssl_enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
15761582
{
@@ -1662,6 +1668,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
16621668
char *cipherlist = NULL;
16631669
char *alpn_protocols = NULL;
16641670
zval *val;
1671+
bool verify_peer = false;
16651672

16661673
if (sslsock->ssl_handle) {
16671674
if (sslsock->s.is_blocked) {
@@ -1713,8 +1720,11 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
17131720

17141721
if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) {
17151722
php_openssl_disable_peer_verification(sslsock->ctx, stream);
1716-
} else if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) {
1717-
return FAILURE;
1723+
} else {
1724+
verify_peer = true;
1725+
if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) {
1726+
return FAILURE;
1727+
}
17181728
}
17191729

17201730
/* callback for the passphrase (for localcert) */
@@ -1815,7 +1825,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream,
18151825

18161826
#ifdef HAVE_TLS_SNI
18171827
/* Enable server-side SNI */
1818-
if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock) == FAILURE) {
1828+
if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock, verify_peer) == FAILURE) {
18191829
return FAILURE;
18201830
}
18211831
#endif

0 commit comments

Comments
 (0)