diff --git a/ext/openssl/tests/peer_verification_ipv6_san.phpt b/ext/openssl/tests/peer_verification_ipv6_san.phpt new file mode 100644 index 000000000000..109fec1358da --- /dev/null +++ b/ext/openssl/tests/peer_verification_ipv6_san.phpt @@ -0,0 +1,64 @@ +--TEST-- +Peer verification matches an IPADDR SAN when connecting to a bracketed IPv6 URI +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s' + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 3); + if ($client) { + fwrite($client, "HELLO\n"); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $serverUri = "ssl://{{ ADDR }}"; + $clientFlags = STREAM_CLIENT_CONNECT; + $clientCtx = stream_context_create(['ssl' => [ + 'cafile' => '%s', + ]]); + + $client = @stream_socket_client($serverUri, $errno, $errstr, 3, $clientFlags, $clientCtx); + if (!$client) { + echo "connect failed: $errstr\n"; + return; + } + echo trim(fread($client, 16)), "\n"; +CODE; +$clientCode = sprintf($clientCode, $cacertFile); + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveCaCert($cacertFile); +$certificateGenerator->saveNewCertAsFileWithKey('ipv6-san', $certFile, null, 'IP:::1'); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +HELLO diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index ffacd8a107b7..796427681db5 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2760,6 +2760,13 @@ static char *php_openssl_get_url_name(const char *resourcename, return NULL; } + if (resourcenamelen >= 2 && resourcename[0] == '[') { + const char *end = memchr(resourcename, ']', resourcenamelen); + if (end != NULL && end > resourcename + 1) { + return pestrndup(resourcename + 1, end - resourcename - 1, is_persistent); + } + } + url = php_url_parse_ex(resourcename, resourcenamelen); if (!url) { return NULL; @@ -2775,6 +2782,11 @@ static char *php_openssl_get_url_name(const char *resourcename, --len; } + if (len >= 2 && host[0] == '[' && host[len-1] == ']') { + host += 1; + len -= 2; + } + if (len) { url_name = pestrndup(host, len, is_persistent); }