. Implemented unified default encoding
(RFC: https://wiki.php.net/rfc/default_encoding). (Yasuo Ohgaki)
+- Curl
+ . Check for openssl.cafile ini directive when loading CA certs. (Daniel Lowrey)
+
- Fileinfo
. Upgraded to libmagic-5.17 (Anatol)
. Fallback to Windows CA cert store for peer verification if no openssl.cafile
ini directive or "cafile" SSL context option specified in Windows.
(Chris Wright)
+ . The openssl.cafile and openssl.capath ini directives introduced in alpha2
+ now have PHP_INI_PERDIR accessibility (was PHP_INI_ALL). (Daniel Lowrey)
+ . New "peer_name" SSL context option replaces "CN_match" (which still works
+ as before but triggers E_DEPRECATED). (Daniel Lowrey)
. Fixed segfault when accessing non-existent context for client SNI use
(Daniel Lowrey)
. Fixed bug #66501 (Add EC key support to php_openssl_is_private_key).
(Mark Zedwood)
- . Fixed Bug #47030 (add new boolean "verify_host" SSL context option
- allowing clients to verify names separately from peer certs).
+ . Fixed Bug #47030 (add new boolean "verify_peer_name" SSL context option
+ allowing clients to verify cert names separately from the cert itself).
+ "verify_peer_name" is enabled by default for client streams.
(Daniel Lowrey)
. Fixed Bug #65538 ("cafile" SSL context option now supports stream
wrappers). (Daniel Lowrey)
- Added gost-crypto (CryptoPro S-box) hash algo.
-- Stream wrappers verify peers and host names by default in encrypted client
- streams.
+- Stream wrappers verify peer certificates and host names by default in
+ encrypted client streams.
- Added openssl certificate fingerprint support (inclusive stream context
option).
- Added "crypto_method" SSL context option for use in encrypted streams.
+- Added "peer_name" SSL context option to better reflect peer certificate
+ name matching using SAN extension (replaces deprecated "CN_match").
+
- Added stream wrapper support when specifying "cafile" SSL context paths.
-- Independent peer cert and host names validation is now available via a new
- "verify_host" SSL context option.
+- Independent peer cert and peer name validation is now available via a new
+ boolean "verify_peer_name" SSL context option. This option is enabled by
+ default in encrypted client streams.
- Added protocol-specific tlsv1.0://, tlsv1.1:// and tlsv1.2:// encryption
stream wrappers. tls:// wrapper now supports TLSv1.1 and TLSv1.2 (previously
Instance calls from an incompatible context are now deprecated and issue
E_DEPRECATED instead of E_STRICT. See https://wiki.php.net/rfc/incompat_ctx
+- The "CN_match" SSL context option is deprecated in favor of the new
+ "peer_name" option. Name verification now checks certificate SAN names as
+ well as the CN field and "CN_match" is deprecated to avoid confusion. Its
+ use triggers E_DEPRECATED but continues to work as before. If both values
+ are specified "CN_match" takes precedence. Otherwise, the two options are
+ interchangeable.
+
========================================
4. Changed Functions
========================================
int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */
{
zval **val = NULL;
- char *cnmatch = NULL;
+ char *peer_name = NULL;
int err;
zend_bool must_verify_peer;
- zend_bool must_verify_host;
+ zend_bool must_verify_peer_name;
zend_bool must_verify_fingerprint;
+ zend_bool has_cnmatch_ctx_opt;
php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
must_verify_peer = GET_VER_OPT("verify_peer")
? zend_is_true(*val)
: sslsock->is_client;
- must_verify_host = GET_VER_OPT("verify_host")
+ has_cnmatch_ctx_opt = GET_VER_OPT("CN_match");
+ must_verify_peer_name = (has_cnmatch_ctx_opt || GET_VER_OPT("verify_peer_name"))
? zend_is_true(*val)
: sslsock->is_client;
must_verify_fingerprint = (GET_VER_OPT("peer_fingerprint") && zend_is_true(*val));
- if ((must_verify_peer || must_verify_host || must_verify_fingerprint) && peer == NULL) {
+ if ((must_verify_peer || must_verify_peer_name || must_verify_fingerprint) && peer == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not get peer certificate");
return FAILURE;
}
}
}
- /* If a peer_fingerprint match is required this trumps host verification */
+ /* If a peer_fingerprint match is required this trumps peer and peer_name verification */
if (must_verify_fingerprint) {
if (Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_ARRAY) {
if (!php_x509_fingerprint_match(peer, *val TSRMLS_CC)) {
}
/* verify the host name presented in the peer certificate */
+ if (must_verify_peer_name) {
+ GET_VER_OPT_STRING("peer_name", peer_name);
- if (must_verify_host) {
- GET_VER_OPT_STRING("CN_match", cnmatch);
- /* If no CN_match was specified assign the autodetected url name in client environments */
- if (cnmatch == NULL && sslsock->is_client) {
- cnmatch = sslsock->url_name;
+ if (has_cnmatch_ctx_opt) {
+ GET_VER_OPT_STRING("CN_match", peer_name);
+ php_error(E_DEPRECATED,
+ "the 'CN_match' SSL context option is deprecated in favor of 'peer_name'"
+ );
+ }
+ /* If no peer name was specified we use the autodetected url name in client environments */
+ if (peer_name == NULL && sslsock->is_client) {
+ peer_name = sslsock->url_name;
}
- if (cnmatch) {
- if (matches_san_list(peer, cnmatch TSRMLS_CC)) {
+ if (peer_name) {
+ if (matches_san_list(peer, peer_name TSRMLS_CC)) {
return SUCCESS;
- } else if (matches_common_name(peer, cnmatch TSRMLS_CC)) {
+ } else if (matches_common_name(peer, peer_name TSRMLS_CC)) {
return SUCCESS;
} else {
return FAILURE;
LPWSTR server_name = NULL;
BOOL verify_result;
- { /* This looks ridiculous and it is - but we validate the name ourselves using the CN_match
+ { /* This looks ridiculous and it is - but we validate the name ourselves using the peer_name
ctx option, so just use the CN from the cert here */
X509_NAME *cert_name;
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'verify_host' => false
+ 'verify_peer_name' => false
]]);
phpt_wait();
$clientFlags = STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT;
$clientCtx = stream_context_create(['ssl' => [
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local'
+ 'peer_name' => 'bug54992.local'
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'buga_buga',
+ 'peer_name' => 'buga_buga',
]]);
phpt_wait();
$serverUri = "https://127.0.0.1:64321/";
$clientCtx = stream_context_create(['ssl' => [
'cafile' => 'file://' . __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$serverUri = "https://127.0.0.1:64321/";
$clientCtx = stream_context_create(['ssl' => [
'cafile' => 'phar://' . __DIR__ . '/bug65538.phar/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'allow_self_signed' => true,
- 'CN_match' => $expected_name,
+ 'peer_name' => $expected_name,
]]);
var_dump(stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx));
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
'capture_peer_cert' => true,
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
// Should succeed with peer verification disabled in context
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'verify_host' => false,
+ 'verify_peer_name' => false,
]]);
var_dump(stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx));
// Should succeed with CA file specified in context
$clientCtx = stream_context_create(['ssl' => [
'cafile' => $caFile,
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
var_dump(stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx));
CODE;
phpt_wait();
- stream_context_set_option($clientCtx, 'ssl', 'CN_match', 'example.org');
+ stream_context_set_option($clientCtx, 'ssl', 'peer_name', 'example.org');
var_dump(stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx));
- stream_context_set_option($clientCtx, 'ssl', 'CN_match', 'moar.example.org');
+ stream_context_set_option($clientCtx, 'ssl', 'peer_name', 'moar.example.org');
var_dump(stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx));
CODE;
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
'capture_session_meta' => true,
]]);
stream_context_set_option($ctx, 'ssl', 'capture_peer_cert', true);
stream_context_set_option($ctx, 'ssl', 'verify_peer', false);
if ($host) {
- stream_context_set_option($ctx, 'ssl', 'CN_match', $host);
+ stream_context_set_option($ctx, 'ssl', 'peer_name', $host);
} else {
- stream_context_set_option($ctx, 'ssl', 'verify_host', false);
+ stream_context_set_option($ctx, 'ssl', 'verify_peer_name', false);
}
return $ctx;
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'CN_match' => 'bug54992.local',
+ 'peer_name' => 'bug54992.local',
]]);
phpt_wait();
$clientFlags = STREAM_CLIENT_CONNECT;
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'CN_match' => 'bug54992.local'
+ 'peer_name' => 'bug54992.local'
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => __DIR__ . '/bug54992-ca.pem',
- 'verify_host' => false
+ 'verify_peer_name' => false
]]);
phpt_wait();
$clientCtx = stream_context_create(['ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
'verify_peer' => false,
- 'verify_host' => false
+ 'verify_peer_name' => false
]]);
phpt_wait();
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'verify_host' => false,
+ 'verify_peer_name' => false,
]]);
phpt_wait();
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'verify_host' => false,
+ 'verify_peer_name' => false,
]]);
phpt_wait();
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
- 'verify_host' => false,
+ 'verify_peer_name' => false,
]]);
phpt_wait();