diff options
author | Andrey Hristov <andrey@php.net> | 2014-01-29 15:32:02 +0200 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2014-01-29 15:32:02 +0200 |
commit | 1c7f54d4f7fe58f1d2c7ed00ca80d93dddc265ab (patch) | |
tree | b981a37d3072a193d0fe9791fc75d3b3b83208f2 | |
parent | fb5c7cda5d776a84730c5133f27e72cb427f22ae (diff) | |
parent | 253a66c8d56e72b166b2d8ebfbc4b368eed4a9fb (diff) | |
download | php-git-1c7f54d4f7fe58f1d2c7ed00ca80d93dddc265ab.tar.gz |
Merge branch 'PHP-5.6'
Conflicts:
NEWS
ext/openssl/xp_ssl.c
25 files changed, 402 insertions, 117 deletions
@@ -24,6 +24,17 @@ PHP X.Y UPGRADE NOTES . dba_delete() now returns false if the key was not found for the inifile handler, too. +- openssl: + To prevent Man-in-the-Middle attacks against encrypted transfers client + streams now verify peer certificates by default. Previous versions + required users to manually enable peer verification. As a result of this + change, existing code using ssl:// or tls:// stream wrappers (e.g. + file_get_contents(), fsockopen(), stream_socket_client()) may no longer + connect successfully without manually disabling peer verification via the + stream context's "verify_peer" setting. Encrypted transfers delegate to + operating system certificate stores by default, so many/most users *should* + be unaffected by this transparent security enhancement. + ======================================== 2. New Features ======================================== diff --git a/ext/mbstring/tests/zend_multibyte-02.phpt b/ext/mbstring/tests/zend_multibyte-02.phpt index 8e15ae8849..84eae89d9e 100644 --- a/ext/mbstring/tests/zend_multibyte-02.phpt +++ b/ext/mbstring/tests/zend_multibyte-02.phpt @@ -1,8 +1,6 @@ --TEST-- zend multibyte (2) --SKIPIF-- ---XFAIL-- -https://bugs.php.net/bug.php?id=66582 --INI-- zend.multibyte=On zend.script_encoding=UTF-8 @@ -11,5 +9,5 @@ mbstring.internal_encoding=CP932 <?php var_dump(bin2hex("テスト")); ?> ---EXPECT-- -string(12) "836583588367" +--EXPECTF-- +php: Zend/zend_language_scanner.l:%d: encoding_filter_script_to_internal: Assertion `internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)' failed. diff --git a/ext/mbstring/tests/zend_multibyte-06.phpt b/ext/mbstring/tests/zend_multibyte-06.phpt index 024a67bbb6..11e263f0b6 100644 --- a/ext/mbstring/tests/zend_multibyte-06.phpt +++ b/ext/mbstring/tests/zend_multibyte-06.phpt @@ -1,8 +1,6 @@ --TEST-- zend multibyte (6) --SKIPIF-- ---XFAIL-- -https://bugs.php.net/bug.php?id=66582 --INI-- zend.multibyte=On zend.script_encoding=EUC-JP @@ -12,5 +10,5 @@ mbstring.internal_encoding=CP932 declare(encoding="UTF-8"); var_dump(bin2hex("テスト")); ?> ---EXPECT-- -string(12) "836583588367" +--EXPECTF-- +php: Zend/zend_language_scanner.l:%d: encoding_filter_script_to_internal: Assertion `internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding)' failed. diff --git a/ext/mbstring/tests/zend_multibyte-10.phpt b/ext/mbstring/tests/zend_multibyte-10.phpt index 4d448a8ccf..139d973b95 100644 --- a/ext/mbstring/tests/zend_multibyte-10.phpt +++ b/ext/mbstring/tests/zend_multibyte-10.phpt @@ -1,8 +1,8 @@ --TEST-- zend multibyte (10) --SKIPIF-- ---XFAIL-- -https://bugs.php.net/bug.php?id=66582 +--INI-- +zend.multibyte=1 --FILE-- <?php declare(encoding="ISO-8859-15"); diff --git a/ext/mbstring/tests/zend_multibyte-11.phpt b/ext/mbstring/tests/zend_multibyte-11.phpt index 91a7d8c44b..c6e45fa5cd 100644 --- a/ext/mbstring/tests/zend_multibyte-11.phpt +++ b/ext/mbstring/tests/zend_multibyte-11.phpt @@ -1,8 +1,8 @@ --TEST-- zend multibyte (11) --SKIPIF-- ---XFAIL-- -https://bugs.php.net/bug.php?id=66582 +--INI-- +zend.multibyte=1 --FILE-- <?php declare(encoding="ISO-8859-15") { diff --git a/ext/mbstring/tests/zend_multibyte-12.phpt b/ext/mbstring/tests/zend_multibyte-12.phpt index 2f2606244c..90968e8820 100644 --- a/ext/mbstring/tests/zend_multibyte-12.phpt +++ b/ext/mbstring/tests/zend_multibyte-12.phpt @@ -1,8 +1,8 @@ --TEST-- zend multibyte (12) --SKIPIF-- ---XFAIL-- -https://bugs.php.net/bug.php?id=66582 +--INI-- +zend.multibyte=1 --FILE-- <?php declare(encoding="ISO-8859-15"); diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 929f776a43..2a5a8c61ff 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -558,6 +558,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY_EX("mysqli.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysqli_globals, mysqli_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX("mysqli.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mysqli_globals, mysqli_globals, display_link_numbers) STD_PHP_INI_BOOLEAN("mysqli.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_mysqli_globals, mysqli_globals) + STD_PHP_INI_BOOLEAN("mysqli.rollback_on_cached_plink", "0",PHP_INI_SYSTEM, OnUpdateBool, rollback_on_cached_plink, zend_mysqli_globals, mysqli_globals) STD_PHP_INI_ENTRY("mysqli.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysqli_globals, mysqli_globals) STD_PHP_INI_ENTRY("mysqli.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysqli_globals, mysqli_globals) STD_PHP_INI_ENTRY("mysqli.default_pw", NULL, PHP_INI_ALL, OnUpdateString, default_pw, zend_mysqli_globals, mysqli_globals) @@ -597,6 +598,7 @@ static PHP_GINIT_FUNCTION(mysqli) #else mysqli_globals->embedded = 0; #endif + mysqli_globals->rollback_on_cached_plink = FALSE; } /* }}} */ diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 9028401595..d6f274b569 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -599,10 +599,20 @@ void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status TSRM #if defined(MYSQLI_USE_MYSQLND) mysqlnd_end_psession(mysql->mysql); #endif - zend_ptr_stack_push(&plist->free_links, mysql->mysql); + if (MyG(rollback_on_cached_plink) && +#if !defined(MYSQLI_USE_MYSQLND) + mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL)) +#else + FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL)) +#endif + { + mysqli_close(mysql->mysql, close_type); + } else { + zend_ptr_stack_push(&plist->free_links, mysql->mysql); + MyG(num_inactive_persistent)++; + } MyG(num_active_persistent)--; - MyG(num_inactive_persistent)++; } } mysql->persistent = FALSE; diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index 61e8e5c81e..3d31b8183c 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -373,6 +373,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_refresh, 0, 0, 1) ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_no_options, 0, 0, 0) +ZEND_END_ARG_INFO() + /* {{{ mysqli_functions[] * @@ -425,6 +428,7 @@ const zend_function_entry mysqli_functions[] = { #endif PHP_FE(mysqli_get_client_info, arginfo_mysqli_only_link) PHP_FE(mysqli_get_client_version, arginfo_mysqli_only_link) + PHP_FE(mysqli_get_links_stats, arginfo_mysqli_no_options) PHP_FE(mysqli_get_host_info, arginfo_mysqli_only_link) PHP_FE(mysqli_get_proto_info, arginfo_mysqli_only_link) PHP_FE(mysqli_get_server_info, arginfo_mysqli_only_link) diff --git a/ext/mysqli/mysqli_fe.h b/ext/mysqli/mysqli_fe.h index d5ae8a6ff9..9a9f851248 100644 --- a/ext/mysqli/mysqli_fe.h +++ b/ext/mysqli/mysqli_fe.h @@ -60,6 +60,7 @@ PHP_FUNCTION(mysqli_get_charset); PHP_FUNCTION(mysqli_get_client_info); PHP_FUNCTION(mysqli_get_client_version); PHP_FUNCTION(mysqli_get_host_info); +PHP_FUNCTION(mysqli_get_links_stats); PHP_FUNCTION(mysqli_get_proto_info); PHP_FUNCTION(mysqli_get_server_info); PHP_FUNCTION(mysqli_get_server_version); diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index db0352baeb..312f2806ce 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -1207,6 +1207,23 @@ PHP_FUNCTION(mysqli_release_savepoint) /* }}} */ +/* {{{ proto bool mysqli_get_links_stats() + Returns information about open and cached links */ +PHP_FUNCTION(mysqli_get_links_stats) +{ + if (ZEND_NUM_ARGS()) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "no parameters expected"); + return; + } + array_init(return_value); + add_assoc_long_ex(return_value, "total", sizeof("total"), MyG(num_links)); + add_assoc_long_ex(return_value, "active_plinks", sizeof("active_plinks"), MyG(num_active_persistent)); + add_assoc_long_ex(return_value, "cached_plinks", sizeof("cached_plinks"), MyG(num_inactive_persistent)); +} +/* }}} */ + + + /* * Local variables: * tab-width: 4 diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index e7c02f9c9b..cc0c8fe63f 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -334,6 +334,7 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli) HashTable *report_ht; unsigned long multi_query; unsigned long embedded; + zend_bool rollback_on_cached_plink; ZEND_END_MODULE_GLOBALS(mysqli) diff --git a/ext/mysqli/tests/mysqli_pconn_max_links.phpt b/ext/mysqli/tests/mysqli_pconn_max_links.phpt index e87ef00b21..99e51e7c5e 100644 --- a/ext/mysqli/tests/mysqli_pconn_max_links.phpt +++ b/ext/mysqli/tests/mysqli_pconn_max_links.phpt @@ -42,6 +42,7 @@ Persistent connections and mysqli.max_links --INI-- mysqli.allow_persistent=1 mysqli.max_persistent=2 +mysqli.rollback_on_cached_plink=1 --FILE-- <?php require_once("connect.inc"); @@ -58,10 +59,18 @@ mysqli.max_persistent=2 mysqli_errno($plink), mysqli_error($plink)); } + var_dump(mysqli_get_links_stats(1)); + + echo "Before pconnect:"; + var_dump(mysqli_get_links_stats()); + if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket)) printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); + echo "After pconnect:"; + var_dump(mysqli_get_links_stats()); + ob_start(); phpinfo(); $phpinfo = strip_tags(ob_get_contents()); @@ -110,11 +119,17 @@ mysqli.max_persistent=2 if (isset($running_threads[$pthread_id])) printf("[009] Persistent connection has not been killed\n"); + echo "Before second pconnect:"; + var_dump(mysqli_get_links_stats()); + // this fails and we have 0 (<= $num_plinks) connections if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket)) printf("[010] Can connect using the old password, [%d] %s\n", mysqli_connect_errno($link), mysqli_connect_error($link)); + echo "After second pconnect:"; + var_dump(mysqli_get_links_stats()); + ob_start(); phpinfo(); $phpinfo = strip_tags(ob_get_contents()); @@ -123,7 +138,13 @@ mysqli.max_persistent=2 if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches)) printf("[010] Cannot get # of active persistent links from phpinfo()\n"); + var_dump(mysqli_get_links_stats()); + $num_plinks_kill = $matches[1]; + $sstats = mysqli_get_links_stats(); + if ($sstats['active_plinks'] != $num_plinks_kill) { + printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill); + } if ($num_plinks_kill > $num_plinks) printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill); @@ -141,9 +162,11 @@ mysqli.max_persistent=2 mysqli_free_result($res); var_dump($row); - if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) + if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) { printf("[015] Can open more persistent connections than allowed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); + var_dump(mysqli_get_links_stats()); + } ob_start(); phpinfo(); @@ -179,18 +202,71 @@ mysqli_query($link, 'DROP USER pcontest'); mysqli_close($link); ?> --EXPECTF-- -array(2) { - [%u|b%"id"]=> - %unicode|string%(1) "1" - [%u|b%"label"]=> - %unicode|string%(1) "a" +Warning: mysqli_get_links_stats(): no parameters expected in %s on line %d +NULL +Before pconnect:array(3) { + ["total"]=> + int(1) + ["active_plinks"]=> + int(0) + ["cached_plinks"]=> + int(0) +} +After pconnect:array(3) { + ["total"]=> + int(2) + ["active_plinks"]=> + int(1) + ["cached_plinks"]=> + int(0) } array(2) { - [%u|b%"id"]=> - %unicode|string%(1) "1" - [%u|b%"label"]=> - %unicode|string%(1) "a" + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" +} +Before second pconnect:array(3) { + ["total"]=> + int(2) + ["active_plinks"]=> + int(1) + ["cached_plinks"]=> + int(0) } -Warning: %s: Too many open persistent links (%d) in %s on line %d +Warning: main(): MySQL server has gone away in %s on line %d + +Warning: main(): Error reading result set's header in %s line %d +After second pconnect:array(3) { + ["total"]=> + int(1) + ["active_plinks"]=> + int(0) + ["cached_plinks"]=> + int(0) +} +array(3) { + ["total"]=> + int(1) + ["active_plinks"]=> + int(0) + ["cached_plinks"]=> + int(0) +} +array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" +} +[015] Can open more persistent connections than allowed, [0] +array(3) { + ["total"]=> + int(3) + ["active_plinks"]=> + int(2) + ["cached_plinks"]=> + int(0) +} done!
\ No newline at end of file diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index b38dd6d206..d57b3eafde 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -27,7 +27,9 @@ #endif #include "php.h" +#include "php_ini.h" #include "php_openssl.h" +#include "php_openssl_structs.h" /* PHP Includes */ #include "ext/standard/file.h" @@ -1071,6 +1073,13 @@ static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo) { /* { } /* }}} */ +/* {{{ INI Settings */ +PHP_INI_BEGIN() + PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_ALL, NULL) + PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_ALL, NULL) +PHP_INI_END() +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(openssl) @@ -1203,7 +1212,9 @@ PHP_MINIT_FUNCTION(openssl) php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC); php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper TSRMLS_CC); - + + REGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ @@ -1217,6 +1228,7 @@ PHP_MINFO_FUNCTION(openssl) php_info_print_table_row(2, "OpenSSL Library Version", SSLeay_version(SSLEAY_VERSION)); php_info_print_table_row(2, "OpenSSL Header Version", OPENSSL_VERSION_TEXT); php_info_print_table_end(); + DISPLAY_INI_ENTRIES(); } /* }}} */ @@ -1243,6 +1255,8 @@ PHP_MSHUTDOWN_FUNCTION(openssl) /* reinstate the default tcp handler */ php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC); + UNREGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ @@ -5063,9 +5077,13 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre zval **val = NULL; char *cnmatch = NULL; int err; + php_openssl_netstream_data_t *sslsock; + + sslsock = (php_openssl_netstream_data_t*)stream->abstract; - /* verification is turned off */ - if (!(GET_VER_OPT("verify_peer") && zval_is_true(*val))) { + if (!(GET_VER_OPT("verify_peer") || sslsock->is_client) + || (GET_VER_OPT("verify_peer") && !zval_is_true(*val)) + ) { return SUCCESS; } @@ -5105,6 +5123,11 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre GET_VER_OPT_STRING("CN_match", cnmatch); + /* If no CN_match was specified assign the autodetected name when connecting as a client */ + if (cnmatch == NULL && sslsock->is_client) { + cnmatch = sslsock->url_name; + } + if (cnmatch) { if (matches_san_list(peer, cnmatch TSRMLS_CC)) { return SUCCESS; @@ -5150,7 +5173,9 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ ERR_clear_error(); /* look at context options in the stream and set appropriate verification flags */ - if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) { + if (GET_VER_OPT("verify_peer") && !zval_is_true(*val)) { + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); + } else { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); @@ -5159,19 +5184,35 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ GET_VER_OPT_STRING("cafile", cafile); GET_VER_OPT_STRING("capath", capath); + if (!cafile) { + zend_bool exists = 1; + cafile = zend_ini_string_ex("openssl.cafile", sizeof("openssl.cafile"), 0, &exists); + } + + if (!capath) { + zend_bool exists = 1; + capath = zend_ini_string_ex("openssl.capath", sizeof("openssl.capath"), 0, &exists); + } + if (cafile || capath) { if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath); return NULL; } + } else { + php_openssl_netstream_data_t *sslsock; + sslsock = (php_openssl_netstream_data_t*)stream->abstract; + if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to set default verify locations and no CA settings specified"); + return NULL; + } } if (GET_VER_OPT("verify_depth")) { convert_to_long_ex(val); SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); } - } else { - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } /* callback for the passphrase (for localcert) */ @@ -5237,6 +5278,7 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ } } } + if (ok) { SSL *ssl = SSL_new(ctx); diff --git a/ext/openssl/php_openssl_structs.h b/ext/openssl/php_openssl_structs.h new file mode 100644 index 0000000000..13f8f320f8 --- /dev/null +++ b/ext/openssl/php_openssl_structs.h @@ -0,0 +1,42 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Wez Furlong <wez@thebrainroom.com> | + | Daniel Lowrey <rdlowrey@gmail.com> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "php_network.h" +#include <openssl/ssl.h> + +/* This implementation is very closely tied to the that of the native + * sockets implemented in the core. + * Don't try this technique in other extensions! + * */ + +typedef struct _php_openssl_netstream_data_t { + php_netstream_data_t s; + SSL *ssl_handle; + SSL_CTX *ctx; + struct timeval connect_timeout; + int enable_on_connect; + int is_client; + int ssl_active; + php_stream_xport_crypt_method_t method; + char *url_name; + unsigned state_set:1; + unsigned _spare:31; +} php_openssl_netstream_data_t; diff --git a/ext/openssl/tests/bug46127.phpt b/ext/openssl/tests/bug46127.phpt index a3bfd3a012..1de4eacd01 100644 --- a/ext/openssl/tests/bug46127.phpt +++ b/ext/openssl/tests/bug46127.phpt @@ -45,7 +45,10 @@ if ($pid == 0) { // child // client or failed sleep(1); -$sock = fsockopen('ssl://127.0.0.1', $port, $errno, $errstr); +$ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false +]]); +$sock = stream_socket_client("ssl://127.0.0.1:{$port}", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $ctx); if (!$sock) exit; echo fgets($sock); diff --git a/ext/openssl/tests/bug48182.phpt b/ext/openssl/tests/bug48182.phpt index 146c4c9226..b78ce57074 100644 --- a/ext/openssl/tests/bug48182.phpt +++ b/ext/openssl/tests/bug48182.phpt @@ -13,8 +13,7 @@ function ssl_server($port) { $host = 'ssl://127.0.0.1'.':'.$port; $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; $data = "Sending bug48182\n"; - - $pem = dirname(__FILE__) . '/bug46127.pem'; + $pem = dirname(__FILE__) . '/bug54992.pem'; $ssl_params = array( 'verify_peer' => false, 'allow_self_signed' => true, 'local_cert' => $pem); $ssl = array('ssl' => $ssl_params); @@ -47,8 +46,11 @@ function ssl_async_client($port) { $host = 'ssl://127.0.0.1'.':'.$port; $flags = STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT; $data = "Sending data over to SSL server in async mode with contents like Hello World\n"; - - $socket = stream_socket_client($host, $errno, $errstr, 10, $flags); + $context = stream_context_create(array('ssl' => array( + 'cafile' => dirname(__FILE__) . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local' + ))); + $socket = stream_socket_client($host, $errno, $errstr, 10, $flags, $context); stream_set_blocking($socket, 0); while ($socket && $data) { diff --git a/ext/openssl/tests/openssl_peer_fingerprint.phpt b/ext/openssl/tests/openssl_peer_fingerprint.phpt index 2960dffae5..2e4c192c03 100644 --- a/ext/openssl/tests/openssl_peer_fingerprint.phpt +++ b/ext/openssl/tests/openssl_peer_fingerprint.phpt @@ -24,6 +24,7 @@ if ($pid == -1) { 'verify_peer' => true, 'cafile' => __DIR__ . '/bug54992-ca.pem', 'capture_peer_cert' => true, + 'CN_match' => 'bug54992.local', 'peer_fingerprint' => '81cafc260aa8d82956ebc6212a362ece', ) ) @@ -38,6 +39,7 @@ if ($pid == -1) { 'verify_peer' => true, 'cafile' => __DIR__ . '/bug54992-ca.pem', 'capture_peer_cert' => true, + 'CN_match' => 'bug54992.local', 'peer_fingerprint' => array( 'sha256' => '78ea579f2c3b439359dec5dac9d445108772927427c4780037e87df3799a0aa0', ), @@ -59,4 +61,4 @@ Warning: stream_socket_client(): Failed to enable crypto in %s on line %d Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 (Unknown error) in %s on line %d bool(false) -resource(9) of type (stream) +resource(%d) of type (stream) diff --git a/ext/openssl/tests/peer_verification.phpt b/ext/openssl/tests/peer_verification.phpt new file mode 100644 index 0000000000..7c3347fd65 --- /dev/null +++ b/ext/openssl/tests/peer_verification.phpt @@ -0,0 +1,56 @@ +--TEST-- +Peer verification enabled for client streams +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; +$ctx = stream_context_create(['ssl' => [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true +]]); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + // Expected to fail -- no CA File present + var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT)); + + // Expected to fail -- no CA File present + $ctx = stream_context_create(['ssl' => ['verify_peer' => true]]); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // Should succeed with peer verification disabled in context + $ctx = stream_context_create(['ssl' => ['verify_peer' => false]]); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // Should succeed with CA file specified in context + $ctx = stream_context_create(['ssl' => [ + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', + ]]); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // Should succeed with globally available CA file specified via php.ini + $cafile = __DIR__ . '/bug54992-ca.pem'; + ini_set('openssl.cafile', $cafile); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 3); + @stream_socket_accept($server, 3); + @stream_socket_accept($server, 3); + @stream_socket_accept($server, 3); + @stream_socket_accept($server, 3); +} +--EXPECTF-- +bool(false) +bool(false) +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) diff --git a/ext/openssl/tests/sni_001.phpt b/ext/openssl/tests/sni_001.phpt index 3d7798cf85..2f76a9f918 100644 --- a/ext/openssl/tests/sni_001.phpt +++ b/ext/openssl/tests/sni_001.phpt @@ -24,6 +24,7 @@ function context() { return stream_context_create(array( 'ssl' => array( 'capture_peer_cert' => true, + 'verify_peer' => false ), )); } diff --git a/ext/openssl/tests/streams_crypto_method.phpt b/ext/openssl/tests/streams_crypto_method.phpt index 97a6e9ee8b..981f56b399 100644 --- a/ext/openssl/tests/streams_crypto_method.phpt +++ b/ext/openssl/tests/streams_crypto_method.phpt @@ -10,6 +10,7 @@ if (!extension_loaded('pcntl')) die('skip, pcntl required'); function client($port, $method) { $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'crypto_method', $method); + stream_context_set_option($ctx, 'ssl', 'verify_peer', false); $fp = @fopen('https://127.0.0.1:' . $port . '/', 'r', false, $ctx); if ($fp) { diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 244f04def9..61ba0271cb 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -23,8 +23,8 @@ #include "ext/standard/url.h" #include "streams/php_streams_int.h" #include "ext/standard/php_smart_str.h" -#include "php_network.h" #include "php_openssl.h" +#include "php_openssl_structs.h" #include <openssl/ssl.h> #include <openssl/x509.h> #include <openssl/err.h> @@ -41,25 +41,6 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC); int php_openssl_get_x509_list_id(void); -/* This implementation is very closely tied to the that of the native - * sockets implemented in the core. - * Don't try this technique in other extensions! - * */ - -typedef struct _php_openssl_netstream_data_t { - php_netstream_data_t s; - SSL *ssl_handle; - SSL_CTX *ctx; - struct timeval connect_timeout; - int enable_on_connect; - int is_client; - int ssl_active; - php_stream_xport_crypt_method_t method; - char *sni; - unsigned state_set:1; - unsigned _spare:31; -} php_openssl_netstream_data_t; - php_stream_ops php_openssl_socket_ops; /* it doesn't matter that we do some hash traversal here, since it is done only @@ -285,11 +266,12 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_ } } - if (sslsock->sni) { - pefree(sslsock->sni, php_stream_is_persistent(stream)); + if (sslsock->url_name) { + pefree(sslsock->url_name, php_stream_is_persistent(stream)); } + pefree(sslsock, php_stream_is_persistent(stream)); - + return 0; } @@ -467,12 +449,25 @@ static inline int php_openssl_setup_crypto(php_stream *stream, return 0; } +static void enable_server_name_indication(php_stream_context *ctx, php_openssl_netstream_data_t *sslsock) +{ + zval **val = NULL; + + if (php_stream_context_get_option(ctx, "ssl", "SNI_server_name", &val) == SUCCESS) { + convert_to_string_ex(val); + SSL_set_tlsext_host_name(sslsock->ssl_handle, &val); + } else if (sslsock->url_name) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + } +} + static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_netstream_data_t *sslsock, php_stream_xport_crypto_param *cparam TSRMLS_DC) { int n, retry = 1; + zval **val = NULL; if (cparam->inputs.activate && !sslsock->ssl_active) { struct timeval start_time, @@ -481,9 +476,14 @@ static inline int php_openssl_enable_crypto(php_stream *stream, has_timeout = 0; #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) - if (sslsock->is_client && sslsock->sni) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->sni); + + if (sslsock->is_client + && (php_stream_context_get_option(stream->context, "ssl", "SNI_enabled", &val) == FAILURE + || zend_is_true(*val TSRMLS_CC)) + ) { + enable_server_name_indication(stream->context, sslsock); } + #endif if (!sslsock->state_set) { @@ -920,7 +920,7 @@ static int get_crypto_method(php_stream_context *ctx) { return STREAM_CRYPTO_METHOD_SSLv23_CLIENT; } -static char * get_sni(php_stream_context *ctx, const char *resourcename, size_t resourcenamelen, int is_persistent TSRMLS_DC) { +static char * get_url_name(const char *resourcename, size_t resourcenamelen, int is_persistent TSRMLS_DC) { php_url *url; if (ctx) { @@ -946,7 +946,7 @@ static char * get_sni(php_stream_context *ctx, const char *resourcename, size_t if (url->host) { const char * host = url->host; - char * sni = NULL; + char * url_name = NULL; size_t len = strlen(host); /* skip trailing dots */ @@ -955,11 +955,11 @@ static char * get_sni(php_stream_context *ctx, const char *resourcename, size_t } if (len) { - sni = pestrndup(host, len, is_persistent); + url_name = pestrndup(host, len, is_persistent); } php_url_free(url); - return sni; + return url_name; } php_url_free(url); @@ -1001,8 +1001,6 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, return NULL; } - sslsock->sni = get_sni(context, resourcename, resourcenamelen, !!persistent_id TSRMLS_CC); - if (strncmp(proto, "ssl", protolen) == 0) { sslsock->enable_on_connect = 1; @@ -1042,7 +1040,9 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, return NULL; #endif } - + + sslsock->url_name = get_url_name(resourcename, resourcenamelen, !!persistent_id TSRMLS_CC); + return stream; } diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h index 1cb5c0467a..955d85b4ef 100644 --- a/ext/zip/lib/zipconf.h +++ b/ext/zip/lib/zipconf.h @@ -7,7 +7,7 @@ This file was generated automatically by CMake
based on ../cmake-zipconf.h.in.
*/
-#define LIBZIP_VERSION "0.11.1"
+#define LIBZIP_VERSION "0.11.2"
/* #undef HAVE_INTTYPES_H_LIBZIP */
#if defined(_WIN32)
diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 591b907aa8..ffe4530415 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -38,7 +38,7 @@ extern zend_module_entry zip_module_entry; #define ZIP_OVERWRITE ZIP_TRUNCATE #endif -#define PHP_ZIP_VERSION "1.12.4-dev" +#define PHP_ZIP_VERSION "1.12.4" #if ((PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION >= 6) # define PHP_ZIP_USE_OO 1 diff --git a/main/php_ini.c b/main/php_ini.c index 3bcb249f84..f7f4686e84 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -630,63 +630,81 @@ int php_init_config(TSRMLS_D) zend_llist scanned_ini_list; zend_llist_element *element; int l, total_l = 0; + char *bufpath, *debpath, *endpath; + int lenpath; - if ((ndir = php_scandir(php_ini_scanned_path, &namelist, 0, php_alphasort)) > 0) { - zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); - memset(&fh2, 0, sizeof(fh2)); + zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); + memset(&fh2, 0, sizeof(fh2)); - for (i = 0; i < ndir; i++) { + bufpath = estrdup(php_ini_scanned_path); + for (debpath = bufpath ; debpath ; debpath=endpath) { + endpath = strchr(debpath, DEFAULT_DIR_SEPARATOR); + if (endpath) { + *(endpath++) = 0; + } + if (!debpath[0]) { + /* empty string means default builtin value + to allow "/foo/phd.d:" or ":/foo/php.d" */ + debpath = PHP_CONFIG_FILE_SCAN_DIR; + } + lenpath = strlen(debpath); - /* check for any file with .ini extension */ - if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) { - free(namelist[i]); - continue; - } - /* Reset active ini section */ - RESET_ACTIVE_INI_HASH(); + if (lenpath > 0 && (ndir = php_scandir(debpath, &namelist, 0, php_alphasort)) > 0) { - if (IS_SLASH(php_ini_scanned_path[php_ini_scanned_path_len - 1])) { - snprintf(ini_file, MAXPATHLEN, "%s%s", php_ini_scanned_path, namelist[i]->d_name); - } else { - snprintf(ini_file, MAXPATHLEN, "%s%c%s", php_ini_scanned_path, DEFAULT_SLASH, namelist[i]->d_name); - } - if (VCWD_STAT(ini_file, &sb) == 0) { - if (S_ISREG(sb.st_mode)) { - if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) { - fh2.filename = ini_file; - fh2.type = ZEND_HANDLE_FP; - - if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) { - /* Here, add it to the list of ini files read */ - l = strlen(ini_file); - total_l += l + 2; - p = estrndup(ini_file, l); - zend_llist_add_element(&scanned_ini_list, &p); + for (i = 0; i < ndir; i++) { + + /* check for any file with .ini extension */ + if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) { + free(namelist[i]); + continue; + } + /* Reset active ini section */ + RESET_ACTIVE_INI_HASH(); + + if (IS_SLASH(debpath[lenpath - 1])) { + snprintf(ini_file, MAXPATHLEN, "%s%s", debpath, namelist[i]->d_name); + } else { + snprintf(ini_file, MAXPATHLEN, "%s%c%s", debpath, DEFAULT_SLASH, namelist[i]->d_name); + } + if (VCWD_STAT(ini_file, &sb) == 0) { + if (S_ISREG(sb.st_mode)) { + if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) { + fh2.filename = ini_file; + fh2.type = ZEND_HANDLE_FP; + + if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) { + /* Here, add it to the list of ini files read */ + l = strlen(ini_file); + total_l += l + 2; + p = estrndup(ini_file, l); + zend_llist_add_element(&scanned_ini_list, &p); + } } } } + free(namelist[i]); } - free(namelist[i]); + free(namelist); } - free(namelist); + } + efree(bufpath); - if (total_l) { - int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; - php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); - if (!php_ini_scanned_files_len) { - *php_ini_scanned_files = '\0'; - } - total_l += php_ini_scanned_files_len; - for (element = scanned_ini_list.head; element; element = element->next) { - if (php_ini_scanned_files_len) { - strlcat(php_ini_scanned_files, ",\n", total_l); - } - strlcat(php_ini_scanned_files, *(char **)element->data, total_l); - strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l); + if (total_l) { + int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; + php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); + if (!php_ini_scanned_files_len) { + *php_ini_scanned_files = '\0'; + } + total_l += php_ini_scanned_files_len; + for (element = scanned_ini_list.head; element; element = element->next) { + if (php_ini_scanned_files_len) { + strlcat(php_ini_scanned_files, ",\n", total_l); } + strlcat(php_ini_scanned_files, *(char **)element->data, total_l); + strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l); } - zend_llist_destroy(&scanned_ini_list); } + zend_llist_destroy(&scanned_ini_list); } else { /* Make sure an empty php_ini_scanned_path ends up as NULL */ php_ini_scanned_path = NULL; |