diff options
author | CoprDistGit <infra@openeuler.org> | 2023-08-18 15:45:34 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2023-08-18 15:45:34 +0000 |
commit | 2a41bfb434bb828912ded819564e2b504fca1ebc (patch) | |
tree | b78c5687e2fa6533914f82f7e77b1d170455e3fb | |
parent | 0fd92ab5ed82aa6d567e6ebcc700d9ab1cd37357 (diff) |
automatic import of php
41 files changed, 9151 insertions, 0 deletions
@@ -0,0 +1 @@ +/php-7.4.33.tar.xz diff --git a/10-opcache.ini b/10-opcache.ini new file mode 100644 index 0000000..8c5db66 --- /dev/null +++ b/10-opcache.ini @@ -0,0 +1,148 @@ +; Enable Zend OPcache extension module +zend_extension=opcache + +; Determines if Zend OPCache is enabled +opcache.enable=1 + +; Determines if Zend OPCache is enabled for the CLI version of PHP +opcache.enable_cli=1 + +; The OPcache shared memory storage size. +;opcache.memory_consumption=128 + +; The amount of memory for interned strings in Mbytes. +;opcache.interned_strings_buffer=8 + +; The maximum number of keys (scripts) in the OPcache hash table. +; Only numbers between 200 and 1000000 are allowed. +;opcache.max_accelerated_files=10000 + +; The maximum percentage of "wasted" memory until a restart is scheduled. +;opcache.max_wasted_percentage=5 + +; When this directive is enabled, the OPcache appends the current working +; directory to the script key, thus eliminating possible collisions between +; files with the same name (basename). Disabling the directive improves +; performance, but may break existing applications. +;opcache.use_cwd=1 + +; When disabled, you must reset the OPcache manually or restart the +; webserver for changes to the filesystem to take effect. +;opcache.validate_timestamps=1 + +; How often (in seconds) to check file timestamps for changes to the shared +; memory storage allocation. ("1" means validate once per second, but only +; once per request. "0" means always validate) +;opcache.revalidate_freq=2 + +; Enables or disables file search in include_path optimization +;opcache.revalidate_path=0 + +; If disabled, all PHPDoc comments are dropped from the code to reduce the +; size of the optimized code. +;opcache.save_comments=1 + +; Allow file existence override (file_exists, etc.) performance feature. +;opcache.enable_file_override=0 + +; A bitmask, where each bit enables or disables the appropriate OPcache +; passes +;opcache.optimization_level=0x7FFFBFFF + +; This hack should only be enabled to work around "Cannot redeclare class" +; errors. +;opcache.dups_fix=0 + +; The location of the OPcache blacklist file (wildcards allowed). +; Each OPcache blacklist file is a text file that holds the names of files +; that should not be accelerated. +opcache.blacklist_filename=/etc/php.d/opcache*.blacklist + +; Allows exclusion of large files from being cached. By default all files +; are cached. +;opcache.max_file_size=0 + +; Check the cache checksum each N requests. +; The default value of "0" means that the checks are disabled. +;opcache.consistency_checks=0 + +; How long to wait (in seconds) for a scheduled restart to begin if the cache +; is not being accessed. +;opcache.force_restart_timeout=180 + +; OPcache error_log file name. Empty string assumes "stderr". +;opcache.error_log= + +; All OPcache errors go to the Web server log. +; By default, only fatal errors (level 0) or errors (level 1) are logged. +; You can also enable warnings (level 2), info messages (level 3) or +; debug messages (level 4). +;opcache.log_verbosity_level=1 + +; Preferred Shared Memory back-end. Leave empty and let the system decide. +;opcache.preferred_memory_model= + +; Protect the shared memory from unexpected writing during script execution. +; Useful for internal debugging only. +;opcache.protect_memory=0 + +; Allows calling OPcache API functions only from PHP scripts which path is +; started from specified string. The default "" means no restriction +;opcache.restrict_api= + +; Enables and sets the second level cache directory. +; It should improve performance when SHM memory is full, at server restart or +; SHM reset. The default "" disables file based caching. +; RPM note : file cache directory must be owned by process owner +; for mod_php, see /etc/httpd/conf.d/php.conf +; for php-fpm, see /etc/php-fpm.d/*conf +;opcache.file_cache= + +; Enables or disables opcode caching in shared memory. +;opcache.file_cache_only=0 + +; Enables or disables checksum validation when script loaded from file cache. +;opcache.file_cache_consistency_checks=1 + +; Implies opcache.file_cache_only=1 for a certain process that failed to +; reattach to the shared memory (for Windows only). Explicitly enabled file +; cache is required. +;opcache.file_cache_fallback=1 + +; Enables or disables copying of PHP code (text segment) into HUGE PAGES. +; This should improve performance, but requires appropriate OS configuration. +opcache.huge_code_pages=0 + +; Validate cached file permissions. +; Leads OPcache to check file readability on each access to cached file. +; This directive should be enabled in shared hosting environment, when few +; users (PHP-FPM pools) reuse the common OPcache shared memory. +;opcache.validate_permission=0 + +; Prevent name collisions in chroot'ed environment. +; This directive prevents file name collisions in different "chroot" +; environments. It should be enabled for sites that may serve requests in +; different "chroot" environments. +;opcache.validate_root=0 + +; If specified, it produces opcode dumps for debugging different stages of +; optimizations. +;opcache.opt_debug_level=0 + +; Specifies a PHP script that is going to be compiled and executed at server +; start-up. +; http://php.net/opcache.preload +;opcache.preload= + +; Preloading code as root is not allowed for security reasons. This directive +; facilitates to let the preloading to be run as another user. +; http://php.net/opcache.preload_user +;opcache.preload_user= + +; Prevents caching files that are less than this number of seconds old. It +; protects from caching of incompletely updated files. In case all file updates +; on your site are atomic, you may increase performance by setting it to "0". +;opcache.file_update_protection=2 + +; Absolute path used to store shared lockfiles (for *nix only). +;opcache.lockfile_path=/tmp diff --git a/20-ffi.ini b/20-ffi.ini new file mode 100644 index 0000000..0bce40d --- /dev/null +++ b/20-ffi.ini @@ -0,0 +1,13 @@ +; Enable ffi extension module +extension=ffi + +; FFI API restriction. Possibe values: +; "preload" - enabled in CLI scripts and preloaded files (default) +; "false" - always disabled +; "true" - always enabled +;ffi.enable=preload + +; List of headers files to preload, wildcard patterns allowed. +; /usr/share/php/preload used by for RPM packages +; /usr/local/share/php/preload may be used for local files +ffi.preload=/usr/share/php/preload/*.h:/usr/local/share/php/preload/*.h diff --git a/20-oci8.ini b/20-oci8.ini new file mode 100644 index 0000000..46e0668 --- /dev/null +++ b/20-oci8.ini @@ -0,0 +1,53 @@ +; Enable oci8 extension module +extension=oci8 + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off diff --git a/macros.php b/macros.php new file mode 100644 index 0000000..989e8b3 --- /dev/null +++ b/macros.php @@ -0,0 +1,26 @@ +# +# Interface versions exposed by PHP: +# +%php_core_api @PHP_APIVER@ +%php_zend_api @PHP_ZENDVER@ +%php_pdo_api @PHP_PDOVER@ +%php_version @PHP_VERSION@ + +%php_extdir %{_libdir}/php/modules +%php_ztsextdir %{_libdir}/php-zts/modules + +%php_inidir %{_sysconfdir}/php.d +%php_ztsinidir %{_sysconfdir}/php-zts.d + +%php_incldir %{_includedir}/php +%php_ztsincldir %{_includedir}/php-zts/php + +%__php %{_bindir}/php +%__ztsphp %{_bindir}/zts-php + +%__phpize %{_bindir}/phpize +%__ztsphpize %{_bindir}/zts-phpize + +%__phpconfig %{_bindir}/php-config +%__ztsphpconfig %{_bindir}/zts-php-config + diff --git a/nginx-fpm.conf b/nginx-fpm.conf new file mode 100644 index 0000000..5b5f9be --- /dev/null +++ b/nginx-fpm.conf @@ -0,0 +1,6 @@ +# PHP-FPM FastCGI server +# network or unix domain socket configuration + +upstream php-fpm { + server 127.0.0.1:9000; +} diff --git a/nginx-php.conf b/nginx-php.conf new file mode 100644 index 0000000..9b01536 --- /dev/null +++ b/nginx-php.conf @@ -0,0 +1,14 @@ +# pass the PHP scripts to FastCGI server +# +# See conf.d/php-fpm.conf for socket configuration +# +index index.php index.html index.htm; + +location ~ \.php$ { + try_files $uri =404; + fastcgi_intercept_errors on; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass php-fpm; +} diff --git a/opcache-default.blacklist b/opcache-default.blacklist new file mode 100644 index 0000000..0cc2e18 --- /dev/null +++ b/opcache-default.blacklist @@ -0,0 +1,11 @@ +; The blacklist file is a text file that holds the names of files +; that should not be accelerated. The file format is to add each filename +; to a new line. The filename may be a full path or just a file prefix +; (i.e., /var/www/x blacklists all the files and directories in /var/www +; that start with 'x'). Line starting with a ; are ignored (comments). +; Files are usually triggered by one of the following three reasons: +; 1) Directories that contain auto generated code, like Smarty or ZFW cache. +; 2) Code that does not work well when accelerated, due to some delayed +; compile time evaluation. +; 3) Code that triggers an OPcache bug. + diff --git a/php-7.0.10-datetests.patch b/php-7.0.10-datetests.patch new file mode 100644 index 0000000..fc42326 --- /dev/null +++ b/php-7.0.10-datetests.patch @@ -0,0 +1,97 @@ +--- a/ext/date/tests/bug66985.phpt 2014-10-30 07:32:03.297693403 +0100 ++++ b/ext/date/tests/bug66985.phpt 2014-10-30 07:32:45.138877977 +0100 +@@ -3,7 +3,7 @@ + --FILE-- + <?php + $zones = array( +- "CST6CDT", "Cuba", "Egypt", "Eire", "EST5EDT", "Factory", "GB-Eire", ++ "CST6CDT", "Cuba", "Egypt", "Eire", "EST5EDT", "GB-Eire", + "GMT0", "Greenwich", "Hongkong", "Iceland", "Iran", "Israel", "Jamaica", + "Japan", "Kwajalein", "Libya", "MST7MDT", "Navajo", "NZ-CHAT", "Poland", + "Portugal", "PST8PDT", "Singapore", "Turkey", "Universal", "W-SU", +@@ -45,11 +45,6 @@ + ) + DateTimeZone Object + ( +- [timezone_type] => 3 +- [timezone] => Factory +-) +-DateTimeZone Object +-( + [timezone_type] => 3 + [timezone] => GB-Eire + ) +diff -up ./ext/date/tests/strtotime3-64bit.phpt.datetests ./ext/date/tests/strtotime3-64bit.phpt +--- ./ext/date/tests/strtotime3-64bit.phpt.datetests 2016-07-21 02:23:03.000000000 +0200 ++++ ./ext/date/tests/strtotime3-64bit.phpt 2016-07-26 07:39:45.713272263 +0200 +@@ -44,7 +44,7 @@ foreach ($strs as $str) { + } + + ?> +---EXPECT-- ++--EXPECTF-- + bool(false) + bool(false) + string(31) "Thu, 15 Jun 2006 00:00:00 +0100" +@@ -53,7 +53,7 @@ bool(false) + string(31) "Fri, 16 Jun 2006 23:49:12 +0100" + bool(false) + string(31) "Fri, 16 Jun 2006 02:22:00 +0100" +-string(31) "Sun, 16 Jun 0222 02:22:00 -0036" ++string(31) "Sun, 16 Jun 0222 02:22:00 %s" + string(31) "Fri, 16 Jun 2006 02:22:33 +0100" + bool(false) + string(31) "Tue, 02 Mar 2004 00:00:00 +0000" +diff -up ./ext/date/tests/bug33414-2.phpt.old ./ext/date/tests/bug33414-2.phpt +--- ./ext/date/tests/bug33414-2.phpt.old 2017-04-25 15:47:21.675700587 +0200 ++++ ./ext/date/tests/bug33414-2.phpt 2017-04-25 15:57:14.034681111 +0200 +@@ -74,10 +74,10 @@ $strtotime_tstamp = strtotime("next Frid + print "result=".date("l Y-m-d H:i:s T I", $strtotime_tstamp)."\n"; + print "wanted=Friday 00:00:00\n\n"; + ?> +---EXPECT-- ++--EXPECTF-- + TZ=Pacific/Rarotonga - wrong day. +-tStamp=Thursday 1970-01-01 17:17:17 -1030 0 +-result=Tuesday 1970-01-06 00:00:00 -1030 0 ++tStamp=Thursday 1970-01-01 17:17:17 %s ++result=Tuesday 1970-01-06 00:00:00 %s + wanted=Tuesday 00:00:00 + + TZ=Atlantic/South_Georgia - wrong day. +@@ -91,13 +91,13 @@ result=Monday 2005-04-04 00:00:00 EDT 1 + wanted=Monday 00:00:00 + + TZ=Pacific/Enderbury - wrong day, off by 2 days. +-tStamp=Thursday 1970-01-01 17:17:17 -12 0 +-result=Monday 1970-01-05 00:00:00 -12 0 ++tStamp=Thursday 1970-01-01 17:17:17 %s ++result=Monday 1970-01-05 00:00:00 %s + wanted=Monday 00:00:00 + + TZ=Pacific/Kiritimati - wrong day, off by 2 days. +-tStamp=Thursday 1970-01-01 17:17:17 -1040 0 +-result=Monday 1970-01-05 00:00:00 -1040 0 ++tStamp=Thursday 1970-01-01 17:17:17 %s ++result=Monday 1970-01-05 00:00:00 %s + wanted=Monday 00:00:00 + + TZ=America/Managua - wrong day. +@@ -106,13 +106,13 @@ result=Tuesday 2005-04-12 00:00:00 CDT 1 + wanted=Tuesday 00:00:00 + + TZ=Pacific/Pitcairn - wrong day. +-tStamp=Thursday 1970-01-01 17:17:17 -0830 0 +-result=Wednesday 1970-01-07 00:00:00 -0830 0 ++tStamp=Thursday 1970-01-01 17:17:17 %s ++result=Wednesday 1970-01-07 00:00:00 %s + wanted=Wednesday 00:00:00 + + TZ=Pacific/Fakaofo - wrong day. +-tStamp=Thursday 1970-01-01 17:17:17 -11 0 +-result=Saturday 1970-01-03 00:00:00 -11 0 ++tStamp=Thursday 1970-01-01 17:17:17 %s ++result=Saturday 1970-01-03 00:00:00 %s + wanted=Saturday 00:00:00 + + TZ=Pacific/Johnston - wrong day. diff --git a/php-7.0.7-curl.patch b/php-7.0.7-curl.patch new file mode 100644 index 0000000..218db98 --- /dev/null +++ b/php-7.0.7-curl.patch @@ -0,0 +1,15 @@ +diff -up php-7.0.7RC1/ext/curl/interface.c.curltls php-7.0.7RC1/ext/curl/interface.c +--- php-7.0.7RC1/ext/curl/interface.c.curltls 2016-05-10 17:28:33.000000000 +0200 ++++ php-7.0.7RC1/ext/curl/interface.c 2016-05-12 07:43:00.900419946 +0200 +@@ -1257,7 +1257,11 @@ PHP_MINIT_FUNCTION(curl) + + #if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */ + REGISTER_CURL_CONSTANT(CURLOPT_LOGIN_OPTIONS); ++#endif + ++#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 (in upstream curl 7.34) ++ backported in RHEL-7 curl-7.29.0-16.el7 rhbz#1012136 ++ backported in RHEL-6 curl-7.19.7-43.el6 rhbz#1036789 */ + REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_0); + REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_1); + REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_2); diff --git a/php-7.2.0-includedir.patch b/php-7.2.0-includedir.patch new file mode 100644 index 0000000..6d9a871 --- /dev/null +++ b/php-7.2.0-includedir.patch @@ -0,0 +1,11 @@ +--- php-7.2.0/configure.ac.includedir ++++ php-7.2.0/configure.ac +@@ -1230,7 +1230,7 @@ + EXPANDED_DATADIR=$datadir + EXPANDED_PHP_CONFIG_FILE_PATH=`eval echo "$PHP_CONFIG_FILE_PATH"` + EXPANDED_PHP_CONFIG_FILE_SCAN_DIR=`eval echo "$PHP_CONFIG_FILE_SCAN_DIR"` +-INCLUDE_PATH=.:$EXPANDED_PEAR_INSTALLDIR ++INCLUDE_PATH=.:$EXPANDED_PEAR_INSTALLDIR:${EXPANDED_DATADIR}/php + + exec_prefix=$old_exec_prefix + libdir=$old_libdir diff --git a/php-7.2.0-libdb.patch b/php-7.2.0-libdb.patch new file mode 100644 index 0000000..ca36d1a --- /dev/null +++ b/php-7.2.0-libdb.patch @@ -0,0 +1,92 @@ +diff -up php-7.2.0alpha0/ext/dba/config.m4.libdb php-7.2.0alpha0/ext/dba/config.m4 +--- php-7.2.0alpha0/ext/dba/config.m4.libdb 2017-05-29 08:56:06.000000000 +0200 ++++ php-7.2.0alpha0/ext/dba/config.m4 2017-05-29 09:13:52.014823282 +0200 +@@ -346,61 +346,13 @@ if test "$PHP_DB4" != "no"; then + dbdp4="/usr/local/BerkeleyDB.4." + dbdp5="/usr/local/BerkeleyDB.5." + for i in $PHP_DB4 ${dbdp5}1 ${dbdp5}0 ${dbdp4}8 ${dbdp4}7 ${dbdp4}6 ${dbdp4}5 ${dbdp4}4 ${dbdp4}3 ${dbdp4}2 ${dbdp4}1 ${dbdp}0 /usr/local /usr; do +- if test -f "$i/db5/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/db5/db.h +- break +- elif test -f "$i/db4/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/db4/db.h +- break +- elif test -f "$i/include/db5.3/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db5.3/db.h +- break +- elif test -f "$i/include/db5.1/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db5.1/db.h +- break +- elif test -f "$i/include/db5.0/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db5.0/db.h +- break +- elif test -f "$i/include/db4.8/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4.8/db.h +- break +- elif test -f "$i/include/db4.7/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4.7/db.h +- break +- elif test -f "$i/include/db4.6/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4.6/db.h +- break +- elif test -f "$i/include/db4.5/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4.5/db.h +- break +- elif test -f "$i/include/db4/db.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4/db.h +- break +- elif test -f "$i/include/db/db4.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db/db4.h +- break +- elif test -f "$i/include/db4.h"; then +- THIS_PREFIX=$i +- THIS_INCLUDE=$i/include/db4.h +- break +- elif test -f "$i/include/db.h"; then ++ if test -f "$i/include/db.h"; then + THIS_PREFIX=$i + THIS_INCLUDE=$i/include/db.h + break + fi + done +- PHP_DBA_DB_CHECK(4, db-5.3 db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) ++ PHP_DBA_DB_CHECK(4, db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) + fi + PHP_DBA_STD_RESULT(db4,Berkeley DB4) + +diff -up php-7.2.0alpha0/ext/dba/dba.c.libdb php-7.2.0alpha0/ext/dba/dba.c +--- php-7.2.0alpha0/ext/dba/dba.c.libdb 2017-05-29 09:16:15.736628202 +0200 ++++ php-7.2.0alpha0/ext/dba/dba.c 2017-05-29 09:16:20.494654746 +0200 +@@ -53,6 +53,10 @@ + #include "php_tcadb.h" + #include "php_lmdb.h" + ++#ifdef DB4_INCLUDE_FILE ++#include DB4_INCLUDE_FILE ++#endif ++ + /* {{{ arginfo */ + ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2) + ZEND_ARG_INFO(0, path) +@@ -558,6 +562,10 @@ PHP_MINFO_FUNCTION(dba) + + php_info_print_table_start(); + php_info_print_table_row(2, "DBA support", "enabled"); ++#ifdef DB_VERSION_STRING ++ php_info_print_table_row(2, "libdb header version", DB_VERSION_STRING); ++ php_info_print_table_row(2, "libdb library version", db_version(NULL, NULL, NULL)); ++#endif + if (handlers.s) { + smart_str_0(&handlers); + php_info_print_table_row(2, "Supported handlers", ZSTR_VAL(handlers.s)); diff --git a/php-7.2.0-oci8conf.patch b/php-7.2.0-oci8conf.patch new file mode 100644 index 0000000..0ad16a1 --- /dev/null +++ b/php-7.2.0-oci8conf.patch @@ -0,0 +1,35 @@ +diff -up ./ext/ldap/php_ldap.h.remi-oci8 ./ext/ldap/php_ldap.h +--- ./ext/ldap/php_ldap.h.remi-oci8 2017-06-20 15:45:35.000000000 +0200 ++++ ./ext/ldap/php_ldap.h 2017-06-20 16:55:01.640203868 +0200 +@@ -27,7 +27,7 @@ + #include <lber.h> + #endif + +-#include <ldap.h> ++#include "/usr/include/ldap.h" + + extern zend_module_entry ldap_module_entry; + #define ldap_module_ptr &ldap_module_entry +diff -up ./ext/oci8/config.m4.remi-oci8 ./ext/oci8/config.m4 +--- ./ext/oci8/config.m4.remi-oci8 2017-06-20 15:45:39.000000000 +0200 ++++ ./ext/oci8/config.m4 2017-06-20 16:55:01.640203868 +0200 +@@ -372,6 +372,7 @@ if test "$PHP_OCI8" != "no"; then + + dnl Header directory for Instant Client SDK RPM install + OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/lib/oracle/\(.*\)/client\('${PHP_OCI8_IC_LIBDIR_SUFFIX}'\)*/lib[/]*$!/usr/include/oracle/\1/client\2!'` ++ OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/\(lib64\|lib\)/oracle/\(.*\)/\(client64\|client\)/lib[/]*$!/usr/include/oracle/\2/\3!'` + + dnl Header directory for Instant Client SDK zip file install + OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include +diff -up ./ext/pdo_oci/config.m4.remi-oci8 ./ext/pdo_oci/config.m4 +--- ./ext/pdo_oci/config.m4.remi-oci8 2017-06-20 16:55:01.640203868 +0200 ++++ ./ext/pdo_oci/config.m4 2017-06-20 17:16:03.053538358 +0200 +@@ -93,7 +93,7 @@ if test "$PHP_PDO_OCI" != "no"; then + + AC_MSG_CHECKING([for oci.h]) + dnl Header directory for Instant Client SDK RPM install +- OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\2/\3!'` ++ OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/\(lib64\|lib\)/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\3/\4!'` + + dnl Header directory for manual installation + OCISDKMANINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib[/]*$!\1/include!'` diff --git a/php-7.3.3-systzdata-v19.patch b/php-7.3.3-systzdata-v19.patch new file mode 100644 index 0000000..9dde92f --- /dev/null +++ b/php-7.3.3-systzdata-v19.patch @@ -0,0 +1,715 @@ +# License: MIT +# http://opensource.org/licenses/MIT + +Add support for use of the system timezone database, rather +than embedding a copy. Discussed upstream but was not desired. + +History: +r20: fix possible buffer overflow +r19: retrieve tzdata version from /usr/share/zoneinfo/tzdata.zi +r18: adapt for autotool change in 7.3.3RC1 +r17: adapt for timelib 2018.01 (in 7.3.2RC1) +r16: adapt for timelib 2017.06 (in 7.2.3RC1) +r15: adapt for timelib 2017.05beta7 (in 7.2.0RC1) +r14: improve check for valid tz file +r13: adapt for upstream changes to use PHP allocator +r12: adapt for upstream changes for new zic +r11: use canonical names to avoid more case sensitivity issues + round lat/long from zone.tab towards zero per builtin db +r10: make timezone case insensitive +r9: fix another compile error without --with-system-tzdata configured (Michael Heimpold) +r8: fix compile error without --with-system-tzdata configured +r7: improve check for valid timezone id to exclude directories +r6: fix fd leak in r5, fix country code/BC flag use in + timezone_identifiers_list() using system db, + fix use of PECL timezonedb to override system db, +r5: reverts addition of "System/Localtime" fake tzname. + updated for 5.3.0, parses zone.tab to pick up mapping between + timezone name, country code and long/lat coords +r4: added "System/Localtime" tzname which uses /etc/localtime +r3: fix a crash if /usr/share/zoneinfo doesn't exist (Raphael Geissert) +r2: add filesystem trawl to set up name alias index +r1: initial revision + +diff --git a/ext/date/config0.m4 b/ext/date/config0.m4 +index 20e4164aaa..a61243646d 100644 +--- a/ext/date/config0.m4 ++++ b/ext/date/config0.m4 +@@ -4,6 +4,19 @@ AC_CHECK_HEADERS([io.h]) + dnl Check for strtoll, atoll + AC_CHECK_FUNCS(strtoll atoll) + ++PHP_ARG_WITH(system-tzdata, for use of system timezone data, ++[ --with-system-tzdata[=DIR] to specify use of system timezone data], ++no, no) ++ ++if test "$PHP_SYSTEM_TZDATA" != "no"; then ++ AC_DEFINE(HAVE_SYSTEM_TZDATA, 1, [Define if system timezone data is used]) ++ ++ if test "$PHP_SYSTEM_TZDATA" != "yes"; then ++ AC_DEFINE_UNQUOTED(HAVE_SYSTEM_TZDATA_PREFIX, "$PHP_SYSTEM_TZDATA", ++ [Define for location of system timezone data]) ++ fi ++fi ++ + PHP_DATE_CFLAGS="-I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DHAVE_TIMELIB_CONFIG_H=1" + timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c + lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c lib/parse_iso_intervals.c lib/interval.c" +diff --git a/ext/date/lib/parse_tz.c b/ext/date/lib/parse_tz.c +index 020da3135e..12e68ef043 100644 +--- a/ext/date/lib/parse_tz.c ++++ b/ext/date/lib/parse_tz.c +@@ -26,8 +26,21 @@ + #include "timelib.h" + #include "timelib_private.h" + ++#ifdef HAVE_SYSTEM_TZDATA ++#include <sys/mman.h> ++#include <sys/stat.h> ++#include <limits.h> ++#include <fcntl.h> ++#include <unistd.h> ++ ++#include "php_scandir.h" ++ ++#else + #define TIMELIB_SUPPORTS_V2DATA + #include "timezonedb.h" ++#endif ++ ++#include <ctype.h> + + #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)) + # if defined(__LITTLE_ENDIAN__) +@@ -88,6 +101,11 @@ static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz) + { + uint32_t version; + ++ if (memcmp(*tzf, "TZif", 4) == 0) { ++ *tzf += 20; ++ return 0; ++ } ++ + /* read ID */ + version = (*tzf)[3] - '0'; + *tzf += 4; +@@ -412,7 +430,467 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz) + } + } + +-static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb) ++#ifdef HAVE_SYSTEM_TZDATA ++ ++#ifdef HAVE_SYSTEM_TZDATA_PREFIX ++#define ZONEINFO_PREFIX HAVE_SYSTEM_TZDATA_PREFIX ++#else ++#define ZONEINFO_PREFIX "/usr/share/zoneinfo" ++#endif ++ ++/* System timezone database pointer. */ ++static const timelib_tzdb *timezonedb_system; ++ ++/* Hash table entry for the cache of the zone.tab mapping table. */ ++struct location_info { ++ char code[2]; ++ double latitude, longitude; ++ char name[64]; ++ char *comment; ++ struct location_info *next; ++}; ++ ++/* Cache of zone.tab. */ ++static struct location_info **system_location_table; ++ ++/* Size of the zone.tab hash table; a random-ish prime big enough to ++ * prevent too many collisions. */ ++#define LOCINFO_HASH_SIZE (1021) ++ ++/* Compute a case insensitive hash of str */ ++static uint32_t tz_hash(const char *str) ++{ ++ const unsigned char *p = (const unsigned char *)str; ++ uint32_t hash = 5381; ++ int c; ++ ++ while ((c = tolower(*p++)) != '\0') { ++ hash = (hash << 5) ^ hash ^ c; ++ } ++ ++ return hash % LOCINFO_HASH_SIZE; ++} ++ ++/* Parse an ISO-6709 date as used in zone.tab. Returns end of the ++ * parsed string on success, or NULL on parse error. On success, ++ * writes the parsed number to *result. */ ++static char *parse_iso6709(char *p, double *result) ++{ ++ double v, sign; ++ char *pend; ++ size_t len; ++ ++ if (*p == '+') ++ sign = 1.0; ++ else if (*p == '-') ++ sign = -1.0; ++ else ++ return NULL; ++ ++ p++; ++ for (pend = p; *pend >= '0' && *pend <= '9'; pend++) ++ ;; ++ ++ /* Annoying encoding used by zone.tab has no decimal point, so use ++ * the length to determine the format: ++ * ++ * 4 = DDMM ++ * 5 = DDDMM ++ * 6 = DDMMSS ++ * 7 = DDDMMSS ++ */ ++ len = pend - p; ++ if (len < 4 || len > 7) { ++ return NULL; ++ } ++ ++ /* p => [D]DD */ ++ v = (p[0] - '0') * 10.0 + (p[1] - '0'); ++ p += 2; ++ if (len == 5 || len == 7) ++ v = v * 10.0 + (*p++ - '0'); ++ /* p => MM[SS] */ ++ v += (10.0 * (p[0] - '0') ++ + p[1] - '0') / 60.0; ++ p += 2; ++ /* p => [SS] */ ++ if (len > 5) { ++ v += (10.0 * (p[0] - '0') ++ + p[1] - '0') / 3600.0; ++ p += 2; ++ } ++ ++ /* Round to five decimal place, not because it's a good idea, ++ * but, because the builtin data uses rounded data, so, match ++ * that. */ ++ *result = trunc(v * sign * 100000.0) / 100000.0; ++ ++ return p; ++} ++ ++/* This function parses the zone.tab file to build up the mapping of ++ * timezone to country code and geographic location, and returns a ++ * hash table. The hash table is indexed by the function: ++ * ++ * tz_hash(timezone-name) ++ */ ++static struct location_info **create_location_table(void) ++{ ++ struct location_info **li, *i; ++ char zone_tab[PATH_MAX]; ++ char line[512]; ++ FILE *fp; ++ ++ strncpy(zone_tab, ZONEINFO_PREFIX "/zone.tab", sizeof zone_tab); ++ ++ fp = fopen(zone_tab, "r"); ++ if (!fp) { ++ return NULL; ++ } ++ ++ li = calloc(LOCINFO_HASH_SIZE, sizeof *li); ++ ++ while (fgets(line, sizeof line, fp)) { ++ char *p = line, *code, *name, *comment; ++ uint32_t hash; ++ double latitude, longitude; ++ ++ while (isspace(*p)) ++ p++; ++ ++ if (*p == '#' || *p == '\0' || *p == '\n') ++ continue; ++ ++ if (!isalpha(p[0]) || !isalpha(p[1]) || p[2] != '\t') ++ continue; ++ ++ /* code => AA */ ++ code = p; ++ p[2] = 0; ++ p += 3; ++ ++ /* coords => [+-][D]DDMM[SS][+-][D]DDMM[SS] */ ++ p = parse_iso6709(p, &latitude); ++ if (!p) { ++ continue; ++ } ++ p = parse_iso6709(p, &longitude); ++ if (!p) { ++ continue; ++ } ++ ++ if (!p || *p != '\t') { ++ continue; ++ } ++ ++ /* name = string */ ++ name = ++p; ++ while (*p != '\t' && *p && *p != '\n') ++ p++; ++ ++ *p++ = '\0'; ++ ++ /* comment = string */ ++ comment = p; ++ while (*p != '\t' && *p && *p != '\n') ++ p++; ++ ++ if (*p == '\n' || *p == '\t') ++ *p = '\0'; ++ ++ hash = tz_hash(name); ++ i = malloc(sizeof *i); ++ memcpy(i->code, code, 2); ++ strncpy(i->name, name, sizeof i->name); ++ i->comment = strdup(comment); ++ i->longitude = longitude; ++ i->latitude = latitude; ++ i->next = li[hash]; ++ li[hash] = i; ++ /* printf("%s [%u, %f, %f]\n", name, hash, latitude, longitude); */ ++ } ++ ++ fclose(fp); ++ ++ return li; ++} ++ ++/* Return location info from hash table, using given timezone name. ++ * Returns NULL if the name could not be found. */ ++const struct location_info *find_zone_info(struct location_info **li, ++ const char *name) ++{ ++ uint32_t hash = tz_hash(name); ++ const struct location_info *l; ++ ++ if (!li) { ++ return NULL; ++ } ++ ++ for (l = li[hash]; l; l = l->next) { ++ if (timelib_strcasecmp(l->name, name) == 0) ++ return l; ++ } ++ ++ return NULL; ++} ++ ++/* Filter out some non-tzdata files and the posix/right databases, if ++ * present. */ ++static int index_filter(const struct dirent *ent) ++{ ++ return strcmp(ent->d_name, ".") != 0 ++ && strcmp(ent->d_name, "..") != 0 ++ && strcmp(ent->d_name, "posix") != 0 ++ && strcmp(ent->d_name, "posixrules") != 0 ++ && strcmp(ent->d_name, "right") != 0 ++ && strstr(ent->d_name, ".list") == NULL ++ && strstr(ent->d_name, ".tab") == NULL; ++} ++ ++static int sysdbcmp(const void *first, const void *second) ++{ ++ const timelib_tzdb_index_entry *alpha = first, *beta = second; ++ ++ return timelib_strcasecmp(alpha->id, beta->id); ++} ++ ++ ++/* Retrieve tzdata version. */ ++static void retrieve_zone_version(timelib_tzdb *db) ++{ ++ static char buf[30]; ++ char path[PATH_MAX]; ++ FILE *fp; ++ ++ strncpy(path, ZONEINFO_PREFIX "/tzdata.zi", sizeof(path)); ++ ++ fp = fopen(path, "r"); ++ if (fp) { ++ if (fgets(buf, sizeof(buf), fp)) { ++ if (!memcmp(buf, "# version ", 10) && ++ isdigit(buf[10]) && ++ isdigit(buf[11]) && ++ isdigit(buf[12]) && ++ isdigit(buf[13]) && ++ islower(buf[14])) { ++ if (buf[14] >= 't') { /* 2022t = 2022.20 */ ++ buf[17] = 0; ++ buf[16] = buf[14] - 't' + '0'; ++ buf[15] = '2'; ++ } else if (buf[14] >= 'j') { /* 2022j = 2022.10 */ ++ buf[17] = 0; ++ buf[16] = buf[14] - 'j' + '0'; ++ buf[15] = '1'; ++ } else { /* 2022a = 2022.1 */ ++ buf[16] = 0; ++ buf[15] = buf[14] - 'a' + '1'; ++ } ++ buf[14] = '.'; ++ db->version = buf+10; ++ } ++ } ++ fclose(fp); ++ } ++} ++ ++/* Create the zone identifier index by trawling the filesystem. */ ++static void create_zone_index(timelib_tzdb *db) ++{ ++ size_t dirstack_size, dirstack_top; ++ size_t index_size, index_next; ++ timelib_tzdb_index_entry *db_index; ++ char **dirstack; ++ ++ /* LIFO stack to hold directory entries to scan; each slot is a ++ * directory name relative to the zoneinfo prefix. */ ++ dirstack_size = 32; ++ dirstack = malloc(dirstack_size * sizeof *dirstack); ++ dirstack_top = 1; ++ dirstack[0] = strdup(""); ++ ++ /* Index array. */ ++ index_size = 64; ++ db_index = malloc(index_size * sizeof *db_index); ++ index_next = 0; ++ ++ do { ++ struct dirent **ents; ++ char name[PATH_MAX], *top; ++ int count; ++ ++ /* Pop the top stack entry, and iterate through its contents. */ ++ top = dirstack[--dirstack_top]; ++ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s", top); ++ ++ count = php_scandir(name, &ents, index_filter, php_alphasort); ++ ++ while (count > 0) { ++ struct stat st; ++ const char *leaf = ents[count - 1]->d_name; ++ ++ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s/%s", ++ top, leaf); ++ ++ if (strlen(name) && stat(name, &st) == 0) { ++ /* Name, relative to the zoneinfo prefix. */ ++ const char *root = top; ++ ++ if (root[0] == '/') root++; ++ ++ snprintf(name, sizeof name, "%s%s%s", root, ++ *root ? "/": "", leaf); ++ ++ if (S_ISDIR(st.st_mode)) { ++ if (dirstack_top == dirstack_size) { ++ dirstack_size *= 2; ++ dirstack = realloc(dirstack, ++ dirstack_size * sizeof *dirstack); ++ } ++ dirstack[dirstack_top++] = strdup(name); ++ } ++ else { ++ if (index_next == index_size) { ++ index_size *= 2; ++ db_index = realloc(db_index, ++ index_size * sizeof *db_index); ++ } ++ ++ db_index[index_next++].id = strdup(name); ++ } ++ } ++ ++ free(ents[--count]); ++ } ++ ++ if (count != -1) free(ents); ++ free(top); ++ } while (dirstack_top); ++ ++ qsort(db_index, index_next, sizeof *db_index, sysdbcmp); ++ ++ db->index = db_index; ++ db->index_size = index_next; ++ ++ free(dirstack); ++} ++ ++#define FAKE_HEADER "1234\0??\1??" ++#define FAKE_UTC_POS (7 - 4) ++ ++/* Create a fake data segment for database 'sysdb'. */ ++static void fake_data_segment(timelib_tzdb *sysdb, ++ struct location_info **info) ++{ ++ size_t n; ++ char *data, *p; ++ ++ data = malloc(3 * sysdb->index_size + sizeof(FAKE_HEADER) - 1); ++ ++ p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1); ++ ++ for (n = 0; n < sysdb->index_size; n++) { ++ const struct location_info *li; ++ timelib_tzdb_index_entry *ent; ++ ++ ent = (timelib_tzdb_index_entry *)&sysdb->index[n]; ++ ++ /* Lookup the timezone name in the hash table. */ ++ if (strcmp(ent->id, "UTC") == 0) { ++ ent->pos = FAKE_UTC_POS; ++ continue; ++ } ++ ++ li = find_zone_info(info, ent->id); ++ if (li) { ++ /* If found, append the BC byte and the ++ * country code; set the position for this ++ * section of timezone data. */ ++ ent->pos = (p - data) - 4; ++ *p++ = '\1'; ++ *p++ = li->code[0]; ++ *p++ = li->code[1]; ++ } ++ else { ++ /* If not found, the timezone data can ++ * point at the header. */ ++ ent->pos = 0; ++ } ++ } ++ ++ sysdb->data = (unsigned char *)data; ++} ++ ++/* Returns true if the passed-in stat structure describes a ++ * probably-valid timezone file. */ ++static int is_valid_tzfile(const struct stat *st, int fd) ++{ ++ if (fd) { ++ char buf[20]; ++ if (read(fd, buf, 20)!=20) { ++ return 0; ++ } ++ lseek(fd, SEEK_SET, 0); ++ if (memcmp(buf, "TZif", 4)) { ++ return 0; ++ } ++ } ++ return S_ISREG(st->st_mode) && st->st_size > 20; ++} ++ ++/* To allow timezone names to be used case-insensitively, find the ++ * canonical name for this timezone, if possible. */ ++static const char *canonical_tzname(const char *timezone) ++{ ++ if (timezonedb_system) { ++ timelib_tzdb_index_entry *ent, lookup; ++ ++ lookup.id = (char *)timezone; ++ ++ ent = bsearch(&lookup, timezonedb_system->index, ++ timezonedb_system->index_size, sizeof lookup, ++ sysdbcmp); ++ if (ent) { ++ return ent->id; ++ } ++ } ++ ++ return timezone; ++} ++ ++/* Return the mmap()ed tzfile if found, else NULL. On success, the ++ * length of the mapped data is placed in *length. */ ++static char *map_tzfile(const char *timezone, size_t *length) ++{ ++ char fname[PATH_MAX]; ++ struct stat st; ++ char *p; ++ int fd; ++ ++ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) { ++ return NULL; ++ } ++ ++ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", canonical_tzname(timezone)); ++ ++ fd = open(fname, O_RDONLY); ++ if (fd == -1) { ++ return NULL; ++ } else if (fstat(fd, &st) != 0 || !is_valid_tzfile(&st, fd)) { ++ close(fd); ++ return NULL; ++ } ++ ++ *length = st.st_size; ++ p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ close(fd); ++ ++ return p != MAP_FAILED ? p : NULL; ++} ++ ++#endif ++ ++static int inmem_seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb) + { + int left = 0, right = tzdb->index_size - 1; + +@@ -438,9 +916,49 @@ static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const + return 0; + } + ++static int seek_to_tz_position(const unsigned char **tzf, char *timezone, ++ char **map, size_t *maplen, ++ const timelib_tzdb *tzdb) ++{ ++#ifdef HAVE_SYSTEM_TZDATA ++ if (tzdb == timezonedb_system) { ++ char *orig; ++ ++ orig = map_tzfile(timezone, maplen); ++ if (orig == NULL) { ++ return 0; ++ } ++ ++ (*tzf) = (unsigned char *)orig; ++ *map = orig; ++ return 1; ++ } ++ else ++#endif ++ { ++ return inmem_seek_to_tz_position(tzf, timezone, tzdb); ++ } ++} ++ + const timelib_tzdb *timelib_builtin_db(void) + { ++#ifdef HAVE_SYSTEM_TZDATA ++ if (timezonedb_system == NULL) { ++ timelib_tzdb *tmp = malloc(sizeof *tmp); ++ ++ tmp->version = "0.system"; ++ tmp->data = NULL; ++ create_zone_index(tmp); ++ retrieve_zone_version(tmp); ++ system_location_table = create_location_table(); ++ fake_data_segment(tmp, system_location_table); ++ timezonedb_system = tmp; ++ } ++ ++ return timezonedb_system; ++#else + return &timezonedb_builtin; ++#endif + } + + const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count) +@@ -452,7 +970,30 @@ const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_ + int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb) + { + const unsigned char *tzf; +- return (seek_to_tz_position(&tzf, timezone, tzdb)); ++ ++#ifdef HAVE_SYSTEM_TZDATA ++ if (tzdb == timezonedb_system) { ++ char fname[PATH_MAX]; ++ struct stat st; ++ ++ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) { ++ return 0; ++ } ++ ++ if (system_location_table) { ++ if (find_zone_info(system_location_table, timezone) != NULL) { ++ /* found in cache */ ++ return 1; ++ } ++ } ++ ++ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", canonical_tzname(timezone)); ++ ++ return stat(fname, &st) == 0 && is_valid_tzfile(&st, 0); ++ } ++#endif ++ ++ return (inmem_seek_to_tz_position(&tzf, timezone, tzdb)); + } + + static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz) +@@ -494,12 +1035,14 @@ static timelib_tzinfo* timelib_tzinfo_ctor(char *name) + timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, int *error_code) + { + const unsigned char *tzf; ++ char *memmap = NULL; ++ size_t maplen; + timelib_tzinfo *tmp; + int version; + int transitions_result, types_result; + unsigned int type; /* TIMELIB_TZINFO_PHP or TIMELIB_TZINFO_ZONEINFO */ + +- if (seek_to_tz_position(&tzf, timezone, tzdb)) { ++ if (seek_to_tz_position(&tzf, timezone, &memmap, &maplen, tzdb)) { + tmp = timelib_tzinfo_ctor(timezone); + + version = read_preamble(&tzf, tmp, &type); +@@ -534,11 +1077,36 @@ timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, i + } + skip_posix_string(&tzf, tmp); + ++#ifdef HAVE_SYSTEM_TZDATA ++ if (memmap) { ++ const struct location_info *li; ++ ++ /* TZif-style - grok the location info from the system database, ++ * if possible. */ ++ ++ if ((li = find_zone_info(system_location_table, timezone)) != NULL) { ++ tmp->location.comments = timelib_strdup(li->comment); ++ strncpy(tmp->location.country_code, li->code, 2); ++ tmp->location.longitude = li->longitude; ++ tmp->location.latitude = li->latitude; ++ tmp->bc = 1; ++ } ++ else { ++ set_default_location_and_comments(&tzf, tmp); ++ } ++ ++ /* Now done with the mmap segment - discard it. */ ++ munmap(memmap, maplen); ++ } else { ++#endif + if (type == TIMELIB_TZINFO_PHP) { + read_location(&tzf, tmp); + } else { + set_default_location_and_comments(&tzf, tmp); + } ++#ifdef HAVE_SYSTEM_TZDATA ++ } ++#endif + } else { + *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE; + tmp = NULL; +diff --git a/ext/date/php_date.c b/ext/date/php_date.c +index e1a427c5ca..465906fa2b 100644 +--- a/ext/date/php_date.c ++++ b/ext/date/php_date.c +@@ -951,7 +951,11 @@ PHP_MINFO_FUNCTION(date) + php_info_print_table_row(2, "date/time support", "enabled"); + php_info_print_table_row(2, "timelib version", TIMELIB_ASCII_VERSION); + php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version); ++#ifdef HAVE_SYSTEM_TZDATA ++ php_info_print_table_row(2, "Timezone Database", "system"); ++#else + php_info_print_table_row(2, "Timezone Database", php_date_global_timezone_db_enabled ? "external" : "internal"); ++#endif + php_info_print_table_row(2, "Default timezone", guess_timezone(tzdb)); + php_info_print_table_end(); + diff --git a/php-7.4.0-embed.patch b/php-7.4.0-embed.patch new file mode 100644 index 0000000..f7a9aaa --- /dev/null +++ b/php-7.4.0-embed.patch @@ -0,0 +1,24 @@ +--- php-5.6.3/sapi/embed/config.m4.embed ++++ php-5.6.3/sapi/embed/config.m4 +@@ -11,7 +11,8 @@ if test "$PHP_EMBED" != "no"; then + case "$PHP_EMBED" in + yes|shared) + PHP_EMBED_TYPE=shared +- INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(prefix)/lib; \$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)\$(prefix)/lib" ++ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -release \$(PHP_MAJOR_VERSION).\$(PHP_MINOR_VERSION)" ++ INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(libdir); \$(LIBTOOL) --mode=install \$(INSTALL) -m 0755 \$(OVERALL_TARGET) \$(INSTALL_ROOT)\$(libdir)" + ;; + static) + PHP_EMBED_TYPE=static +diff -up php-5.5.30/scripts/php-config.in.old php-5.5.30/scripts/php-config.in +--- php-5.5.30/scripts/php-config.in.old 2015-10-19 15:17:31.944747715 +0200 ++++ php-5.5.30/scripts/php-config.in 2015-10-19 15:17:58.278858083 +0200 +@@ -18,7 +18,7 @@ exe_extension="@EXEEXT@" + php_cli_binary=NONE + php_cgi_binary=NONE + configure_options="@CONFIGURE_OPTIONS@" +-php_sapis="@PHP_INSTALLED_SAPIS@" ++php_sapis="apache2handler litespeed fpm phpdbg @PHP_INSTALLED_SAPIS@" + ini_dir="@EXPANDED_PHP_CONFIG_FILE_SCAN_DIR@" + ini_path="@EXPANDED_PHP_CONFIG_FILE_PATH@" + diff --git a/php-7.4.0-httpd.patch b/php-7.4.0-httpd.patch new file mode 100644 index 0000000..34f7c8a --- /dev/null +++ b/php-7.4.0-httpd.patch @@ -0,0 +1,27 @@ +Disable MPM detection + +mod_php is build twice +- as NTS without option +- as ZTS using --enable-maintainer-zts + +diff --git a/sapi/apache2handler/config.m4 b/sapi/apache2handler/config.m4 +--- a/sapi/apache2handler/config.m4 ++++ b/sapi/apache2handler/config.m4 +@@ -105,17 +105,6 @@ if test "$PHP_APXS2" != "no"; then + ;; + esac + +- if test "$APACHE_VERSION" -lt 2004001; then +- APXS_MPM=`$APXS -q MPM_NAME` +- if test "$APXS_MPM" != "prefork" && test "$APXS_MPM" != "peruser" && test "$APXS_MPM" != "itk"; then +- PHP_BUILD_THREAD_SAFE +- fi +- else +- APACHE_THREADED_MPM=`$APXS_HTTPD -V 2>/dev/null | grep 'threaded:.*yes'` +- if test -n "$APACHE_THREADED_MPM"; then +- PHP_BUILD_THREAD_SAFE +- fi +- fi + AC_MSG_RESULT(yes) + PHP_SUBST(APXS) + else diff --git a/php-7.4.0-ldap_r.patch b/php-7.4.0-ldap_r.patch new file mode 100644 index 0000000..13566b4 --- /dev/null +++ b/php-7.4.0-ldap_r.patch @@ -0,0 +1,19 @@ + +Use -lldap_r by default. + +diff -up php-7.4.0RC2/ext/ldap/config.m4.ldap_r php-7.4.0RC2/ext/ldap/config.m4 +--- php-7.4.0RC2/ext/ldap/config.m4.ldap_r 2019-09-17 10:21:24.769200812 +0200 ++++ php-7.4.0RC2/ext/ldap/config.m4 2019-09-17 10:21:30.658181771 +0200 +@@ -68,7 +68,11 @@ if test "$PHP_LDAP" != "no"; then + dnl -pc removal is a hack for clang + MACHINE_INCLUDES=$($CC -dumpmachine | $SED 's/-pc//') + +- if test -f $LDAP_LIBDIR/liblber.a || test -f $LDAP_LIBDIR/liblber.$SHLIB_SUFFIX_NAME || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/liblber.a || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/liblber.$SHLIB_SUFFIX_NAME; then ++ if test -f $LDAP_LIBDIR/libldap_r.$SHLIB_SUFFIX_NAME; then ++ PHP_ADD_LIBRARY_WITH_PATH(lber, $LDAP_LIBDIR, LDAP_SHARED_LIBADD) ++ PHP_ADD_LIBRARY_WITH_PATH(ldap_r, $LDAP_LIBDIR, LDAP_SHARED_LIBADD) ++ ++ elif test -f $LDAP_LIBDIR/liblber.a || test -f $LDAP_LIBDIR/liblber.$SHLIB_SUFFIX_NAME || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/liblber.a || test -f $LDAP_LIBDIR/$MACHINE_INCLUDES/liblber.$SHLIB_SUFFIX_NAME; then + PHP_ADD_LIBRARY_WITH_PATH(lber, $LDAP_LIBDIR, LDAP_SHARED_LIBADD) + PHP_ADD_LIBRARY_WITH_PATH(ldap, $LDAP_LIBDIR, LDAP_SHARED_LIBADD) + diff --git a/php-7.4.0-phpize.patch b/php-7.4.0-phpize.patch new file mode 100644 index 0000000..fb99f3e --- /dev/null +++ b/php-7.4.0-phpize.patch @@ -0,0 +1,35 @@ +diff -up ./scripts/phpize.in.headers ./scripts/phpize.in +--- ./scripts/phpize.in.headers 2019-07-23 10:05:11.000000000 +0200 ++++ ./scripts/phpize.in 2019-07-23 10:18:13.648098089 +0200 +@@ -165,6 +165,15 @@ phpize_autotools() + $PHP_AUTOHEADER || exit 1 + } + ++phpize_check_headers() ++{ ++ if test ! -f $includedir/main/php.h; then ++ echo "Can't find PHP headers in $includedir" ++ echo "The php-devel package is required for use of this command." ++ exit 1 ++ fi ++} ++ + # Main script + + case "$1" in +@@ -183,12 +192,15 @@ case "$1" in + + # Version + --version|-v) ++ phpize_check_headers + phpize_print_api_numbers + exit 0 + ;; + + # Default + *) ++ phpize_check_headers ++ + phpize_check_configm4 0 + + phpize_check_build_files diff --git a/php-7.4.20-argon2.patch b/php-7.4.20-argon2.patch new file mode 100644 index 0000000..73a1452 --- /dev/null +++ b/php-7.4.20-argon2.patch @@ -0,0 +1,15 @@ +diff --git a/ext/sodium/sodium_pwhash.c b/ext/sodium/sodium_pwhash.c +index 2b284c7116..4a453255e2 100644 +--- a/ext/sodium/sodium_pwhash.c ++++ b/ext/sodium/sodium_pwhash.c +@@ -64,10 +64,6 @@ static inline int get_options(zend_array *options, size_t *memlimit, size_t *ops + return FAILURE; + } + } +- if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && (zval_get_long(opt) != 1)) { +- php_error_docref(NULL, E_WARNING, "A thread value other than 1 is not supported by this implementation"); +- return FAILURE; +- } + return SUCCESS; + } + diff --git a/php-7.4.26-openssl3.patch b/php-7.4.26-openssl3.patch new file mode 100644 index 0000000..c23c517 --- /dev/null +++ b/php-7.4.26-openssl3.patch @@ -0,0 +1,2604 @@ +From d040474c7c9d6d94e10c6757e5f100ecacabf19f Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@php.net> +Date: Sun, 8 Aug 2021 17:38:30 +0200 +Subject: [PATCH 01/27] minimal fix for openssl 3.0 (#7002) + +(cherry picked from commit a0972deb0f441fc7991001cb51efc994b70a3b51) +--- + ext/openssl/openssl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index aa819be422..9cb643601c 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -1517,7 +1517,9 @@ PHP_MINIT_FUNCTION(openssl) + REGISTER_LONG_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_CS|CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PADDING", RSA_PKCS1_PADDING, CONST_CS|CONST_PERSISTENT); ++#ifdef RSA_SSLV23_PADDING + REGISTER_LONG_CONSTANT("OPENSSL_SSLV23_PADDING", RSA_SSLV23_PADDING, CONST_CS|CONST_PERSISTENT); ++#endif + REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); + +-- +2.41.0 + +From ef7710bd3a3ce04ddada7221bf7ba9410d1a0fe8 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 09:41:39 +0200 +Subject: [PATCH 02/27] ignore deprecated + +--- + ext/openssl/openssl.c | 2 ++ + ext/openssl/tests/bug79145.phpt | 11 ++++++----- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 9cb643601c..2f2a7981da 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -25,6 +25,8 @@ + #include "config.h" + #endif + ++# pragma GCC diagnostic ignored "-Wdeprecated-declarations" ++ + #include "php.h" + #include "php_ini.h" + #include "php_openssl.h" +diff --git a/ext/openssl/tests/bug79145.phpt b/ext/openssl/tests/bug79145.phpt +index 348831189b..b2cb6164bd 100644 +--- a/ext/openssl/tests/bug79145.phpt ++++ b/ext/openssl/tests/bug79145.phpt +@@ -14,13 +14,14 @@ j85Q5OliVxOdB1LoTOsOmfFf/fdvpU3DsOWsDKlVrL41MHxXorwrwOiys/r/gv2d + C9C4JmhTOjBVAK8SewIDAQAC + -----END PUBLIC KEY-----'; + ++$a = openssl_get_publickey($b); ++@openssl_free_key($a); ++ + $start = memory_get_usage(true); +-for ($i = 0; $i < 100000; $i++) { +- $a = openssl_get_publickey($b); +- openssl_free_key($a); +-} ++$a = openssl_get_publickey($b); ++@openssl_free_key($a); + $end = memory_get_usage(true); +-var_dump($end <= 1.1 * $start); ++var_dump($end == $start); + ?> + --EXPECT-- + bool(true) +-- +2.41.0 + +From c421e4e98b35c1744f784c05ffd34583fbe96c37 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 09:46:07 +0200 +Subject: [PATCH 03/27] Reduce security level in some OpenSSL tests + +This allows tests using older protocols and algorithms to work +under OpenSSL 3. + +Also account for minor changes in error reporting. + +(cherry picked from commit 3ea57cf83834e07aae6953201015e39b4a2ac6dd) +--- + ext/openssl/tests/session_meta_capture.phpt | 4 ++-- + ext/openssl/tests/stream_crypto_flags_001.phpt | 4 ++-- + ext/openssl/tests/stream_crypto_flags_002.phpt | 4 ++-- + ext/openssl/tests/stream_crypto_flags_003.phpt | 4 ++-- + ext/openssl/tests/stream_crypto_flags_004.phpt | 4 ++-- + ext/openssl/tests/stream_security_level.phpt | 6 +++--- + ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt | 4 ++-- + ext/openssl/tests/tls_wrapper.phpt | 4 ++-- + ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt | 4 ++-- + ext/openssl/tests/tlsv1.0_wrapper.phpt | 4 ++-- + ext/openssl/tests/tlsv1.1_wrapper.phpt | 4 ++-- + 11 files changed, 23 insertions(+), 23 deletions(-) + +diff --git a/ext/openssl/tests/session_meta_capture.phpt b/ext/openssl/tests/session_meta_capture.phpt +index d7169fe1f8..ebd442d0e5 100644 +--- a/ext/openssl/tests/session_meta_capture.phpt ++++ b/ext/openssl/tests/session_meta_capture.phpt +@@ -15,7 +15,7 @@ $serverCode = <<<'CODE' + $serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; + $serverCtx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); +@@ -37,7 +37,7 @@ $clientCode = <<<'CODE' + 'cafile' => '%s', + 'peer_name' => '%s', + 'capture_session_meta' => true, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/stream_crypto_flags_001.phpt b/ext/openssl/tests/stream_crypto_flags_001.phpt +index acd97110ff..a86e0f8a6c 100644 +--- a/ext/openssl/tests/stream_crypto_flags_001.phpt ++++ b/ext/openssl/tests/stream_crypto_flags_001.phpt +@@ -15,7 +15,7 @@ $serverCode = <<<'CODE' + $serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; + $serverCtx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); +@@ -35,7 +35,7 @@ $clientCode = <<<'CODE' + 'verify_peer' => true, + 'cafile' => '%s', + 'peer_name' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/stream_crypto_flags_002.phpt b/ext/openssl/tests/stream_crypto_flags_002.phpt +index 15b1ec2cfc..2870bdc814 100644 +--- a/ext/openssl/tests/stream_crypto_flags_002.phpt ++++ b/ext/openssl/tests/stream_crypto_flags_002.phpt +@@ -15,7 +15,7 @@ $serverCode = <<<'CODE' + $serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; + $serverCtx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); +@@ -36,7 +36,7 @@ $clientCode = <<<'CODE' + 'verify_peer' => true, + 'cafile' => '%s', + 'peer_name' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/stream_crypto_flags_003.phpt b/ext/openssl/tests/stream_crypto_flags_003.phpt +index 35f83f22dd..da1f1ae228 100644 +--- a/ext/openssl/tests/stream_crypto_flags_003.phpt ++++ b/ext/openssl/tests/stream_crypto_flags_003.phpt +@@ -19,7 +19,7 @@ $serverCode = <<<'CODE' + + // Only accept TLSv1.0 and TLSv1.2 connections + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); +@@ -40,7 +40,7 @@ $clientCode = <<<'CODE' + 'verify_peer' => true, + 'cafile' => '%s', + 'peer_name' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/stream_crypto_flags_004.phpt b/ext/openssl/tests/stream_crypto_flags_004.phpt +index d9bfcfea3f..b7626b8ea7 100644 +--- a/ext/openssl/tests/stream_crypto_flags_004.phpt ++++ b/ext/openssl/tests/stream_crypto_flags_004.phpt +@@ -16,7 +16,7 @@ $serverCode = <<<'CODE' + $serverCtx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); +@@ -37,7 +37,7 @@ $clientCode = <<<'CODE' + 'verify_peer' => true, + 'cafile' => '%s', + 'peer_name' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/stream_security_level.phpt b/ext/openssl/tests/stream_security_level.phpt +index a377101c37..28ef1fc3d5 100644 +--- a/ext/openssl/tests/stream_security_level.phpt ++++ b/ext/openssl/tests/stream_security_level.phpt +@@ -24,8 +24,8 @@ $serverCode = <<<'CODE' + 'local_cert' => '%s', + // Make sure the server side starts up successfully if the default security level is + // higher. We want to test the error at the client side. +- 'security_level' => 1, +- ]]); ++ 'security_level' => 0, ++ ]]); + + $server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); + phpt_notify(); +@@ -66,7 +66,7 @@ ServerClientTestCase::getInstance()->run($clientCode, $serverCode); + ?> + --EXPECTF-- + Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: +-error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in %s : eval()'d code on line %d ++error:%s:SSL routines:%S:certificate verify failed in %s : eval()'d code on line %d + + Warning: stream_socket_client(): Failed to enable crypto in %s : eval()'d code on line %d + +diff --git a/ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt b/ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt +index ac31192da4..73dd812291 100644 +--- a/ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt ++++ b/ext/openssl/tests/tls_min_v1.0_max_v1.1_wrapper.phpt +@@ -15,7 +15,7 @@ $serverCode = <<<'CODE' + 'local_cert' => '%s', + 'min_proto_version' => STREAM_CRYPTO_PROTO_TLSv1_0, + 'max_proto_version' => STREAM_CRYPTO_PROTO_TLSv1_1, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +@@ -32,7 +32,7 @@ $clientCode = <<<'CODE' + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/tls_wrapper.phpt b/ext/openssl/tests/tls_wrapper.phpt +index d79e978c10..3488f6f7f0 100644 +--- a/ext/openssl/tests/tls_wrapper.phpt ++++ b/ext/openssl/tests/tls_wrapper.phpt +@@ -14,7 +14,7 @@ $serverCode = <<<'CODE' + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $ctx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +@@ -31,7 +31,7 @@ $clientCode = <<<'CODE' + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt b/ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt +index b419179b3f..c8a0245601 100644 +--- a/ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt ++++ b/ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt +@@ -14,7 +14,7 @@ $serverCode = <<<'CODE' + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $ctx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +@@ -31,7 +31,7 @@ $clientCode = <<<'CODE' + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/tlsv1.0_wrapper.phpt b/ext/openssl/tests/tlsv1.0_wrapper.phpt +index adbe7b6308..fc802662ac 100644 +--- a/ext/openssl/tests/tlsv1.0_wrapper.phpt ++++ b/ext/openssl/tests/tlsv1.0_wrapper.phpt +@@ -13,7 +13,7 @@ $serverCode = <<<'CODE' + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $ctx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server('tlsv1.0://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +@@ -30,7 +30,7 @@ $clientCode = <<<'CODE' + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +diff --git a/ext/openssl/tests/tlsv1.1_wrapper.phpt b/ext/openssl/tests/tlsv1.1_wrapper.phpt +index c1aaa04919..84a137b5f4 100644 +--- a/ext/openssl/tests/tlsv1.1_wrapper.phpt ++++ b/ext/openssl/tests/tlsv1.1_wrapper.phpt +@@ -13,7 +13,7 @@ $serverCode = <<<'CODE' + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $ctx = stream_context_create(['ssl' => [ + 'local_cert' => '%s', +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + $server = stream_socket_server('tlsv1.1://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +@@ -30,7 +30,7 @@ $clientCode = <<<'CODE' + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, +- 'security_level' => 1, ++ 'security_level' => 0, + ]]); + + phpt_wait(); +-- +2.41.0 + +From dfbbf02d413db19dd3337b5b60c55eb974ebb2b7 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 09:57:40 +0200 +Subject: [PATCH 04/27] Adjust some tests for whitespace differences in OpenSSL + 3 + +A trailing newline is no longer present in OpenSSL 3. + +(cherry picked from commit 0a530d7650c6f9cb7c1b55755c8bf5961052039c) +--- + ext/openssl/tests/bug28382.phpt | 17 +++++++---------- + ext/openssl/tests/cve2013_4073.phpt | 5 ++--- + ext/openssl/tests/openssl_x509_parse_basic.phpt | 10 ++++------ + 3 files changed, 13 insertions(+), 19 deletions(-) + +diff --git a/ext/openssl/tests/bug28382.phpt b/ext/openssl/tests/bug28382.phpt +index f64e77dbd2..00765ba838 100644 +--- a/ext/openssl/tests/bug28382.phpt ++++ b/ext/openssl/tests/bug28382.phpt +@@ -9,11 +9,10 @@ if (!extension_loaded("openssl")) die("skip"); + $cert = file_get_contents(__DIR__ . "/bug28382cert.txt"); + $ext = openssl_x509_parse($cert); + var_dump($ext['extensions']); +-/* openssl 1.0 prepends the string "Full Name:" to the crlDistributionPoints array key. +- For now, as this is the one difference only between 0.9.x and 1.x, it's handled with +- placeholders to not to duplicate the test. When more diffs come, a duplication would +- be probably a better solution. +-*/ ++/* ++ * The reason for %A at the end of crlDistributionPoints and authorityKeyIdentifier is that ++ * OpenSSL 3.0 removes new lines which were present in previous versions. ++ */ + ?> + --EXPECTF-- + array(11) { +@@ -24,8 +23,7 @@ array(11) { + ["nsCertType"]=> + string(30) "SSL Client, SSL Server, S/MIME" + ["crlDistributionPoints"]=> +- string(%d) "%AURI:http://mobile.blue-software.ro:90/ca/crl.shtml +-" ++ string(%d) "%AURI:http://mobile.blue-software.ro:90/ca/crl.shtml%A" + ["nsCaPolicyUrl"]=> + string(38) "http://mobile.blue-software.ro:90/pub/" + ["subjectAltName"]=> +@@ -33,9 +31,8 @@ array(11) { + ["subjectKeyIdentifier"]=> + string(59) "B0:A7:FF:F9:41:15:DE:23:39:BD:DD:31:0F:97:A0:B2:A2:74:E0:FC" + ["authorityKeyIdentifier"]=> +- string(115) "DirName:/C=RO/ST=Romania/L=Craiova/O=Sergiu/OU=Sergiu SRL/CN=Sergiu CA/emailAddress=n_sergiu@hotmail.com +-serial:00 +-" ++ string(%d) "DirName:/C=RO/ST=Romania/L=Craiova/O=Sergiu/OU=Sergiu SRL/CN=Sergiu CA/emailAddress=n_sergiu@hotmail.com ++serial:00%A" + ["keyUsage"]=> + string(71) "Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment" + ["nsBaseUrl"]=> +diff --git a/ext/openssl/tests/cve2013_4073.phpt b/ext/openssl/tests/cve2013_4073.phpt +index c88021b0ae..5cd05ab040 100644 +--- a/ext/openssl/tests/cve2013_4073.phpt ++++ b/ext/openssl/tests/cve2013_4073.phpt +@@ -9,11 +9,10 @@ $info = openssl_x509_parse($cert); + var_export($info['extensions']); + + ?> +---EXPECT-- ++--EXPECTF-- + array ( + 'basicConstraints' => 'CA:FALSE', + 'subjectKeyIdentifier' => '88:5A:55:C0:52:FF:61:CD:52:A3:35:0F:EA:5A:9C:24:38:22:F7:5C', + 'keyUsage' => 'Digital Signature, Non Repudiation, Key Encipherment', +- 'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, email:null@python.org' . "\0" . 'user@example.org, URI:http://null.python.org' . "\0" . 'http://example.org, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1 +-', ++ 'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, email:null@python.org' . "\0" . 'user@example.org, URI:http://null.python.org' . "\0" . 'http://example.org, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1%A', + ) +diff --git a/ext/openssl/tests/openssl_x509_parse_basic.phpt b/ext/openssl/tests/openssl_x509_parse_basic.phpt +index b80c1f71f1..38915157f3 100644 +--- a/ext/openssl/tests/openssl_x509_parse_basic.phpt ++++ b/ext/openssl/tests/openssl_x509_parse_basic.phpt +@@ -153,10 +153,9 @@ array(16) { + ["subjectKeyIdentifier"]=> + string(59) "DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D" + ["authorityKeyIdentifier"]=> +- string(202) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D ++ string(%d) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D + DirName:/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net +-serial:AE:C5:56:CC:72:37:50:A2 +-" ++serial:AE:C5:56:CC:72:37:50:A2%A" + ["basicConstraints"]=> + string(7) "CA:TRUE" + } +@@ -301,10 +300,9 @@ array(16) { + ["subjectKeyIdentifier"]=> + string(59) "DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D" + ["authorityKeyIdentifier"]=> +- string(202) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D ++ string(%d) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D + DirName:/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net +-serial:AE:C5:56:CC:72:37:50:A2 +-" ++serial:AE:C5:56:CC:72:37:50:A2%A" + ["basicConstraints"]=> + string(7) "CA:TRUE" + } +-- +2.41.0 + +From a8e511110696e83f728faee9294798351c84fb85 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 11:55:47 +0200 +Subject: [PATCH 05/27] Use different cipher in openssl_seal() test + +RC4 is insecure and not supported in newer versions. + +(cherry picked from commit 046b36bcf8c062375c9f5e2a763d6144c2a484b4) +--- + ext/openssl/tests/openssl_seal_basic.phpt | 25 ++++++++++++----------- + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/ext/openssl/tests/openssl_seal_basic.phpt b/ext/openssl/tests/openssl_seal_basic.phpt +index 111bf6f094..588efa707b 100644 +--- a/ext/openssl/tests/openssl_seal_basic.phpt ++++ b/ext/openssl/tests/openssl_seal_basic.phpt +@@ -9,23 +9,24 @@ $a = 1; + $b = array(1); + $c = array(1); + $d = array(1); ++$method = "AES-128-ECB"; + +-var_dump(openssl_seal($a, $b, $c, $d)); +-var_dump(openssl_seal($a, $a, $a, array())); +-var_dump(openssl_seal($c, $c, $c, 1)); +-var_dump(openssl_seal($b, $b, $b, "")); ++var_dump(openssl_seal($a, $b, $c, $d, $method)); ++var_dump(openssl_seal($a, $a, $a, array(), $method)); ++var_dump(openssl_seal($c, $c, $c, 1, $method)); ++var_dump(openssl_seal($b, $b, $b, "", $method)); + + // tests with cert + $data = "openssl_open() test"; + $pub_key = "file://" . __DIR__ . "/public.key"; + $wrong = "wrong"; + +-var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key))); // no output +-var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key))); // no output +-var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $wrong))); +-var_dump(openssl_seal($data, $sealed, $ekeys, $pub_key)); +-var_dump(openssl_seal($data, $sealed, $ekeys, array())); +-var_dump(openssl_seal($data, $sealed, $ekeys, array($wrong))); ++var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key), $method)); // no output ++var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), $method)); // no output ++var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $wrong), $method)); ++var_dump(openssl_seal($data, $sealed, $ekeys, $pub_key, $method)); ++var_dump(openssl_seal($data, $sealed, $ekeys, array(), $method)); ++var_dump(openssl_seal($data, $sealed, $ekeys, array($wrong), $method)); + + echo "Done\n"; + ?> +@@ -41,8 +42,8 @@ NULL + + Warning: openssl_seal() expects parameter 1 to be string, array given in %s on line %d + NULL +-int(19) +-int(19) ++int(32) ++int(32) + + Warning: openssl_seal(): not a public key (2th member of pubkeys) in %s on line %d + bool(false) +-- +2.41.0 + +From 54f6bd9814a09d57b80933b1cedfd4266286bb9a Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 11:58:46 +0200 +Subject: [PATCH 06/27] Don't test legacy algorithms in SPKI tests + +MD4 and RMD160 may not be available on newer OpenSSL versions. + +(cherry picked from commit 9695936341c49ea0efec5bdf24acbcdf59e2a7f8) +--- + ext/openssl/tests/openssl_spki_export_basic.phpt | 4 ---- + .../tests/openssl_spki_export_challenge_basic.phpt | 14 -------------- + ext/openssl/tests/openssl_spki_new_basic.phpt | 8 -------- + ext/openssl/tests/openssl_spki_verify_basic.phpt | 7 ------- + 4 files changed, 33 deletions(-) + +diff --git a/ext/openssl/tests/openssl_spki_export_basic.phpt b/ext/openssl/tests/openssl_spki_export_basic.phpt +index 4085d2d5d8..c03954390b 100644 +--- a/ext/openssl/tests/openssl_spki_export_basic.phpt ++++ b/ext/openssl/tests/openssl_spki_export_basic.phpt +@@ -19,14 +19,12 @@ foreach ($key_sizes as $key_size) { + + /* array of available hashings to test */ + $algo = array( +- OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, +- OPENSSL_ALGO_RMD160 + ); + + /* loop over key sizes for test */ +@@ -56,5 +54,3 @@ function _uuid() { + \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- + \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- + \-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +-\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +-\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +diff --git a/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt b/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt +index f44e60ec62..06308bf10c 100644 +--- a/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt ++++ b/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt +@@ -21,14 +21,12 @@ foreach ($key_sizes as $key_size) { + + /* array of available hashings to test */ + $algo = array( +- OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, +- OPENSSL_ALGO_RMD160 + ); + + /* loop over key sizes for test */ +@@ -89,15 +87,3 @@ string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" + bool\(false\) + string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" + bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +-string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" +-bool\(false\) +diff --git a/ext/openssl/tests/openssl_spki_new_basic.phpt b/ext/openssl/tests/openssl_spki_new_basic.phpt +index cb54747fe0..8378bd1ac6 100644 +--- a/ext/openssl/tests/openssl_spki_new_basic.phpt ++++ b/ext/openssl/tests/openssl_spki_new_basic.phpt +@@ -18,14 +18,12 @@ foreach ($key_sizes as $key_size) { + + /* array of available hashings to test */ + $algo = array( +- OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, +- OPENSSL_ALGO_RMD160 + ); + + /* loop over key sizes for test */ +@@ -53,21 +51,15 @@ string(478) "%s" + string(478) "%s" + string(478) "%s" + string(478) "%s" +-string(478) "%s" +-string(474) "%s" +-string(830) "%s" + string(830) "%s" + string(830) "%s" + string(830) "%s" + string(830) "%s" + string(830) "%s" + string(830) "%s" +-string(826) "%s" +-string(1510) "%s" + string(1510) "%s" + string(1510) "%s" + string(1510) "%s" + string(1510) "%s" + string(1510) "%s" + string(1510) "%s" +-string(1506) "%s" +diff --git a/ext/openssl/tests/openssl_spki_verify_basic.phpt b/ext/openssl/tests/openssl_spki_verify_basic.phpt +index c760d0cb83..35badcda37 100644 +--- a/ext/openssl/tests/openssl_spki_verify_basic.phpt ++++ b/ext/openssl/tests/openssl_spki_verify_basic.phpt +@@ -25,7 +25,6 @@ $algo = array( + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, +- OPENSSL_ALGO_RMD160 + ); + + /* loop over key sizes for test */ +@@ -80,9 +79,3 @@ bool(true) + bool(false) + bool(true) + bool(false) +-bool(true) +-bool(false) +-bool(true) +-bool(false) +-bool(true) +-bool(false) +-- +2.41.0 + +From 9f5fa8ab4e8d5ba1e9e12eac956ba658e2047b93 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 12:48:02 +0200 +Subject: [PATCH 07/27] Only report provided ciphers in + openssl_get_cipher_methods() + +With OpenSSL 3 ciphers may be registered, but not provided. Make +sure that openssl_get_cipher_methods() only returns provided +ciphers, so that "in_array openssl_get_cipher_methods" style +checks continue working as expected. + +(cherry picked from commit a80ae97d3176aded77ee422772608a026380fc1a) +--- + ext/openssl/openssl.c | 34 +++++++++++++++++++++++++++++++++- + ext/openssl/php_openssl.h | 4 +++- + 2 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 2f2a7981da..e0b3772a29 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -6393,6 +6393,31 @@ PHP_FUNCTION(openssl_get_md_methods) + } + /* }}} */ + ++#if PHP_OPENSSL_API_VERSION >= 0x30000 ++static void php_openssl_add_cipher_name(const char *name, void *arg) ++{ ++ size_t len = strlen(name); ++ zend_string *str = zend_string_alloc(len, 0); ++ zend_str_tolower_copy(ZSTR_VAL(str), name, len); ++ add_next_index_str((zval*)arg, str); ++} ++ ++static void php_openssl_add_cipher_or_alias(EVP_CIPHER *cipher, void *arg) ++{ ++ EVP_CIPHER_names_do_all(cipher, php_openssl_add_cipher_name, arg); ++} ++ ++static void php_openssl_add_cipher(EVP_CIPHER *cipher, void *arg) ++{ ++ php_openssl_add_cipher_name(EVP_CIPHER_get0_name(cipher), arg); ++} ++ ++static int php_openssl_compare_func(const void *a, const void *b) ++{ ++ return string_compare_function(&((Bucket *)a)->val, &((Bucket *)b)->val); ++} ++#endif ++ + /* {{{ proto array openssl_get_cipher_methods([bool aliases = false]) + Return array of available cipher methods */ + PHP_FUNCTION(openssl_get_cipher_methods) +@@ -6403,9 +6428,16 @@ PHP_FUNCTION(openssl_get_cipher_methods) + return; + } + array_init(return_value); ++#if PHP_OPENSSL_API_VERSION >= 0x30000 ++ EVP_CIPHER_do_all_provided(NULL, ++ aliases ? php_openssl_add_cipher_or_alias : php_openssl_add_cipher, ++ return_value); ++ zend_hash_sort(Z_ARRVAL_P(return_value), php_openssl_compare_func, 1); ++#else + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, +- aliases ? php_openssl_add_method_or_alias: php_openssl_add_method, ++ aliases ? php_openssl_add_method_or_alias : php_openssl_add_method, + return_value); ++#endif + } + /* }}} */ + +diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h +index 7926b475e7..29d64171d9 100644 +--- a/ext/openssl/php_openssl.h ++++ b/ext/openssl/php_openssl.h +@@ -41,8 +41,10 @@ extern zend_module_entry openssl_module_entry; + #define PHP_OPENSSL_API_VERSION 0x10001 + #elif OPENSSL_VERSION_NUMBER < 0x10100000L + #define PHP_OPENSSL_API_VERSION 0x10002 +-#else ++#elif OPENSSL_VERSION_NUMBER < 0x30000000L + #define PHP_OPENSSL_API_VERSION 0x10100 ++#else ++#define PHP_OPENSSL_API_VERSION 0x30000 + #endif + #endif + +-- +2.41.0 + +From d03ccc6933b4e585980458455b17cb384a3e5ab6 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 12:05:02 +0200 +Subject: [PATCH 08/27] Avoid RC4 use in another test + +(cherry picked from commit 503146aa87e48f075f47a093ed7868e323814a66) +--- + ext/openssl/tests/openssl_open_basic.phpt | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/ext/openssl/tests/openssl_open_basic.phpt b/ext/openssl/tests/openssl_open_basic.phpt +index d564bcf8e8..e19f07e7b1 100644 +--- a/ext/openssl/tests/openssl_open_basic.phpt ++++ b/ext/openssl/tests/openssl_open_basic.phpt +@@ -8,15 +8,16 @@ $data = "openssl_open() test"; + $pub_key = "file://" . __DIR__ . "/public.key"; + $priv_key = "file://" . __DIR__ . "/private_rsa_1024.key"; + $wrong = "wrong"; ++$method = "AES-128-ECB"; + +-openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key, $pub_key)); +-openssl_open($sealed, $output, $ekeys[0], $priv_key); ++openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key, $pub_key), $method); ++openssl_open($sealed, $output, $ekeys[0], $priv_key, $method); + var_dump($output); +-openssl_open($sealed, $output2, $ekeys[1], $wrong); ++openssl_open($sealed, $output2, $ekeys[1], $wrong, $method); + var_dump($output2); +-openssl_open($sealed, $output3, $ekeys[2], $priv_key); ++openssl_open($sealed, $output3, $ekeys[2], $priv_key, $method); + var_dump($output3); +-openssl_open($sealed, $output4, $wrong, $priv_key); ++openssl_open($sealed, $output4, $wrong, $priv_key, $method); + var_dump($output4); + ?> + --EXPECTF-- +-- +2.41.0 + +From cafc815c45cdc12ab559c2e9e1c1af0500ca0ca5 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Thu, 5 Aug 2021 11:50:11 +0200 +Subject: [PATCH 09/27] Relax error check + +The precise error is version-dependent, just check that there +is some kind of error reported. + +(cherry picked from commit cd8bf0b6bd23e03bdc8d069df53a2d976809a916) +--- + ext/openssl/tests/bug80747.phpt | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/ext/openssl/tests/bug80747.phpt b/ext/openssl/tests/bug80747.phpt +index 327c916688..3f319b4b24 100644 +--- a/ext/openssl/tests/bug80747.phpt ++++ b/ext/openssl/tests/bug80747.phpt +@@ -14,11 +14,9 @@ $conf = array( + 'private_key_bits' => 511, + ); + var_dump(openssl_pkey_new($conf)); +-while ($e = openssl_error_string()) { +- echo $e, "\n"; +-} ++var_dump(openssl_error_string() !== false); + + ?> +---EXPECTF-- ++--EXPECT-- + bool(false) +-error:%s:key size too small ++bool(true) +-- +2.41.0 + +From 736d5d5eac86df2e5710111f90a0196ce9335c60 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Thu, 5 Aug 2021 14:59:16 +0200 +Subject: [PATCH 10/27] Add test for openssl_dh_compute_key() + +This function was not tested at all :( + +(cherry picked from commit 7168f71e00676172e7fcf710adfc07eccd6714e6) +--- + ext/openssl/tests/openssl_dh_compute_key.phpt | 29 +++++++++++++++++++ + 1 file changed, 29 insertions(+) + create mode 100644 ext/openssl/tests/openssl_dh_compute_key.phpt + +diff --git a/ext/openssl/tests/openssl_dh_compute_key.phpt b/ext/openssl/tests/openssl_dh_compute_key.phpt +new file mode 100644 +index 0000000000..8730f4b57d +--- /dev/null ++++ b/ext/openssl/tests/openssl_dh_compute_key.phpt +@@ -0,0 +1,29 @@ ++--TEST-- ++openssl_dh_compute_key() ++--FILE-- ++<?php ++ ++$privateKey = <<<'KEY' ++-----BEGIN PRIVATE KEY----- ++MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBANn6weB11zG7izhfzM4qsITZ ++3q/ORkF6+h3RTn7sh8Ji1MpHt3zHcPfdYFvs7V5SJfNN5Xv9L62RN8GwgxwRWIJr ++8VBHfL3LyZNMMgnGBGJR0qmoM48iNd8i2ggZYj+H8WVh2y6tGw1YsDI3AFHpZFkN ++TvCT1JHl2JfNEgOgSryBO84KDEWLxWaN/4Nqa9x5R0fxKMLjpWNRzEBBKcVeEHIZ ++gzl7VKVJEpYC336sjYJE19ZD0O/gWl+q4WeRpDazDi6LDLZgnoDrUgbNAXtDETKL ++gKOnYq+iwRWCQicQmaQvGXntmgdriExVacrRnH8o09ioxcVdtPG8WuLeqJczCvsC ++AQIEggEEAoIBAH1yv00aZkw/7IIAJL1fZUrpVeO3xKIQDl982HOKS32+o2mUJWbc ++DuDMIOvqiUEltEnFQOqDaJue0ucseJdH5Q9JHlSIhuUQiPB/JfEcPlb2QYzXHuAE ++fWS94X0wiSxYgKXIL0XceA3yg5bYhDSR3DntdJrbboyYHt/QGQ8WCWiYEa402ovI ++x+r7k3BlGxah33HeuqhMCFAfFvWUhLaj85QEmjHTjVMKeeTlNfBS+nscbCcZvLXd ++qanvRxYYGdOhgLTcJe/iUsxmAWVTiqrid8MEvtFrenanawTgnPXAp5WtYTCGcsiQ ++TBG24ND/tnZpPoPz/Rwlpo1IL4IbvKGRsfU= ++-----END PRIVATE KEY----- ++KEY; ++ ++$publicKey = hex2bin("29ECC536A85A4AFAD7D63E50545C68CE44A834396886E9A7BAC27E3A08A14C05259BA6E9940FDC512457155A60CAFACD8E43897E1B537A282D39697B75357197B5E3AD7F1826C0216604496AFAEF8999FBCE336C148166AE23E77EC66C0611235110FA8D6180A26425154959FACEC18FEE3EDA68E9355627820C14B44B486C9547ECE62BE72D56A7FAC4747AFCF201D8A4155F63A076234D6BC04DE27E7A7849BF8956E3DB6E51C043CB6FC66889ADE1F8DE756E9194838E8EF8A5CF9C0DD553282DE8A3130CA7752C22C191E5C352AC3BD77EF9270BF37BC807BBDB3F39AE7966B013723E71EAF41082A056D994F64B428183C5BAFEE9C7A41CABCEA868FC34"); ++ ++echo bin2hex(openssl_dh_compute_key($publicKey, openssl_get_privatekey($privateKey))), "\n"; ++ ++?> ++--EXPECT-- ++b0049944fa5d36f364dd02e675dde50f8c2d67481c5cf0fe2f248d383eec1d38c23d5ed2644fbef2676bcd6ce148361ca82619c8f93e10506cb89d0a1bdaa0f0bc6f68cef0f7cb6d97d43e8dda3c7a5c5a98ebd2342a605ce530fd46a0602d28d4afc48e92088d0bc42194ca8682a85317f812d81b86cd284eed405df2f76aae84ccd560856e8a3d0ce4f591394bca02eb8a1984ebb41bb19714fb8b579bcafd36a9051d51d075f66229893289d8a0c918bfd222f17803cc532d2cf93bb2a567953323ca409beb3237faae9c6fdfc671594324953badd07dd4770ee09fd19f90045654c5709e92aa614b83594c2f62a8bc3c7e786e54bc1259a0a737c70dd4cc +-- +2.41.0 + +From 95ede22356cdcfb4053850437eb3bb59f8190e5c Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 14:54:59 +0200 +Subject: [PATCH 11/27] Use different algorithm in pkcs7 tests + +The default of OPENSSL_CIPHER_RC2_40 is no longer (non-legacy) +supported in OpenSSL 3, specify a newer cipher instead. + +We should probably either change the default (if acceptable) or +make the parameter required. + +(cherry picked from commit 563b3e3472d7c5e3502fb49ef023b6e18ed0f22a) +--- + .../tests/openssl_pkcs7_decrypt_basic.phpt | 3 +- + .../tests/openssl_pkcs7_encrypt_basic.phpt | 31 +++++++------------ + 2 files changed, 14 insertions(+), 20 deletions(-) + +diff --git a/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt b/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt +index 937180a22e..ed2b8be6fb 100644 +--- a/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt ++++ b/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt +@@ -19,8 +19,9 @@ $single_cert = "file://" . __DIR__ . "/cert.crt"; + $headers = array("test@test", "testing openssl_pkcs7_encrypt()"); + $wrong = "wrong"; + $empty = ""; ++$cipher = OPENSSL_CIPHER_AES_128_CBC; + +-openssl_pkcs7_encrypt($infile, $encrypted, $single_cert, $headers); ++openssl_pkcs7_encrypt($infile, $encrypted, $single_cert, $headers, 0, $cipher); + var_dump(openssl_pkcs7_decrypt($encrypted, $outfile, $single_cert, $privkey)); + var_dump(openssl_pkcs7_decrypt($encrypted, $outfile, openssl_x509_read($single_cert), $privkey)); + var_dump(openssl_pkcs7_decrypt($encrypted, $outfile, $single_cert, $wrong)); +diff --git a/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt b/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt +index f823462f9e..e38a006d0c 100644 +--- a/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt ++++ b/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt +@@ -20,21 +20,20 @@ $headers = array("test@test", "testing openssl_pkcs7_encrypt()"); + $empty_headers = array(); + $wrong = "wrong"; + $empty = ""; ++$cipher = OPENSSL_CIPHER_AES_128_CBC; + +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, openssl_x509_read($single_cert), $headers)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, openssl_x509_read($single_cert), $headers, 0, $cipher)); + var_dump(openssl_pkcs7_decrypt($outfile, $outfile2, $single_cert, $privkey)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $assoc_headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $empty_headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $wrong)); +-var_dump(openssl_pkcs7_encrypt($wrong, $outfile, $single_cert, $headers)); +-var_dump(openssl_pkcs7_encrypt($empty, $outfile, $single_cert, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $empty, $single_cert, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $wrong, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $empty, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $empty)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, $multi_certs, $headers)); +-var_dump(openssl_pkcs7_encrypt($infile, $outfile, array_map('openssl_x509_read', $multi_certs) , $headers)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $assoc_headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $single_cert, $empty_headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($wrong, $outfile, $single_cert, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($empty, $outfile, $single_cert, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $empty, $single_cert, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $wrong, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $empty, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, $multi_certs, $headers, 0, $cipher)); ++var_dump(openssl_pkcs7_encrypt($infile, $outfile, array_map('openssl_x509_read', $multi_certs), $headers, 0, $cipher)); + + if (file_exists($outfile)) { + echo "true\n"; +@@ -51,17 +50,11 @@ bool(true) + bool(true) + bool(true) + bool(true) +- +-Warning: openssl_pkcs7_encrypt() expects parameter 4 to be array, string given in %s on line %d +-bool(false) + bool(false) + bool(false) + bool(false) + bool(false) + bool(false) +- +-Warning: openssl_pkcs7_encrypt() expects parameter 4 to be array, string given in %s on line %d +-bool(false) + bool(true) + bool(true) + true +-- +2.41.0 + +From 1942dc87aaa0e473ec74d5be68866b327a2dd62b Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Thu, 5 Aug 2021 17:07:44 +0200 +Subject: [PATCH 12/27] Use larger key size for DSA/DH tests + +OpenSSL 3 validates allowed sizes strictly, pick minimum sizes +that are supported. + +(cherry picked from commit 1cf4fb739f7a4fa8404a4c0958f13d04eae519d4) +--- + ext/openssl/tests/bug73711.cnf | 3 --- + ext/openssl/tests/bug73711.phpt | 11 ++++++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + delete mode 100644 ext/openssl/tests/bug73711.cnf + +diff --git a/ext/openssl/tests/bug73711.cnf b/ext/openssl/tests/bug73711.cnf +deleted file mode 100644 +index 0d27d910d4..0000000000 +--- a/ext/openssl/tests/bug73711.cnf ++++ /dev/null +@@ -1,3 +0,0 @@ +-[ req ] +-default_bits = 384 +- +diff --git a/ext/openssl/tests/bug73711.phpt b/ext/openssl/tests/bug73711.phpt +index c5f5575e2c..7beb020a4c 100644 +--- a/ext/openssl/tests/bug73711.phpt ++++ b/ext/openssl/tests/bug73711.phpt +@@ -6,9 +6,14 @@ if (!extension_loaded("openssl")) die("skip openssl not loaded"); + ?> + --FILE-- + <?php +-$cnf = __DIR__ . DIRECTORY_SEPARATOR . 'bug73711.cnf'; +-var_dump(openssl_pkey_new(["private_key_type" => OPENSSL_KEYTYPE_DSA, 'config' => $cnf])); +-var_dump(openssl_pkey_new(["private_key_type" => OPENSSL_KEYTYPE_DH, 'config' => $cnf])); ++var_dump(openssl_pkey_new([ ++ "private_key_type" => OPENSSL_KEYTYPE_DSA, ++ "private_key_bits" => 1024, ++])); ++var_dump(openssl_pkey_new([ ++ "private_key_type" => OPENSSL_KEYTYPE_DH, ++ "private_key_bits" => 512, ++])); + echo "DONE"; + ?> + --EXPECTF-- +-- +2.41.0 + +From b8904668632df0eadb5f24b365f1b2189f6694c7 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Wed, 4 Aug 2021 13:54:26 +0200 +Subject: [PATCH 13/27] Skip some tests if cipher not available + +(cherry picked from commit d23a8b33abc3cd7e516563877a3f698b7a94ac10) +--- + ext/openssl/tests/bug71917.phpt | 1 + + ext/openssl/tests/bug72362.phpt | 1 + + ext/openssl/tests/openssl_decrypt_basic.phpt | 15 ++++++++++----- + 3 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/ext/openssl/tests/bug71917.phpt b/ext/openssl/tests/bug71917.phpt +index a68cf0162c..0cc518c4ef 100644 +--- a/ext/openssl/tests/bug71917.phpt ++++ b/ext/openssl/tests/bug71917.phpt +@@ -3,6 +3,7 @@ Bug #71917: openssl_open() returns junk on envelope < 16 bytes + --SKIPIF-- + <?php + if (!extension_loaded("openssl")) die("skip openssl not loaded"); ++if (!in_array('rc4', openssl_get_cipher_methods())) die('skip rc4 not available'); + ?> + --FILE-- + <?php +diff --git a/ext/openssl/tests/bug72362.phpt b/ext/openssl/tests/bug72362.phpt +index cd6ec1e838..b73cac7425 100644 +--- a/ext/openssl/tests/bug72362.phpt ++++ b/ext/openssl/tests/bug72362.phpt +@@ -3,6 +3,7 @@ Bug #72362: OpenSSL Blowfish encryption is incorrect for short keys + --SKIPIF-- + <?php + if (!extension_loaded("openssl")) die("skip openssl not loaded"); ++if (!in_array('bf-ecb', openssl_get_cipher_methods())) die('skip bf-ecb not available'); + ?> + --FILE-- + <?php +diff --git a/ext/openssl/tests/openssl_decrypt_basic.phpt b/ext/openssl/tests/openssl_decrypt_basic.phpt +index 4175e703d2..e846b42e78 100644 +--- a/ext/openssl/tests/openssl_decrypt_basic.phpt ++++ b/ext/openssl/tests/openssl_decrypt_basic.phpt +@@ -24,10 +24,15 @@ $padded_data = $data . str_repeat(' ', 16 - (strlen($data) % 16)); + $encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); + $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); + var_dump(rtrim($output)); +-// if we want to prefer variable length cipher setting +-$encrypted = openssl_encrypt($data, "bf-ecb", $password, OPENSSL_DONT_ZERO_PAD_KEY); +-$output = openssl_decrypt($encrypted, "bf-ecb", $password, OPENSSL_DONT_ZERO_PAD_KEY); +-var_dump($output); ++ ++if (in_array("bf-ecb", openssl_get_cipher_methods())) { ++ // if we want to prefer variable length cipher setting ++ $encrypted = openssl_encrypt($data, "bf-ecb", $password, OPENSSL_DONT_ZERO_PAD_KEY); ++ $output = openssl_decrypt($encrypted, "bf-ecb", $password, OPENSSL_DONT_ZERO_PAD_KEY); ++ var_dump($output === $data); ++} else { ++ var_dump(true); ++} + + // It's okay to pass $tag for a non-authenticated cipher. + // It will be populated with null in that case. +@@ -39,5 +44,5 @@ var_dump($tag); + string(45) "openssl_encrypt() and openssl_decrypt() tests" + string(45) "openssl_encrypt() and openssl_decrypt() tests" + string(45) "openssl_encrypt() and openssl_decrypt() tests" +-string(45) "openssl_encrypt() and openssl_decrypt() tests" ++bool(true) + NULL +-- +2.41.0 + +From 1f611e84806818b53cda70708f7eb6d1915b2887 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Fri, 6 Aug 2021 10:35:49 +0200 +Subject: [PATCH 14/27] Generate pkcs12_read test inputs on the fly + +The old p12_with_extra_certs.p12 file uses an unsupported something. + +(cherry picked from commit 5843ba518cfb9ac6ae6d6a69629239cbf77d4cfb) +--- + ext/openssl/tests/bug74022_2.phpt | 10 ++-- + .../tests/openssl_pkcs12_read_basic.phpt | 46 ++++++++++--------- + 2 files changed, 31 insertions(+), 25 deletions(-) + +diff --git a/ext/openssl/tests/bug74022_2.phpt b/ext/openssl/tests/bug74022_2.phpt +index 07cb683274..4220149db2 100644 +--- a/ext/openssl/tests/bug74022_2.phpt ++++ b/ext/openssl/tests/bug74022_2.phpt +@@ -12,11 +12,13 @@ function test($p12_contents, $password) { + var_dump(count($cert_data['extracerts'])); + } + +-$p12_base64 = 'MIIW+QIBAzCCFr8GCSqGSIb3DQEHAaCCFrAEghasMIIWqDCCEV8GCSqGSIb3DQEHBqCCEVAwghFMAgEAMIIRRQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIQOfCxIAgGIICAggAgIIRGFTkvHpJjCtFjukXYVlhyOIqKiS8Zvg84dX244hhI0S51Uyn/tlXM2GD/3hDNVxcVKwP/fKN21lEkoXoK4h2/5BY3qCdZa3Ef3vk44b/+FGCUAqvsOo1ZjD2P/sBGhLu3aFnQ6ktUXlKV4cnqhlF62AqY4e5efQzmJXn+gI8cSNI5c+qQ0RQgGoRY4nJfvMSZG0/DAkirjGikU/2TZd8LwLkxVUBYbF5/T0fNtA3o99+4tF+8ZRv6ArYjplRdwcBbMbzGhn3ytCq6cmVid9iLjwHJFmvAPXKbmu0Lh5eRRznX9gBWlzGd08Q/ch0MW2ehZTu1A2VrNWl+FKWSk8l0MlSoTPJFutFiejRvMr6VzbQItyJ/mtrNa9b1Hicgoj9HaBB6arx4wKORlbSOxFNOWdTCUhFdqthK5o7b9i/owyVgyY0s7BFEZChc0zGpRq7BLrynY79b+pHKzpil9isuisp1++piHZx9Y/bpC7OP5FlYF9+3TJL0EpEFQD8FqEoqcMFRxIDWGpCQiLGcmL14OH1JKSgOJEAgogsIF/KQhvWeKcUSJlai+0sskl8mOrCt2EJwuRvzmemuzebYN3JMOiBXKONYR0yU8AeAyNTgSBimWhACtikUyfpgZXlIeXyFMvj9fmd0I/zqjaW4upqrCudCOj/CWx7+e+8udfJxI7agWwrZMf1BEkOhRFOHOIuV+IEbaoMP6vVrGlhK71oN+gnoes5ivohpFDJWSZ3+1fMh56vfNynuM2wLJO7FTROPla+4ug33V/2ubGpoIyXn2lTSbuXaYDfsXMa1inakOMW9Q+PHGdIjZrwQU/u9Q2H0IlwFd4uQojZo15SRf4xh5FOuUrrfGRAnp1mWHALTBqd2VnkgqtBl8rXZXqA+CiEhEDhTAQmvf+wCKd3FklrhV+p65YcfRK9OJv5aFQM1/+WbJozF4/Wi5j4rtIDPrgMMEflOyoZIxGxDOaklyAvaasRU2TT8E2LIEvGKOzlrhIZqWyRESjgXdh6l0UBMaVAidIZ0JLf+8fqSZ0Zia5iAaJpm82MQr/PVXC4lqqxDlHhefwM3OKfZVkfAw0a2eePM5YkIxAgMpAstBt32UIixlj/5l4MwqzP8Reb4MsV6Fph2e14vsV1diLBaJI3hrU5UBVEDWV0GSbwdhZLtdubSaBHcv5v9aZ1cdFKL6d2rHksW9ooNnh/ljPxmVlfHbb8sPYDXmLmBNJdNV1gQouhKKrt0ov1J9+sqE53D9+9dfRwf/myYlnyNgqU4vNMrZI2flyugkYoUxIC8stVF46zfL5QkSg3GqdLQC4gpeJ0WdTSyOBaOgUvqGdSARb5bXm1VXF5IxVg1B4v+puNIHS9yuphXUJvw6xWWPjbQAllDrPjMqAbxmF465vFyQP0qEvMjRD+SaFIgW4KjMqfteKo4MgqKTRF4UP9r0HkwRErOznxWDfSxzXYztY6U72NdifN9IIFiBikKQqZvfvaN+1jukehSRpGQHQB5OxeeKThJZJGiUC5Fgvl7lPb6Djx8Rfba/FJvVsR2KFS64sArtUKmC6LcJxEY9WcsiJTHek817zvYej7FD1NxuttNp+ue9ArOoIhOEf08HIOu3d2yjeRlN5CJ/jIdKYlZW6m6Ap1M+OUHhJTF73K6lKKD9Diwa3s6FoqOwtZF4uYwHnCG218BMY8GgEVD73x5KjDOP02Y6EakZNp/9QIqQT4WkMWXMaqAPADtoh8X1FJLlnvs2Ko+hLlPxuPaIA4KvSuuocnWx/6HJbdqHUS/Se+JJo0Igt4Svax1R2kvoIPuQmPmHJ6l7CeZZiNbe+baFSx+V6g/6AgHUsUOSqGvUIEns1uIE9CQ8w0G3yLVonjERJLrdj+em3Pt7fxrxoOI4nwjplX0wJk0rkQREiS8ULQDHueptUcxJxMKpugAc4CL+BsHohkhm4kpOEmviKDwzxytQhDp2Fj2PRO9kqyNrNfzNGCN5709blEIVYTtonELI2vR5Ap+O2pH+AlqrnHWgeOYAKAyWT13xCNRsGNdv2sCDDiHqxq01IBzYhPvoWzECOmGbJRRSGOVzYCJJpVjl0NNKv9ucmftSQRjm6xgLIqv1xrehDYuJ/IMsYQ5QwXBGxy7nkeRg+onWzA0ZnEWgzLs3T/Pj7z/TPQWiN03MH24RvQXTWBqp9iBwXpsCZVgUIM/VLCQJn0/V5gfRy9Ne0rk2/tHMnzGHvll5Spoy6WkxSfQ8c8CjTilaoPWV6fOcNB2Z6ZuTqX0fbnxcEAu2fOK7e6ryGipEgaxrdiopDTlgPEFMdGUETbUh0ACrv/gNsS+m5MtNisWnhxFEiXrsWoWIgW/6TgRJGo+l52bh/xxC0bwHbYuHK62sxDVeXpBOnA4VE+WckWsC0CKYJvv4vfTbLI46fyd3lnlcSuHYM4SdbND7THNeK+KB5GyuUFLgAhhtZv8ceEo63IOlBUUy1NlWnr0cbidxvVnOugFLExCV5QGr+xbrssIibQxs8AfOBK8Cxh83IlzJVe7dX1mZVG1c6AM6SKSC6F0LBOeNEvcLlz4PBMIciubCE6ecdXCzJYFbj9ERDlnrZMKrnATRMsgCPaWdyYgQwkDuCj5uqf4aiKLzA61918hLY3MB7mSyJcCkXDYKr11Br0YSAdu8uG6IjpiUQS2PFz8E8XHBmO/uobhEuCPR2LnUv+xFN8zoPQlA5ueRz1yBF8L+CsvDGp/N3KF26ETWlvmnEdt7foE+o/J7aG6xO/CNB+/+yGbVPZRVAntZec9nbqlQ55qECnWtQNnShW7+3RSGamWeTtE2DyRSfd/62JkPNEY25jbBUIkMNtKolA5dbYa+u50S3lvakMmvQvzcSC3PONajKHgk4mBn3qf9X2uM5RDL83M7489r6JPcxTnNK27rQoxplkxLiN8HuB+AB5hp82WoyvLydR4hoBnJPIYKMcmEfIR+SgLoCyNIQLjzk5Iyk1ZwdwsjyNPXi1/HHZq8+NhoTCupjGfWgXghoz89MTYAjpMvOlES2rgFuCdphSc8Nd1uQtZx4CLMOU0gut0PI81ePBBI0iG74PWMEcp5HlHHY/hPTaRkBFLYkq9CWmJc1PfjiCWf3pwRmT7dUnmcptynexIMOZt2Nd76jc+g7k5MmEK+Qdz7/c1un4sVLquxdY6nUY/znLz+2zC/OTSsF39+rak3p8TXR0kBNsHl8UTioi4CGhCMsWsQy9me25TDHzbtIvBPVp9xXufsOe2wqPLjq3iNEGXTsagx3sLvl7BJ6WW/YMC7sUpjx1Ai3zkqViW0jQB+BzMZjfYM/8Yj31EEE+WssxY+NfitBgZzeMGGjNOAKp7XN0glwhuo1G2/APyU/Zopx3gMYj5OExgkZ7kvK++7+NlPmE+8AEuZ/uf30TtKwvRXOSvAMqqm26kb/WQPCj1xFQ0AEDl0Sbyfgk1E51Cd/ujL0t32FNkSoE8pe3IaTnwAnW7NHTZ/RByh2nsr0ThfFg4pFFuSD4dzU8r2J/4YJG3B06eyyTRLoyLBQwzwIgzGBAU8USdD8CXlA8SkfBbF39500ZRNcMIt6wdQa1CHAUHDLPw9JF9Q0FwCspgkjc9+lTRZMtumN5ChgypSkUB1dzLV2hqeQzDngVjcco/CoxM0Svm8gGrM9qobCTGzGF8/wZljv1yRiqu6HGFYWDAQ/p+wWx6ScstxEAB+5R5GrOedgd4zPXi2NMvyeN+ACFRBSPkhXIXpLZADvBi/WQMYbHia1wL8WUrSGQuB4P46cWGyseaxl//6GQ9IoGbK3XuLIPeE+BpPLB0H9LSLY+5f3qOEkKzCCW0z+68ZMlanlsThLKhqk8yrmJhV4788Tr7BC3eGbAie1urrrfUR613Jsp5peLSJuWQHdWCE/fdKgoSsRJ+DYkPoyS1YNz4BF4yz1Oem9Mti7gvgTQNX6g6PCu0rN8B6HIgY9TvWy5OCoZjJKasb+OgTMld7TJDnyK5/JcvDKHNVwcpK74lxcVX7IRorP/eh4IQ1+P/Gh06A62RHp2dEh/fNuKeCiRM2vGH0gdIN/Ca6MX8MqazgJq2EONyWiqRoGPqqZpAVTa8l5kgGvxQE/CQ4x0uAxwresRRTUZ+fJEanAhTWYgI5mRoEkG88UZjyCWmCnpNMQRYHoq7iY0So5qUdkHvpUA48cNMyztPEEHsUyWC36ZCyNsQN26FoJrG9TqXedBrhcki0sPOWugvKtGsdTT354wJTDe5OCo0AH3eFo/auuuAk/DF7yu614UCmKtXHYJ61GpIkjBu9WrPAIJhndMqfGMD/yU4UMEPHyojqHvU0BSgv1k76vI3K2lqERkaNYFfzRNj+e7k+NNos8w7XCzilWBL2ePB3pG5xfivcH4tYFm0FbnIkSz52VIy+PTiK7QQuBPDRTcn1k41+9vxQxRWpsqM/NP+4gqGozNyANXLQ64Y+QXSnWrD+xMjL/kVFwUBJ2HaAIJHjZ7ZqLRzXVOUbQ9pivJiBkXvLptSo72Iw4zsbRd1x8WNEaihx1MBAj+s+4MNdC5MBkQMlSB0PTJzs9xlz0gN+Oz0lohH6JO7ngPJUYbo2AIWEYZN+9kn/RyHblQTElrJeLf1jGNi4anBfzbsIXQuVm/nsrE5MH23X66+rJzUk8Fc5JAIDGBslkDPg3UNnElcE3cYbcB/ZzjFtgz8ducWKQmI+Yqv4p7BVXji/rHPim8vL6P5xZc95tbIonp5bQH+PPSmcfDk3rrf5mS58dJvWh/UpwcfdVvUAsWLJEV1lUBg1qecVbCsa6Oy7tJ2ZK7e3KdtZrmXiYpSAnSzRNJotr4g4H99brG6IwUx3qk5BE4x3C8MpSb+1NcKnM9nhqwAGRb9sfVXG38eNltm7hDnsolQcFQmHkDSM4arUVRqmsG8O16bThtlFWbYYN355aGQxrO2pICnt0ZOAI5CA3Rl8FprhFZgVy4pcpMVwy2zCNaYGJoGYsxDm/lEWJbTGcVm6YkyaZvdkXM1uAVegLZOCKnlW9H7b1uU3NvUw4Qx3DhI5xMD9jZhlXIsYfa9s5NQjTeIX8fFbx1fdENpHjVRxs82DO26uLEaJpoL/Ywn1xfs1uV0VQb2NGPvUJKysjMRoX0Zfa0hsSBhw/ZSlyX1xfQY8ShusVswf3zEnwI1LTgtr0CvBNwnuaSDv/IoypEfCOuMrJEGJuTPDbGGyS4VeRf0He5Dk9RskehgrJcwhlw+hXajR6SluODcsEGfL+eOUjAOO9agWaqM2CfV52/vJNhA5KMEJwHuQAU1SHr4+xaW4EKWPlxB6Sjjz/IuL+toLBetBA3ZhEfokac6rQplUIiOICd3Ghwi1rpUZPL5YuP0murhpBGTdzMzGSMhSZ74LeAcoRKEG4rKKIS3fRS65QMlaLC6uOT8givHdXsk+4zLBF0BnYAe4bq8RDcpt9TJRczL6+NaxYxa36R+DRin4U1SwaUdIvEKaEDBdVLnzKkpAim5cww1MYkGZmFcVg8u8fSnoz5TeorZy00dQCMCC+SyMb58TTA08UrCOSq07+ILregexlx+Cxpbgpabo858lkJLDpPJmq8YQmog2gaMstJbpyV3M4wf1GL4ylPurPWUuyX58H8oRyX/FH79cpsbyeNoghwfvRVw8/tOUyF1DbA8Lw0HauIHTQwMTOvREPCPmlMvldIUJxHqIpqcsXESIWT/+YaHBiKGueGqPOdkFPtXSyf4t1Ka56M/9ftvdR/oFtr/iApE0Hyosz84INF/Rq9HYd8jrVb3IcQw637U2s4sE+I95+c+VaYxcDq29Jd2jD3uZfn6vbxb7Zz//Z8G4PGBNDns+D/jDoAMIIFQQYJKoZIhvcNAQcBoIIFMgSCBS4wggUqMIIFJgYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECDpR8wgSXD4AAgIIAASCBMijRdwb0L38qXtBGebx6l35L3eR8/NPfJTyDKqYQOiIhNfYp/f+Ml9g3NlCB+ba03BZBCFSo1a9csjMZ1fDgS5AoNE683hbPdNj6D5JYQtvOpX/D5rawmI0iuDTIc6GOpN5PS0ds9OLnlS6pagq3U7QycuiPR0jVq72qzQUDxnqXU0XO+IwQXFP5UhKrPJe/cbUotznQPGH5g88ydM9YelIvIVImXLlXeVLY8CtzRQPSduX1zckVUMktrpSvqJUhVuN4ikhh+4ga1LvtaziOibk6HNekSlN13sqSQ7GeWGToB1AOmN8i1LZmWRnrPG61dT3uPg0R/5rPq6hrNQvAnx7Mpq7Uz1OuzDzGoaBtX+/CVIpeYLAYm7hdKouT84hk7qsT9ls1Dwb5P1C8HjBWas0KufoyxoHL61A+xGIcHkbOeVNy20AFUf7Xhb+kPlSdOhP3Ik1F2iUXa0pFxqTNcsmTDRzAReciYxVJ0lOTbqX7O6/a+U/sT109GqVGZJcpyk1FCUSk3HWbjSKOhxjpvxqfSKexr9ZOTmih7rBNYSY6sRUYgtpQyWNo8iWilwSP3FCBCbRIJrzJ5O6wn0JDTHONqxS9zENz/MvX8oHEZk+mkpxZA4YCodP10zQjzKHsXI1lRWrUARzpDfqGck1BBXXLrLNDL3w+00ipkTdEgtdhNFtHZ7A0Fda62ys5JTKt/oWSi0FPhjXdGnxf+8rBkB/jlKx99Ue6R4S+ve7Eqyl98TelFvX5C6wa63+/kw4/8L5aSlhrAUyYrykmnZ9nb61YY4HTmwpSJP0tHmr3LHxPVx15vp3KIyrYQVvbap+FvfcLjMoU6ckLQDZpQSJdFo86MdNedrKbwmVN7pV/M2b3DjPp5ixLCSXJgK3RaATIxQL88IDv4+ySL0Z2t6jUopZ40liyDnHGDl9zajeQ1WaW4yHS65aVlzYHSFvCGr8F/4Lydk5ax5HHqna6LbFeuQ4kUcUaGfiIagtFW+ueyfOckqLnwYisjG5fQmheONPHb7jg/qHQoKasD4TvmwrvUcG20c5J57oZ80C94zySYpdHTaETXHEOwz7NBPP1hplC1IaAfbhwZ48Z0kWWqddfELUC5miapzthvzpycOzL6zWmTLjyTXPZrbkqYfVrD26bsD/YOo54BThGcBdEfu2chT2eNF0rRZwF5U9TACfzMFYxUIVRq4rWAaerppkK5JNBT/la2QxUElh9HPn+0GGL1BYYEPCihciwWy2BwJs1IgjhU4ARTlukuxK+WLPTflwvlOX5G1P5D57up8kxtDncR5IIuZJgWWSFLGOkGeHXmjynLMqS1OCzIId3dj0c3EYBnku82eItAQd5fk7/rs0Lg0S1XeVSrgPphTgviGXzTWSh28S3VZJ2G7k4dr1P/sJQounjbcDrFyYaFxYXEqyO9L6vFShO5z7/vD5h9uLPddE4vC6PKJxZoWopWncLcLljuYKG0k+y4MV9U0/cESYJWzBbcZZpULdesinhxMg1wNPu5FeeFCsZpdhN2FadIuu/Kcsk6xNeDDIwwYXb3hVY0ARRAo//LyLv3zDB0LWz1LH3qJQeZ53DbgZ4VXQ6uK0yTgSsH4Lwaj5oFBPp4NJ3hdGa7trpJbeUMIxJTAjBgkqhkiG9w0BCRUxFgQUh6FIxf4sbyJnvvC+6J1NHGaa9w0wMTAhMAkGBSsOAwIaBQAEFFkCkI701QHxh2zcZkzDy8bn7qKwBAjafnZaU5r0FgICCAA='; ++$cert = file_get_contents(__DIR__ . "/public.crt"); ++$priv = file_get_contents(__DIR__ . "/private.crt"); ++$extracert = file_get_contents(__DIR__ . "/cert.crt"); ++$pass = "qwerty"; ++openssl_pkcs12_export($cert, $p12, $priv, $pass, array('extracerts' => [$extracert, $extracert])); + +-$p12 = base64_decode($p12_base64); +- +-test($p12, 'qwerty'); ++test($p12, $pass); + ?> + ===DONE=== + --EXPECT-- +diff --git a/ext/openssl/tests/openssl_pkcs12_read_basic.phpt b/ext/openssl/tests/openssl_pkcs12_read_basic.phpt +index b81b4d9dac..8cb2b41fd7 100644 +--- a/ext/openssl/tests/openssl_pkcs12_read_basic.phpt ++++ b/ext/openssl/tests/openssl_pkcs12_read_basic.phpt +@@ -4,10 +4,12 @@ openssl_pkcs12_read() tests + <?php if (!extension_loaded("openssl")) print "skip"; ?> + --FILE-- + <?php +-$p12_file = __DIR__ . "/p12_with_extra_certs.p12"; +-$p12 = file_get_contents($p12_file); +-$certs = array(); ++ ++$cert = file_get_contents(__DIR__ . "/public.crt"); ++$priv = file_get_contents(__DIR__ . "/private.crt"); ++$extracert = file_get_contents(__DIR__ . "/cert.crt"); + $pass = "qwerty"; ++openssl_pkcs12_export($cert, $p12, $priv, $pass, array('extracerts' => $extracert)); + + var_dump(openssl_pkcs12_read("", $certs, "")); + var_dump(openssl_pkcs12_read($p12, $certs, "")); +@@ -73,24 +75,26 @@ MK80GEnRQIkB7uZVk+r0HusK + ["extracerts"]=> + array(1) { + [0]=> +- string(1111) "-----BEGIN CERTIFICATE----- +-MIIDBjCCAe4CCQDaL5/+UVeXuTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +-VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +-cyBQdHkgTHRkMB4XDTE1MDYxMDEyNDAwNVoXDTE2MDYwOTEyNDAwNVowRTELMAkG +-A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +-IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +-AL/IF7bW0vpEg5A054SDqTi5pkSeie6nyIT77qCAVI5PMlhNjxuqDIlLpCWonvKb +-LMRtp7t24BsQBRgQgps8mtfRr0gV1qq9HMfDj2bZdGcTShZN/M/BFATwxaNRTHl9 +-ey8zxGcLd4aFFBlVhXHYdBXg/PG/oxJMAFuMwa+KxSP6Mqp1FlOZtvUUieQcToMf +-Mh8Lbr4g/yHFj5lgWIJ2fmJjHJZ4wf9QBeGUrVqqxzSDEL9f0PGy+grqSHoIzLr3 +-+uhvhoI85nCyZs9+lrELuQKqbiZ8Q6Vmj6JGt3miNBFVTbBpP9GK8sVuVQwgqd8p +-C3e8hHqv7vwF+s0zjiZ+rCcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAdpTtiyDJ +-0wLB18iunXCMUJpjc/HVYEp5P9vl2E/bcZfGns/8KxNHoe9mgJycr3mwjCjMjVx2 +-L/9q/8XoT02aBncwAx4oZ2H0qfjZppaUSnSc1Uv+dsldDC2mZvJgwXN7jtQmU5P3 +-cspFHuJoYK8AqYJqlO6E4L9uRF7dLEliUnrBpF4BxziwskTquRX+zgD+fmk0L5O8 +-qqvm8btWCxfng+qD7UHFWbUQ2IegZ3VrBWJ2XsxOvokMM4HoHVb0BZgq8Dvu0XJ9 +-EriEQkcydtrRKtlcWHLKcJuNUnkw2qfj+F8mmdaZib8Apa1UCkt0ZlpyYO3V2ejY +-WIjafwJYrv6f5g== ++ string(1249) "-----BEGIN CERTIFICATE----- ++MIIDbDCCAtWgAwIBAgIJAK7FVsxyN1CiMA0GCSqGSIb3DQEBBQUAMIGBMQswCQYD ++VQQGEwJCUjEaMBgGA1UECBMRUmlvIEdyYW5kZSBkbyBTdWwxFTATBgNVBAcTDFBv ++cnRvIEFsZWdyZTEeMBwGA1UEAxMVSGVucmlxdWUgZG8gTi4gQW5nZWxvMR8wHQYJ ++KoZIhvcNAQkBFhBobmFuZ2Vsb0BwaHAubmV0MB4XDTA4MDYzMDEwMjg0M1oXDTA4 ++MDczMDEwMjg0M1owgYExCzAJBgNVBAYTAkJSMRowGAYDVQQIExFSaW8gR3JhbmRl ++IGRvIFN1bDEVMBMGA1UEBxMMUG9ydG8gQWxlZ3JlMR4wHAYDVQQDExVIZW5yaXF1 ++ZSBkbyBOLiBBbmdlbG8xHzAdBgkqhkiG9w0BCQEWEGhuYW5nZWxvQHBocC5uZXQw ++gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMteno+QK1ulX4/WDAVBYfoTPRTz ++e4SZLwgael4jwWTytj+8c5nNllrFELD6WjJzfjaoIMhCF4w4I2bkWR6/PTqrvnv+ ++iiiItHfKvJgYqIobUhkiKmWa2wL3mgqvNRIqTrTC4jWZuCkxQ/ksqL9O/F6zk+aR ++S1d+KbPaqCR5Rw+lAgMBAAGjgekwgeYwHQYDVR0OBBYEFNt+QHK9XDWF7CkpgRLo ++Ymhqtz99MIG2BgNVHSMEga4wgauAFNt+QHK9XDWF7CkpgRLoYmhqtz99oYGHpIGE ++MIGBMQswCQYDVQQGEwJCUjEaMBgGA1UECBMRUmlvIEdyYW5kZSBkbyBTdWwxFTAT ++BgNVBAcTDFBvcnRvIEFsZWdyZTEeMBwGA1UEAxMVSGVucmlxdWUgZG8gTi4gQW5n ++ZWxvMR8wHQYJKoZIhvcNAQkBFhBobmFuZ2Vsb0BwaHAubmV0ggkArsVWzHI3UKIw ++DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCP1GUnStC0TBqngr3Kx+zS ++UW8KutKO0ORc5R8aV/x9LlaJrzPyQJgiPpu5hXogLSKRIHxQS3X2+Y0VvIpW72LW ++PVKPhYlNtO3oKnfoJGKin0eEhXRZMjfEW/kznY+ZZmNifV2r8s+KhNAqI4PbClvn ++4vh8xF/9+eVEj+hM+0OflA== + -----END CERTIFICATE----- + " + } +-- +2.41.0 + +From 770edaa92bbf183455a60b902b12fc33ff56e95a Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Sun, 8 Aug 2021 20:54:46 +0100 +Subject: [PATCH 15/27] Make CertificateGenerator not dependent on external + config in OpenSSL 3.0 + +(cherry picked from commit c90c9c7545427d9d35cbac45c4ec896f54619744) +--- + ext/openssl/tests/CertificateGenerator.inc | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/ext/openssl/tests/CertificateGenerator.inc b/ext/openssl/tests/CertificateGenerator.inc +index b409376058..6fe9b4e9a8 100644 +--- a/ext/openssl/tests/CertificateGenerator.inc ++++ b/ext/openssl/tests/CertificateGenerator.inc +@@ -65,7 +65,10 @@ class CertificateGenerator + ), + null, + $this->caKey, +- 2 ++ 2, ++ [ ++ 'config' => self::CONFIG, ++ ] + ); + } + +@@ -101,6 +104,7 @@ class CertificateGenerator + [ req ] + distinguished_name = req_distinguished_name + default_md = sha256 ++default_bits = 1024 + + [ req_distinguished_name ] + +@@ -124,8 +128,9 @@ CONFIG; + ]; + + $this->lastKey = self::generateKey($keyLength); ++ $csr = openssl_csr_new($dn, $this->lastKey, $config); + $this->lastCert = openssl_csr_sign( +- openssl_csr_new($dn, $this->lastKey, $config), ++ $csr, + $this->ca, + $this->caKey, + /* days */ 2, +@@ -139,7 +144,7 @@ CONFIG; + openssl_x509_export($this->lastCert, $certText); + + $keyText = ''; +- openssl_pkey_export($this->lastKey, $keyText); ++ openssl_pkey_export($this->lastKey, $keyText, null, $config); + + file_put_contents($file, $certText . PHP_EOL . $keyText); + } finally { +-- +2.41.0 + +From 1234e56683d3f040eb98f7aabf745cf7baccc0e4 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Tue, 10 Aug 2021 11:50:18 +0200 +Subject: [PATCH 16/27] Fork openssl_error_string() test for OpenSSL + +The used error code differ signficantly, so use a separate test +file. + +openssl_encrypt() no longer throws an error for invalid key length, +which looks like an upstream bug. + +(cherry picked from commit e5f53e1ca13bfe8abd0f6037c98b59d2dac5744f) +--- + ext/openssl/tests/openssl_error_string_basic.phpt | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt +index cdf558e9a5..f9f0e7062f 100644 +--- a/ext/openssl/tests/openssl_error_string_basic.phpt ++++ b/ext/openssl/tests/openssl_error_string_basic.phpt +@@ -1,7 +1,10 @@ + --TEST-- +-openssl_error_string() tests ++openssl_error_string() tests (OpenSSL < 3.0) + --SKIPIF-- +-<?php if (!extension_loaded("openssl")) print "skip"; ?> ++<?php ++if (!extension_loaded("openssl")) print "skip"; ++if (OPENSSL_VERSION_NUMBER >= 0x30000000) die('skip For OpenSSL < 3.0'); ++?> + --FILE-- + <?php + // helper function to check openssl errors +-- +2.41.0 + +From 49c081a3d22d621a3024d7ea4c32f0350228c60b Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Sun, 8 Aug 2021 17:39:06 +0200 +Subject: [PATCH 17/27] Use OpenSSL NCONF APIs (#7337) + +(cherry picked from commit 94bc5fce261a4a56a545bdfb25d5c2452a07de08) +--- + ext/openssl/openssl.c | 66 +++++++++++++++++++++++-------------------- + 1 file changed, 36 insertions(+), 30 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index e0b3772a29..666616e7c5 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -835,8 +835,8 @@ int php_openssl_get_ssl_stream_data_index() + static char default_ssl_conf_filename[MAXPATHLEN]; + + struct php_x509_request { /* {{{ */ +- LHASH_OF(CONF_VALUE) * global_config; /* Global SSL config */ +- LHASH_OF(CONF_VALUE) * req_config; /* SSL config for this request */ ++ CONF *global_config; /* Global SSL config */ ++ CONF *req_config; /* SSL config for this request */ + const EVP_MD * md_alg; + const EVP_MD * digest; + char * section_name, +@@ -1048,13 +1048,13 @@ static time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr) /* {{{ */ + } + /* }}} */ + +-static inline int php_openssl_config_check_syntax(const char * section_label, const char * config_filename, const char * section, LHASH_OF(CONF_VALUE) * config) /* {{{ */ ++static inline int php_openssl_config_check_syntax(const char * section_label, const char * config_filename, const char * section, CONF *config) /* {{{ */ + { + X509V3_CTX ctx; + + X509V3_set_ctx_test(&ctx); +- X509V3_set_conf_lhash(&ctx, config); +- if (!X509V3_EXT_add_conf(config, &ctx, (char *)section, NULL)) { ++ X509V3_set_nconf(&ctx, config); ++ if (!X509V3_EXT_add_nconf(config, &ctx, (char *)section, NULL)) { + php_openssl_store_errors(); + php_error_docref(NULL, E_WARNING, "Error loading %s section %s of %s", + section_label, +@@ -1066,17 +1066,24 @@ static inline int php_openssl_config_check_syntax(const char * section_label, co + } + /* }}} */ + +-static char *php_openssl_conf_get_string( +- LHASH_OF(CONF_VALUE) *conf, const char *group, const char *name) { +- char *str = CONF_get_string(conf, group, name); +- if (str == NULL) { +- /* OpenSSL reports an error if a configuration value is not found. +- * However, we don't want to generate errors for optional configuration. */ +- ERR_clear_error(); +- } ++static char *php_openssl_conf_get_string(CONF *conf, const char *group, const char *name) { ++ /* OpenSSL reports an error if a configuration value is not found. ++ * However, we don't want to generate errors for optional configuration. */ ++ ERR_set_mark(); ++ char *str = NCONF_get_string(conf, group, name); ++ ERR_pop_to_mark(); + return str; + } + ++static long php_openssl_conf_get_number(CONF *conf, const char *group, const char *name) { ++ /* Same here, ignore errors. */ ++ long res = 0; ++ ERR_set_mark(); ++ NCONF_get_number(conf, group, name, &res); ++ ERR_pop_to_mark(); ++ return res; ++} ++ + static int php_openssl_add_oid_section(struct php_x509_request * req) /* {{{ */ + { + char * str; +@@ -1088,7 +1095,7 @@ static int php_openssl_add_oid_section(struct php_x509_request * req) /* {{{ */ + if (str == NULL) { + return SUCCESS; + } +- sktmp = CONF_get_section(req->req_config, str); ++ sktmp = NCONF_get_section(req->req_config, str); + if (sktmp == NULL) { + php_openssl_store_errors(); + php_error_docref(NULL, E_WARNING, "problem loading oid section %s", str); +@@ -1159,13 +1166,13 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option + + SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename); + SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req"); +- req->global_config = CONF_load(NULL, default_ssl_conf_filename, NULL); +- if (req->global_config == NULL) { ++ req->global_config = NCONF_new(NULL); ++ if (!NCONF_load(req->global_config, default_ssl_conf_filename, NULL)) { + php_openssl_store_errors(); + } +- req->req_config = CONF_load(NULL, req->config_filename, NULL); +- if (req->req_config == NULL) { +- php_openssl_store_errors(); ++ ++ req->req_config = NCONF_new(NULL); ++ if (!NCONF_load(req->req_config, req->config_filename, NULL)) { + return FAILURE; + } + +@@ -1189,8 +1196,7 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option + SET_OPTIONAL_STRING_ARG("req_extensions", req->request_extensions_section, + php_openssl_conf_get_string(req->req_config, req->section_name, "req_extensions")); + SET_OPTIONAL_LONG_ARG("private_key_bits", req->priv_key_bits, +- CONF_get_number(req->req_config, req->section_name, "default_bits")); +- ++ php_openssl_conf_get_number(req->req_config, req->section_name, "default_bits")); + SET_OPTIONAL_LONG_ARG("private_key_type", req->priv_key_type, OPENSSL_KEYTYPE_DEFAULT); + + if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key", sizeof("encrypt_key")-1)) != NULL) { +@@ -1270,11 +1276,11 @@ static void php_openssl_dispose_config(struct php_x509_request * req) /* {{{ */ + req->priv_key = NULL; + } + if (req->global_config) { +- CONF_free(req->global_config); ++ NCONF_free(req->global_config); + req->global_config = NULL; + } + if (req->req_config) { +- CONF_free(req->req_config); ++ NCONF_free(req->req_config); + req->req_config = NULL; + } + } +@@ -3134,12 +3140,12 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z + STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL; + char * str, *dn_sect, *attr_sect; + +- dn_sect = CONF_get_string(req->req_config, req->section_name, "distinguished_name"); ++ dn_sect = NCONF_get_string(req->req_config, req->section_name, "distinguished_name"); + if (dn_sect == NULL) { + php_openssl_store_errors(); + return FAILURE; + } +- dn_sk = CONF_get_section(req->req_config, dn_sect); ++ dn_sk = NCONF_get_section(req->req_config, dn_sect); + if (dn_sk == NULL) { + php_openssl_store_errors(); + return FAILURE; +@@ -3148,7 +3154,7 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z + if (attr_sect == NULL) { + attr_sk = NULL; + } else { +- attr_sk = CONF_get_section(req->req_config, attr_sect); ++ attr_sk = NCONF_get_section(req->req_config, attr_sect); + if (attr_sk == NULL) { + php_openssl_store_errors(); + return FAILURE; +@@ -3554,8 +3560,8 @@ PHP_FUNCTION(openssl_csr_sign) + X509V3_CTX ctx; + + X509V3_set_ctx(&ctx, cert, new_cert, csr, NULL, 0); +- X509V3_set_conf_lhash(&ctx, req.req_config); +- if (!X509V3_EXT_add_conf(req.req_config, &ctx, req.extensions_section, new_cert)) { ++ X509V3_set_nconf(&ctx, req.req_config); ++ if (!X509V3_EXT_add_nconf(req.req_config, &ctx, req.extensions_section, new_cert)) { + php_openssl_store_errors(); + goto cleanup; + } +@@ -3638,10 +3644,10 @@ PHP_FUNCTION(openssl_csr_new) + X509V3_CTX ext_ctx; + + X509V3_set_ctx(&ext_ctx, NULL, NULL, csr, NULL, 0); +- X509V3_set_conf_lhash(&ext_ctx, req.req_config); ++ X509V3_set_nconf(&ext_ctx, req.req_config); + + /* Add extensions */ +- if (req.request_extensions_section && !X509V3_EXT_REQ_add_conf(req.req_config, ++ if (req.request_extensions_section && !X509V3_EXT_REQ_add_nconf(req.req_config, + &ext_ctx, req.request_extensions_section, csr)) + { + php_openssl_store_errors(); +-- +2.41.0 + +From 95dd07c54542ac48cf7d43392f61b0423b04fe63 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Sun, 12 Sep 2021 20:30:02 +0100 +Subject: [PATCH 18/27] Make OpenSSL tests less dependent on system config + +It fixes dependencies on system config if running tests with OpenSSL 3.0 + +(cherry picked from commit 43f0141d74c1db6e792f3b625ea7f4ae57ff338f) +--- + ext/openssl/tests/bug52093.phpt | 6 +++--- + ext/openssl/tests/bug72165.phpt | 5 +++-- + ext/openssl/tests/bug73711.phpt | 3 +++ + ext/openssl/tests/ecc.phpt | 3 +++ + 4 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/ext/openssl/tests/bug52093.phpt b/ext/openssl/tests/bug52093.phpt +index 63eaceb5ac..162945f914 100644 +--- a/ext/openssl/tests/bug52093.phpt ++++ b/ext/openssl/tests/bug52093.phpt +@@ -14,10 +14,10 @@ $dn = array( + "commonName" => "Henrique do N. Angelo", + "emailAddress" => "hnangelo@php.net" + ); +- ++$options = ['config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf']; + $privkey = openssl_pkey_new(); +-$csr = openssl_csr_new($dn, $privkey); +-$cert = openssl_csr_sign($csr, null, $privkey, 365, [], PHP_INT_MAX); ++$csr = openssl_csr_new($dn, $privkey, $options); ++$cert = openssl_csr_sign($csr, null, $privkey, 365, $options, PHP_INT_MAX); + var_dump(openssl_x509_parse($cert)['serialNumber']); + ?> + --EXPECT-- +diff --git a/ext/openssl/tests/bug72165.phpt b/ext/openssl/tests/bug72165.phpt +index 93b3c3d4a8..7b38827c37 100644 +--- a/ext/openssl/tests/bug72165.phpt ++++ b/ext/openssl/tests/bug72165.phpt +@@ -6,8 +6,9 @@ if (!extension_loaded("openssl")) die("skip"); + ?> + --FILE-- + <?php +-$var0 = array(0 => "hello", 1 => "world"); +-$var2 = openssl_csr_new(array(0),$var0,null,array(0)); ++$var0 = [0 => "hello", 1 => "world"]; ++$options = ['config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf']; ++$var2 = openssl_csr_new([0], $var0, $options, [0]); + ?> + ==DONE== + --EXPECTF-- +diff --git a/ext/openssl/tests/bug73711.phpt b/ext/openssl/tests/bug73711.phpt +index 7beb020a4c..b6ac4871a3 100644 +--- a/ext/openssl/tests/bug73711.phpt ++++ b/ext/openssl/tests/bug73711.phpt +@@ -6,13 +6,16 @@ if (!extension_loaded("openssl")) die("skip openssl not loaded"); + ?> + --FILE-- + <?php ++$config = __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'; + var_dump(openssl_pkey_new([ + "private_key_type" => OPENSSL_KEYTYPE_DSA, + "private_key_bits" => 1024, ++ 'config' => $config, + ])); + var_dump(openssl_pkey_new([ + "private_key_type" => OPENSSL_KEYTYPE_DH, + "private_key_bits" => 512, ++ 'config' => $config, + ])); + echo "DONE"; + ?> +diff --git a/ext/openssl/tests/ecc.phpt b/ext/openssl/tests/ecc.phpt +index 41567e9b32..6c09238003 100644 +--- a/ext/openssl/tests/ecc.phpt ++++ b/ext/openssl/tests/ecc.phpt +@@ -4,9 +4,11 @@ openssl_*() with OPENSSL_KEYTYPE_EC + <?php if (!extension_loaded("openssl") || !defined("OPENSSL_KEYTYPE_EC")) print "skip"; ?> + --FILE-- + <?php ++$config = __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'; + $args = array( + "curve_name" => "secp384r1", + "private_key_type" => OPENSSL_KEYTYPE_EC, ++ "config" => $config, + ); + echo "Testing openssl_pkey_new\n"; + $key1 = openssl_pkey_new($args); +@@ -15,6 +17,7 @@ var_dump($key1); + $argsFailed = array( + "curve_name" => "invalid_cuve_name", + "private_key_type" => OPENSSL_KEYTYPE_EC, ++ "config" => $config, + ); + + $keyFailed = openssl_pkey_new($argsFailed); +-- +2.41.0 + +From 6167fdd70654ff63a6a759cffbbdb5468e5c517a Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Fri, 6 Aug 2021 11:15:18 +0200 +Subject: [PATCH 19/27] Do not special case export of EC keys + +All other private keys are exported in PKCS#8 format, while EC +keys use traditional format. Switch them to use PKCS#8 format as +well. + +As the OpenSSL docs say: + +> PEM_write_bio_PrivateKey_traditional() writes out a private key +> in the "traditional" format with a simple private key marker and +> should only be used for compatibility with legacy programs. + +(cherry picked from commit f2d3e75933fa155a5281c824263780dbc660ecb1) +--- + ext/openssl/openssl.c | 36 ++++--------------- + .../tests/openssl_pkey_export_basic.phpt | 6 +++- + 2 files changed, 11 insertions(+), 31 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 666616e7c5..4af0942209 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -4647,21 +4647,9 @@ PHP_FUNCTION(openssl_pkey_export_to_file) + cipher = NULL; + } + +- switch (EVP_PKEY_base_id(key)) { +-#ifdef HAVE_EVP_PKEY_EC +- case EVP_PKEY_EC: +- pem_write = PEM_write_bio_ECPrivateKey( +- bio_out, EVP_PKEY_get0_EC_KEY(key), cipher, +- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); +- break; +-#endif +- default: +- pem_write = PEM_write_bio_PrivateKey( +- bio_out, key, cipher, +- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); +- break; +- } +- ++ pem_write = PEM_write_bio_PrivateKey( ++ bio_out, key, cipher, ++ (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); + if (pem_write) { + /* Success! + * If returning the output as a string, do so now */ +@@ -4724,21 +4712,9 @@ PHP_FUNCTION(openssl_pkey_export) + cipher = NULL; + } + +- switch (EVP_PKEY_base_id(key)) { +-#ifdef HAVE_EVP_PKEY_EC +- case EVP_PKEY_EC: +- pem_write = PEM_write_bio_ECPrivateKey( +- bio_out, EVP_PKEY_get0_EC_KEY(key), cipher, +- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); +- break; +-#endif +- default: +- pem_write = PEM_write_bio_PrivateKey( +- bio_out, key, cipher, +- (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); +- break; +- } +- ++ pem_write = PEM_write_bio_PrivateKey( ++ bio_out, key, cipher, ++ (unsigned char *)passphrase, (int)passphrase_len, NULL, NULL); + if (pem_write) { + /* Success! + * If returning the output as a string, do so now */ +diff --git a/ext/openssl/tests/openssl_pkey_export_basic.phpt b/ext/openssl/tests/openssl_pkey_export_basic.phpt +index d71f8da9a3..47a82d7873 100644 +--- a/ext/openssl/tests/openssl_pkey_export_basic.phpt ++++ b/ext/openssl/tests/openssl_pkey_export_basic.phpt +@@ -46,7 +46,11 @@ var_dump(is_resource($key)); + --EXPECTF-- + resource(%d) of type (OpenSSL key) + bool(true) +------BEGIN EC PRIVATE KEY-----%a-----END EC PRIVATE KEY----- ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs+Sqh7IzteDBiS5K ++PfTvuWuyt9YkrkuoyiW/6bag6NmhRANCAAQ+riFshYe8HnWt1avx6OuNajipU1ZW ++6BgW0+D/EtDDSYeQg9ngO8qyo5M6cyh7ORtKZVUy7DP1+W+eocaZC+a6 ++-----END PRIVATE KEY----- + bool(true) + bool(true) + resource(%d) of type (OpenSSL key) +-- +2.41.0 + +From 94c952911ba9b53470056f0e679c842311e601e5 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Thu, 5 Aug 2021 10:29:50 +0200 +Subject: [PATCH 20/27] Use EVP_PKEY APIs for key generation + +Use high level API instead of deprecated low level API. + +(cherry picked from commit 13313d9b1b9fa014fe6f92c496477e28f4f11772) +--- + ext/openssl/openssl.c | 210 ++++++++++++++++++++---------------------- + 1 file changed, 100 insertions(+), 110 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 4af0942209..588aa3902f 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -3995,140 +3995,130 @@ static EVP_PKEY * php_openssl_evp_from_zval( + } + /* }}} */ + ++static int php_openssl_get_evp_pkey_type(int key_type) { ++ switch (key_type) { ++ case OPENSSL_KEYTYPE_RSA: ++ return EVP_PKEY_RSA; ++#if !defined(NO_DSA) ++ case OPENSSL_KEYTYPE_DSA: ++ return EVP_PKEY_DSA; ++#endif ++#if !defined(NO_DH) ++ case OPENSSL_KEYTYPE_DH: ++ return EVP_PKEY_DH; ++#endif ++#ifdef HAVE_EVP_PKEY_EC ++ case OPENSSL_KEYTYPE_EC: ++ return EVP_PKEY_EC; ++#endif ++ default: ++ return -1; ++ } ++} ++ + /* {{{ php_openssl_generate_private_key */ + static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) + { +- char * randfile = NULL; +- int egdsocket, seeded; +- EVP_PKEY * return_val = NULL; +- + if (req->priv_key_bits < MIN_KEY_LENGTH) { + php_error_docref(NULL, E_WARNING, "private key length is too short; it needs to be at least %d bits, not %d", + MIN_KEY_LENGTH, req->priv_key_bits); + return NULL; + } + +- randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE"); ++ int type = php_openssl_get_evp_pkey_type(req->priv_key_type); ++ if (type < 0) { ++ php_error_docref(NULL, E_WARNING, "Unsupported private key type"); ++ return NULL; ++ } ++ ++ int egdsocket, seeded; ++ char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE"); + php_openssl_load_rand_file(randfile, &egdsocket, &seeded); ++ PHP_OPENSSL_RAND_ADD_TIME(); + +- if ((req->priv_key = EVP_PKEY_new()) != NULL) { +- switch(req->priv_key_type) { +- case OPENSSL_KEYTYPE_RSA: +- { +- RSA* rsaparam; +-#if OPENSSL_VERSION_NUMBER < 0x10002000L +- /* OpenSSL 1.0.2 deprecates RSA_generate_key */ +- PHP_OPENSSL_RAND_ADD_TIME(); +- rsaparam = (RSA*)RSA_generate_key(req->priv_key_bits, RSA_F4, NULL, NULL); +-#else +- { +- BIGNUM *bne = (BIGNUM *)BN_new(); +- if (BN_set_word(bne, RSA_F4) != 1) { +- BN_free(bne); +- php_error_docref(NULL, E_WARNING, "failed setting exponent"); +- return NULL; +- } +- rsaparam = RSA_new(); +- PHP_OPENSSL_RAND_ADD_TIME(); +- if (rsaparam == NULL || !RSA_generate_key_ex(rsaparam, req->priv_key_bits, bne, NULL)) { +- php_openssl_store_errors(); +- RSA_free(rsaparam); +- rsaparam = NULL; +- } +- BN_free(bne); +- } +-#endif +- if (rsaparam && EVP_PKEY_assign_RSA(req->priv_key, rsaparam)) { +- return_val = req->priv_key; +- } else { +- php_openssl_store_errors(); +- } +- } +- break; ++ EVP_PKEY *key = NULL; ++ EVP_PKEY *params = NULL; ++ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL); ++ if (!ctx) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ ++ if (type != EVP_PKEY_RSA) { ++ if (EVP_PKEY_paramgen_init(ctx) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ ++ switch (type) { + #if !defined(NO_DSA) +- case OPENSSL_KEYTYPE_DSA: +- PHP_OPENSSL_RAND_ADD_TIME(); +- { +- DSA *dsaparam = DSA_new(); +- if (dsaparam && DSA_generate_parameters_ex(dsaparam, req->priv_key_bits, NULL, 0, NULL, NULL, NULL)) { +- DSA_set_method(dsaparam, DSA_get_default_method()); +- if (DSA_generate_key(dsaparam)) { +- if (EVP_PKEY_assign_DSA(req->priv_key, dsaparam)) { +- return_val = req->priv_key; +- } else { +- php_openssl_store_errors(); +- } +- } else { +- php_openssl_store_errors(); +- DSA_free(dsaparam); +- } +- } else { +- php_openssl_store_errors(); +- } +- } +- break; ++ case EVP_PKEY_DSA: ++ if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, req->priv_key_bits) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ break; + #endif + #if !defined(NO_DH) +- case OPENSSL_KEYTYPE_DH: +- PHP_OPENSSL_RAND_ADD_TIME(); +- { +- int codes = 0; +- DH *dhparam = DH_new(); +- if (dhparam && DH_generate_parameters_ex(dhparam, req->priv_key_bits, 2, NULL)) { +- DH_set_method(dhparam, DH_get_default_method()); +- if (DH_check(dhparam, &codes) && codes == 0 && DH_generate_key(dhparam)) { +- if (EVP_PKEY_assign_DH(req->priv_key, dhparam)) { +- return_val = req->priv_key; +- } else { +- php_openssl_store_errors(); +- } +- } else { +- php_openssl_store_errors(); +- DH_free(dhparam); +- } +- } else { +- php_openssl_store_errors(); +- } +- } +- break; ++ case EVP_PKEY_DH: ++ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, req->priv_key_bits) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ break; + #endif + #ifdef HAVE_EVP_PKEY_EC +- case OPENSSL_KEYTYPE_EC: +- { +- EC_KEY *eckey; +- if (req->curve_name == NID_undef) { +- php_error_docref(NULL, E_WARNING, "Missing configuration value: 'curve_name' not set"); +- return NULL; +- } +- eckey = EC_KEY_new_by_curve_name(req->curve_name); +- if (eckey) { +- EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); +- if (EC_KEY_generate_key(eckey) && +- EVP_PKEY_assign_EC_KEY(req->priv_key, eckey)) { +- return_val = req->priv_key; +- } else { +- EC_KEY_free(eckey); +- } +- } +- } +- break; ++ case EVP_PKEY_EC: ++ if (req->curve_name == NID_undef) { ++ php_error_docref(NULL, E_WARNING, "Missing configuration value: \"curve_name\" not set"); ++ goto cleanup; ++ } ++ ++ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, req->curve_name) <= 0 || ++ EVP_PKEY_CTX_set_ec_param_enc(ctx, OPENSSL_EC_NAMED_CURVE) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ break; + #endif +- default: +- php_error_docref(NULL, E_WARNING, "Unsupported private key type"); ++ EMPTY_SWITCH_DEFAULT_CASE() + } +- } else { ++ ++ if (EVP_PKEY_paramgen(ctx, ¶ms) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ ++ EVP_PKEY_CTX_free(ctx); ++ ctx = EVP_PKEY_CTX_new(params, NULL); ++ if (!ctx) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } ++ } ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0) { + php_openssl_store_errors(); ++ goto cleanup; + } + +- php_openssl_write_rand_file(randfile, egdsocket, seeded); ++ if (type == EVP_PKEY_RSA && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, req->priv_key_bits) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; ++ } + +- if (return_val == NULL) { +- EVP_PKEY_free(req->priv_key); +- req->priv_key = NULL; +- return NULL; ++ if (EVP_PKEY_keygen(ctx, &key) <= 0) { ++ php_openssl_store_errors(); ++ goto cleanup; + } + +- return return_val; ++ req->priv_key = key; ++ ++cleanup: ++ php_openssl_write_rand_file(randfile, egdsocket, seeded); ++ EVP_PKEY_free(params); ++ EVP_PKEY_CTX_free(ctx); ++ return key; + } + /* }}} */ + +-- +2.41.0 + +From 3e896d255c644a0d1c27a6c19e074b43bfc4c5ac Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Mon, 9 Aug 2021 10:26:12 +0200 +Subject: [PATCH 21/27] Extract EC key initialization + +(cherry picked from commit 14d7c7e9aee5ab55a92ddc626b7b81c130ea7618) +--- + ext/openssl/openssl.c | 239 ++++++++++++++++++++++-------------------- + 1 file changed, 125 insertions(+), 114 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 588aa3902f..5671311508 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -4372,8 +4372,126 @@ static zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data) + } + /* }}} */ + +-/* {{{ proto resource openssl_pkey_new([array configargs]) +- Generates a new private key */ ++#ifdef HAVE_EVP_PKEY_EC ++static int php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, int *is_private) { ++ EC_GROUP *group = NULL; ++ EC_POINT *pnt = NULL; ++ BIGNUM *d = NULL; ++ zval *bn; ++ zval *x; ++ zval *y; ++ ++ if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL && ++ Z_TYPE_P(bn) == IS_STRING) { ++ int nid = OBJ_sn2nid(Z_STRVAL_P(bn)); ++ if (nid != NID_undef) { ++ group = EC_GROUP_new_by_curve_name(nid); ++ if (!group) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); ++ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); ++ if (!EC_KEY_set_group(eckey, group)) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ } ++ } ++ ++ if (group == NULL) { ++ php_error_docref(NULL, E_WARNING, "Unknown curve name"); ++ goto clean_exit; ++ } ++ ++ // The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y' ++ *is_private = 0; ++ if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL && ++ Z_TYPE_P(bn) == IS_STRING) { ++ *is_private = 1; ++ d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL); ++ if (!EC_KEY_set_private_key(eckey, d)) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ // Calculate the public key by multiplying the Point Q with the public key ++ // P = d * Q ++ pnt = EC_POINT_new(group); ++ if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ ++ BN_free(d); ++ } else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL && ++ Z_TYPE_P(x) == IS_STRING && ++ (y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL && ++ Z_TYPE_P(y) == IS_STRING) { ++ pnt = EC_POINT_new(group); ++ if (pnt == NULL) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ if (!EC_POINT_set_affine_coordinates_GFp( ++ group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL), ++ BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ } ++ ++ if (pnt != NULL) { ++ if (!EC_KEY_set_public_key(eckey, pnt)) { ++ php_openssl_store_errors(); ++ goto clean_exit; ++ } ++ EC_POINT_free(pnt); ++ pnt = NULL; ++ } ++ ++ if (!EC_KEY_check_key(eckey)) { ++ PHP_OPENSSL_RAND_ADD_TIME(); ++ EC_KEY_generate_key(eckey); ++ php_openssl_store_errors(); ++ } ++ if (EC_KEY_check_key(eckey)) { ++ return 1; ++ } else { ++ php_openssl_store_errors(); ++ } ++ ++clean_exit: ++ BN_free(d); ++ EC_POINT_free(pnt); ++ EC_GROUP_free(group); ++ return 0; ++} ++ ++static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, int *is_private) { ++ EVP_PKEY *pkey = EVP_PKEY_new(); ++ if (!pkey) { ++ php_openssl_store_errors(); ++ return NULL; ++ } ++ ++ EC_KEY *ec = EC_KEY_new(); ++ if (!ec) { ++ EVP_PKEY_free(pkey); ++ return NULL; ++ } ++ ++ if (!php_openssl_pkey_init_legacy_ec(ec, data, is_private) ++ || !EVP_PKEY_assign_EC_KEY(pkey, ec)) { ++ php_openssl_store_errors(); ++ EVP_PKEY_free(pkey); ++ EC_KEY_free(ec); ++ return NULL; ++ } ++ ++ return pkey; ++} ++#endif ++ + PHP_FUNCTION(openssl_pkey_new) + { + struct php_x509_request req; +@@ -4454,119 +4572,12 @@ PHP_FUNCTION(openssl_pkey_new) + #ifdef HAVE_EVP_PKEY_EC + } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ec", sizeof("ec") - 1)) != NULL && + Z_TYPE_P(data) == IS_ARRAY) { +- EC_KEY *eckey = NULL; +- EC_GROUP *group = NULL; +- EC_POINT *pnt = NULL; +- BIGNUM *d = NULL; +- pkey = EVP_PKEY_new(); +- if (pkey) { +- eckey = EC_KEY_new(); +- if (eckey) { +- EC_GROUP *group = NULL; +- zval *bn; +- zval *x; +- zval *y; +- +- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL && +- Z_TYPE_P(bn) == IS_STRING) { +- int nid = OBJ_sn2nid(Z_STRVAL_P(bn)); +- if (nid != NID_undef) { +- group = EC_GROUP_new_by_curve_name(nid); +- if (!group) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); +- EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); +- if (!EC_KEY_set_group(eckey, group)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- } +- } +- +- if (group == NULL) { +- php_error_docref(NULL, E_WARNING, "Unknown curve_name"); +- goto clean_exit; +- } +- +- // The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y' +- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL && +- Z_TYPE_P(bn) == IS_STRING) { +- d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL); +- if (!EC_KEY_set_private_key(eckey, d)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- // Calculate the public key by multiplying the Point Q with the public key +- // P = d * Q +- pnt = EC_POINT_new(group); +- if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- +- BN_free(d); +- } else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL && +- Z_TYPE_P(x) == IS_STRING && +- (y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL && +- Z_TYPE_P(y) == IS_STRING) { +- pnt = EC_POINT_new(group); +- if (pnt == NULL) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- if (!EC_POINT_set_affine_coordinates_GFp( +- group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL), +- BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- } +- +- if (pnt != NULL) { +- if (!EC_KEY_set_public_key(eckey, pnt)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- EC_POINT_free(pnt); +- pnt = NULL; +- } +- +- if (!EC_KEY_check_key(eckey)) { +- PHP_OPENSSL_RAND_ADD_TIME(); +- EC_KEY_generate_key(eckey); +- php_openssl_store_errors(); +- } +- if (EC_KEY_check_key(eckey) && EVP_PKEY_assign_EC_KEY(pkey, eckey)) { +- EC_GROUP_free(group); +- RETURN_RES(zend_register_resource(pkey, le_key)); +- } else { +- php_openssl_store_errors(); +- } +- } else { +- php_openssl_store_errors(); +- } +- } else { +- php_openssl_store_errors(); +- } +-clean_exit: +- if (d != NULL) { +- BN_free(d); +- } +- if (pnt != NULL) { +- EC_POINT_free(pnt); +- } +- if (group != NULL) { +- EC_GROUP_free(group); +- } +- if (eckey != NULL) { +- EC_KEY_free(eckey); +- } +- if (pkey != NULL) { +- EVP_PKEY_free(pkey); ++ int is_private; ++ pkey = php_openssl_pkey_init_ec(data, &is_private); ++ if (!pkey) { ++ RETURN_FALSE; + } +- RETURN_FALSE; ++ RETURN_RES(zend_register_resource(pkey, le_key)); + #endif + } + } +-- +2.41.0 + +From 9ac7bdc3d7eb104d7d95e2b1aa4e2b631f45051b Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Mon, 9 Aug 2021 12:01:35 +0200 +Subject: [PATCH 22/27] Test calculation of EC public key from private key + +(cherry picked from commit 246698671f941b2034518ab04f35009b2da77bb1) +--- + ext/openssl/tests/ecc.phpt | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ext/openssl/tests/ecc.phpt b/ext/openssl/tests/ecc.phpt +index 6c09238003..ecc34a3330 100644 +--- a/ext/openssl/tests/ecc.phpt ++++ b/ext/openssl/tests/ecc.phpt +@@ -36,6 +36,16 @@ $d2 = openssl_pkey_get_details($key2); + // Compare array + var_dump($d1 === $d2); + ++// Check that the public key info is computed from the private key if it is missing. ++$d1_priv = $d1; ++unset($d1_priv["ec"]["x"]); ++unset($d1_priv["ec"]["y"]); ++ ++$key3 = openssl_pkey_new($d1_priv); ++var_dump($key3); ++$d3 = openssl_pkey_get_details($key3); ++var_dump($d1 === $d3); ++ + $dn = array( + "countryName" => "BR", + "stateOrProvinceName" => "Rio Grande do Sul", +@@ -94,6 +104,8 @@ string(9) "secp384r1" + bool(true) + resource(%d) of type (OpenSSL key) + bool(true) ++resource(%d) of type (OpenSSL key) ++bool(true) + Testing openssl_csr_new with key generation + NULL + resource(%d) of type (OpenSSL key) +-- +2.41.0 + +From d8ffb2117e6b986cb4a5b8e5c0cf5c74af8a32fc Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Mon, 9 Aug 2021 11:12:20 +0200 +Subject: [PATCH 23/27] Use param API for creating EC keys + +Rather than the deprecated low level APIs. + +(cherry picked from commit f9e701cde813fad4e1f647e63750c0b9bdeadb4e) +--- + ext/openssl/openssl.c | 101 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 101 insertions(+) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 5671311508..5a76057c5f 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -57,6 +57,11 @@ + #include <openssl/rand.h> + #include <openssl/ssl.h> + #include <openssl/pkcs12.h> ++#include <openssl/cms.h> ++#if PHP_OPENSSL_API_VERSION >= 0x30000 ++#include <openssl/core_names.h> ++#include <openssl/param_build.h> ++#endif + + /* Common */ + #include <time.h> +@@ -4373,6 +4378,7 @@ static zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data) + /* }}} */ + + #ifdef HAVE_EVP_PKEY_EC ++#if PHP_OPENSSL_API_VERSION < 0x30000 + static int php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, int *is_private) { + EC_GROUP *group = NULL; + EC_POINT *pnt = NULL; +@@ -4450,6 +4456,7 @@ static int php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, int *is_pr + } + + if (!EC_KEY_check_key(eckey)) { ++ *is_private = true; + PHP_OPENSSL_RAND_ADD_TIME(); + EC_KEY_generate_key(eckey); + php_openssl_store_errors(); +@@ -4466,8 +4473,101 @@ clean_exit: + EC_GROUP_free(group); + return 0; + } ++#endif + + static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, int *is_private) { ++#if PHP_OPENSSL_API_VERSION >= 0x30000 ++ BIGNUM *d = NULL, *x = NULL, *y = NULL; ++ EC_GROUP *group = NULL; ++ EC_POINT *pnt = NULL; ++ char *pnt_oct = NULL; ++ EVP_PKEY *param_key = NULL, *pkey = NULL; ++ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ OSSL_PARAM *params = NULL; ++ OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); ++ zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1); ++ ++ OPENSSL_PKEY_SET_BN(data, d); ++ OPENSSL_PKEY_SET_BN(data, x); ++ OPENSSL_PKEY_SET_BN(data, y); ++ ++ if (!ctx || !bld || !curve_name_zv || Z_TYPE_P(curve_name_zv) != IS_STRING) { ++ goto cleanup; ++ } ++ ++ int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv)); ++ group = EC_GROUP_new_by_curve_name(nid); ++ if (!group) { ++ php_error_docref(NULL, E_WARNING, "Unknown curve name"); ++ goto cleanup; ++ } ++ ++ OSSL_PARAM_BLD_push_utf8_string( ++ bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv)); ++ ++ if (d) { ++ OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d); ++ ++ pnt = EC_POINT_new(group); ++ if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) { ++ goto cleanup; ++ } ++ } else if (x && y) { ++ /* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */ ++ pnt = EC_POINT_new(group); ++ if (!pnt || !EC_POINT_set_affine_coordinates(group, pnt, x, y, NULL)) { ++ goto cleanup; ++ } ++ } ++ ++ if (pnt) { ++ size_t pnt_oct_len = ++ EC_POINT_point2buf(group, pnt, POINT_CONVERSION_COMPRESSED, &pnt_oct, NULL); ++ if (!pnt_oct_len) { ++ goto cleanup; ++ } ++ ++ OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pnt_oct, pnt_oct_len); ++ } ++ ++ params = OSSL_PARAM_BLD_to_param(bld); ++ if (!params) { ++ goto cleanup; ++ } ++ ++ if (EVP_PKEY_fromdata_init(ctx) <= 0 || ++ EVP_PKEY_fromdata(ctx, ¶m_key, EVP_PKEY_KEYPAIR, params) <= 0) { ++ goto cleanup; ++ } ++ ++ EVP_PKEY_CTX_free(ctx); ++ ctx = EVP_PKEY_CTX_new(param_key, NULL); ++ if (EVP_PKEY_check(ctx)) { ++ *is_private = d != NULL; ++ EVP_PKEY_up_ref(param_key); ++ pkey = param_key; ++ } else { ++ *is_private = 1; ++ PHP_OPENSSL_RAND_ADD_TIME(); ++ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { ++ goto cleanup; ++ } ++ } ++ ++cleanup: ++ php_openssl_store_errors(); ++ EVP_PKEY_free(param_key); ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(bld); ++ EC_POINT_free(pnt); ++ EC_GROUP_free(group); ++ OPENSSL_free(pnt_oct); ++ BN_free(d); ++ BN_free(x); ++ BN_free(y); ++ return pkey; ++#else + EVP_PKEY *pkey = EVP_PKEY_new(); + if (!pkey) { + php_openssl_store_errors(); +@@ -4489,6 +4589,7 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, int *is_private) { + } + + return pkey; ++#endif + } + #endif + +-- +2.41.0 + +From c1047e5c4bf6919ab9600318721d4fa6cbebb40b Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Mon, 9 Aug 2021 14:19:33 +0200 +Subject: [PATCH 24/27] Extract public key portion via PEM roundtrip + +The workaround with cloning the X509_REQ no longer works in +OpenSSL 3. Instead extract the public key portion by round +tripping through PEM. + +(cherry picked from commit 26a51e8d7a6026f6bd69813d044785d154a296a3) +--- + ext/openssl/openssl.c | 41 +++++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 22 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 5a76057c5f..00ab6dc73a 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -3727,6 +3727,20 @@ PHP_FUNCTION(openssl_csr_get_subject) + } + /* }}} */ + ++static EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key) ++{ ++ /* Extract public key portion by round-tripping through PEM. */ ++ BIO *bio = BIO_new(BIO_s_mem()); ++ if (!bio || !PEM_write_bio_PUBKEY(bio, priv_key)) { ++ BIO_free(bio); ++ return NULL; ++ } ++ ++ EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ return pub_key; ++} ++ + /* {{{ proto mixed openssl_csr_get_public_key(mixed csr) + Returns the subject of a CERT or FALSE on error */ + PHP_FUNCTION(openssl_csr_get_public_key) +@@ -3734,42 +3748,25 @@ PHP_FUNCTION(openssl_csr_get_public_key) + zval * zcsr; + zend_bool use_shortnames = 1; + zend_resource *csr_resource; +- +- X509_REQ *orig_csr, *csr; ++ X509_REQ *csr; + EVP_PKEY *tpubkey; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &zcsr, &use_shortnames) == FAILURE) { + return; + } + +- orig_csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource); ++ csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource); + +- if (orig_csr == NULL) { ++ if (csr == NULL) { + RETURN_FALSE; + } + +-#if PHP_OPENSSL_API_VERSION >= 0x10100 +- /* Due to changes in OpenSSL 1.1 related to locking when decoding CSR, +- * the pub key is not changed after assigning. It means if we pass +- * a private key, it will be returned including the private part. +- * If we duplicate it, then we get just the public part which is +- * the same behavior as for OpenSSL 1.0 */ +- csr = X509_REQ_dup(orig_csr); +-#else +- csr = orig_csr; +-#endif +- + /* Retrieve the public key from the CSR */ +- tpubkey = X509_REQ_get_pubkey(csr); +- +- if (csr != orig_csr) { +- /* We need to free the duplicated CSR */ +- X509_REQ_free(csr); +- } ++ tpubkey = php_openssl_extract_public_key(X509_REQ_get_pubkey(csr)); + + if (!csr_resource) { + /* We also need to free the original CSR if it was freshly created */ +- X509_REQ_free(orig_csr); ++ X509_REQ_free(csr); + } + + if (tpubkey == NULL) { +-- +2.41.0 + +From ee274b8bb13e8f9a3df79550be2ea3e4538c6326 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita.ppv@gmail.com> +Date: Tue, 10 Aug 2021 12:17:17 +0200 +Subject: [PATCH 25/27] Switch dh_param handling to EVP_PKEY API + +(cherry picked from commit ef787bae242fdd2e72625bbce6ab4ca466b1ef59) +--- + ext/openssl/xp_ssl.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c +index 9710e44a07..f130bdee66 100644 +--- a/ext/openssl/xp_ssl.c ++++ b/ext/openssl/xp_ssl.c +@@ -1200,11 +1200,7 @@ static RSA *php_openssl_tmp_rsa_cb(SSL *s, int is_export, int keylength) + + static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* {{{ */ + { +- DH *dh; +- BIO* bio; +- zval *zdhpath; +- +- zdhpath = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param"); ++ zval *zdhpath = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "dh_param"); + if (zdhpath == NULL) { + #if 0 + /* Coming in OpenSSL 1.1 ... eventually we'll want to enable this +@@ -1219,14 +1215,29 @@ static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* + return FAILURE; + } + +- bio = BIO_new_file(Z_STRVAL_P(zdhpath), PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); ++ BIO *bio = BIO_new_file(Z_STRVAL_P(zdhpath), PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); + + if (bio == NULL) { + php_error_docref(NULL, E_WARNING, "invalid dh_param"); + return FAILURE; + } + +- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); ++#if PHP_OPENSSL_API_VERSION >= 0x30000 ++ EVP_PKEY *pkey = PEM_read_bio_Parameters(bio, NULL); ++ BIO_free(bio); ++ ++ if (pkey == NULL) { ++ php_error_docref(NULL, E_WARNING, "Failed reading DH params"); ++ return FAILURE; ++ } ++ ++ if (SSL_CTX_set0_tmp_dh_pkey(ctx, pkey) < 0) { ++ php_error_docref(NULL, E_WARNING, "Failed assigning DH params"); ++ EVP_PKEY_free(pkey); ++ return FAILURE; ++ } ++#else ++ DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (dh == NULL) { +@@ -1241,6 +1252,7 @@ static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /* + } + + DH_free(dh); ++#endif + + return SUCCESS; + } +-- +2.41.0 + +From 6bb3f5d83ea5a108018b22b5e5b3b7dff77a66de Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 18 Nov 2021 15:08:19 +0100 +Subject: [PATCH 26/27] ignore remaining warnings + +--- + ext/openssl/openssl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 00ab6dc73a..b136729cb5 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -26,6 +26,7 @@ + #endif + + # pragma GCC diagnostic ignored "-Wdeprecated-declarations" ++# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" + + #include "php.h" + #include "php_ini.h" +@@ -4477,7 +4478,7 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, int *is_private) { + BIGNUM *d = NULL, *x = NULL, *y = NULL; + EC_GROUP *group = NULL; + EC_POINT *pnt = NULL; +- char *pnt_oct = NULL; ++ unsigned char *pnt_oct = NULL; + EVP_PKEY *param_key = NULL, *pkey = NULL; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + OSSL_PARAM *params = NULL; +-- +2.41.0 + +From 5019534853051a3cb3cce9811e98e583e568e112 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 26 Jun 2023 07:59:18 +0200 +Subject: [PATCH 27/27] don't use true + +--- + ext/openssl/openssl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index b136729cb5..d0fd976376 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -4454,7 +4454,7 @@ static int php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, int *is_pr + } + + if (!EC_KEY_check_key(eckey)) { +- *is_private = true; ++ *is_private = 1; + PHP_OPENSSL_RAND_ADD_TIME(); + EC_KEY_generate_key(eckey); + php_openssl_store_errors(); +-- +2.41.0 + diff --git a/php-7.4.26-snmp.patch b/php-7.4.26-snmp.patch new file mode 100644 index 0000000..e7ee193 --- /dev/null +++ b/php-7.4.26-snmp.patch @@ -0,0 +1,38 @@ +Backported from 8.0 for 7.4 by Remi + + +From f9fd3595ecb36c8dc6add0515782a18f15216d77 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 27 May 2021 14:20:07 +0200 +Subject: [PATCH] Fix snmp build without DES + +--- + ext/snmp/snmp.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c +index 35d19c8738828..d31995827880d 100644 +--- a/ext/snmp/snmp.c ++++ b/ext/snmp/snmp.c +@@ -1225,15 +1225,19 @@ static int netsnmp_session_set_auth_prot + Set the security protocol in the snmpv3 session */ + static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot) + { ++#ifndef NETSNMP_DISABLE_DES + if (!strcasecmp(prot, "DES")) { + s->securityPrivProto = usmDESPrivProtocol; + s->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; ++ } else ++#endif + #ifdef HAVE_AES +- } else if (!strcasecmp(prot, "AES128") || !strcasecmp(prot, "AES")) { ++ if (!strcasecmp(prot, "AES128") || !strcasecmp(prot, "AES")) { + s->securityPrivProto = usmAESPrivProtocol; + s->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; ++ } else + #endif +- } else { ++ { + php_error_docref(NULL, E_WARNING, "Unknown security protocol '%s'", prot); + return (-1); + } diff --git a/php-7.4.8-phpinfo.patch b/php-7.4.8-phpinfo.patch new file mode 100644 index 0000000..9b7175e --- /dev/null +++ b/php-7.4.8-phpinfo.patch @@ -0,0 +1,76 @@ + +Drop "Configure Command" from phpinfo as it doesn't +provide any useful information. +The available extensions are not related to this command. + +diff -up a/ext/standard/info.c.phpinfo v/ext/standard/info.c +--- a/ext/standard/info.c.phpinfo 2015-08-18 23:39:24.000000000 +0200 ++++ b/ext/standard/info.c 2015-08-22 07:56:18.344761928 +0200 +@@ -809,9 +809,6 @@ PHPAPI void php_print_info(int flag) + #ifdef ARCHITECTURE + php_info_print_table_row(2, "Architecture", ARCHITECTURE); + #endif +-#ifdef CONFIGURE_COMMAND +- php_info_print_table_row(2, "Configure Command", CONFIGURE_COMMAND ); +-#endif + + if (sapi_module.pretty_name) { + php_info_print_table_row(2, "Server API", sapi_module.pretty_name ); +diff -up a/ext/standard/tests/general_functions/phpinfo.phpt.phpinfo b/ext/standard/tests/general_functions/phpinfo.phpt +--- a/ext/standard/tests/general_functions/phpinfo.phpt.phpinfo 2015-08-18 23:39:22.000000000 +0200 ++++ b/ext/standard/tests/general_functions/phpinfo.phpt 2015-08-22 07:56:18.344761928 +0200 +@@ -20,7 +20,6 @@ PHP Version => %s + + System => %s + Build Date => %s%a +-Configure Command => %s + Server API => Command Line Interface + Virtual Directory Support => %s + Configuration File (php.ini) Path => %s + + +Backported from 8.0: + +From ad0d2e438fddc089917e71e5d8909d145db9da8a Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Fri, 3 Jul 2020 10:08:09 +0200 +Subject: [PATCH] display info about system used to build and its provider + +--- + configure.ac | 5 +++++ + ext/standard/info.c | 6 ++++++ + 2 files changed, 11 insertions(+) + +diff --git a/configure.ac b/configure.ac +index d9e6329314a3..77f12a55569a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1328,6 +1328,11 @@ PHP_UNAME=${PHP_UNAME:-$UNAME} + AC_DEFINE_UNQUOTED(PHP_UNAME,"$PHP_UNAME",[uname -a output]) + PHP_OS=`uname | xargs` + AC_DEFINE_UNQUOTED(PHP_OS,"$PHP_OS",[uname output]) ++PHP_BUILD_SYSTEM=${PHP_BUILD_SYSTEM:-$PHP_UNAME} ++AC_DEFINE_UNQUOTED(PHP_BUILD_SYSTEM,"$PHP_BUILD_SYSTEM",[builder uname output]) ++if test -n "${PHP_BUILD_PROVIDER}"; then ++ AC_DEFINE_UNQUOTED(PHP_BUILD_PROVIDER,"$PHP_BUILD_PROVIDER",[build provider]) ++fi + + PHP_SUBST_OLD(PHP_INSTALLED_SAPIS) + +diff --git a/ext/standard/info.c b/ext/standard/info.c +index 262e95ae2731..f652efd23657 100644 +--- a/ext/standard/info.c ++++ b/ext/standard/info.c +@@ -803,6 +803,12 @@ PHPAPI ZEND_COLD void php_print_info(int flag) + php_info_print_table_start(); + php_info_print_table_row(2, "System", ZSTR_VAL(php_uname)); + php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__); ++#ifdef PHP_BUILD_SYSTEM ++ php_info_print_table_row(2, "Build System", PHP_BUILD_SYSTEM); ++#endif ++#ifdef PHP_BUILD_PROVIDER ++ php_info_print_table_row(2, "Build Provider", PHP_BUILD_PROVIDER); ++#endif + #ifdef COMPILER + php_info_print_table_row(2, "Compiler", COMPILER); + #endif diff --git a/php-bug81740.patch b/php-bug81740.patch new file mode 100644 index 0000000..4826efc --- /dev/null +++ b/php-bug81740.patch @@ -0,0 +1,84 @@ +From 7cb160efe19d3dfb8b92629805733ea186b55050 Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" <cmbecker69@gmx.de> +Date: Mon, 31 Oct 2022 17:20:23 +0100 +Subject: [PATCH 1/2] Fix #81740: PDO::quote() may return unquoted string + +`sqlite3_snprintf()` expects its first parameter to be `int`; we need +to avoid overflow. + +(cherry picked from commit 921b6813da3237a83e908998483f46ae3d8bacba) +--- + ext/pdo_sqlite/sqlite_driver.c | 3 +++ + ext/pdo_sqlite/tests/bug81740.phpt | 17 +++++++++++++++++ + 2 files changed, 20 insertions(+) + create mode 100644 ext/pdo_sqlite/tests/bug81740.phpt + +diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c +index 0595bd09feb..54f9d05e1e2 100644 +--- a/ext/pdo_sqlite/sqlite_driver.c ++++ b/ext/pdo_sqlite/sqlite_driver.c +@@ -233,6 +233,9 @@ static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t + /* NB: doesn't handle binary strings... use prepared stmts for that */ + static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype ) + { ++ if (unquotedlen > (INT_MAX - 3) / 2) { ++ return 0; ++ } + *quoted = safe_emalloc(2, unquotedlen, 3); + sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted); + *quotedlen = strlen(*quoted); +diff --git a/ext/pdo_sqlite/tests/bug81740.phpt b/ext/pdo_sqlite/tests/bug81740.phpt +new file mode 100644 +index 00000000000..99fb07c3048 +--- /dev/null ++++ b/ext/pdo_sqlite/tests/bug81740.phpt +@@ -0,0 +1,17 @@ ++--TEST-- ++Bug #81740 (PDO::quote() may return unquoted string) ++--SKIPIF-- ++<?php ++if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ++if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); ++?> ++--INI-- ++memory_limit=-1 ++--FILE-- ++<?php ++$pdo = new PDO("sqlite::memory:"); ++$string = str_repeat("a", 0x80000000); ++var_dump($pdo->quote($string)); ++?> ++--EXPECT-- ++bool(false) +-- +2.38.1 + +From 7328f3a0344806b846bd05657bdce96e47810bf0 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 19 Dec 2022 09:24:02 +0100 +Subject: [PATCH 2/2] NEWS + +--- + NEWS | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/NEWS b/NEWS +index 8a8c0c9285d..03e8c839c77 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,5 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ++ ++Backported from 8.0.27 ++ ++- PDO/SQLite: ++ . Fixed bug #81740 (PDO::quote() may return unquoted string). ++ (CVE-2022-31631) (cmb) ++ + 03 Nov 2022, PHP 7.4.33 + + - GD: +-- +2.38.1 + diff --git a/php-bug81744.patch b/php-bug81744.patch new file mode 100644 index 0000000..62296ce --- /dev/null +++ b/php-bug81744.patch @@ -0,0 +1,188 @@ +From 7437aaae38cf4b3357e7580f9e22fd4a403b6c23 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 21:15:24 +0100 +Subject: [PATCH 1/7] crypt: Fix validation of malformed BCrypt hashes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PHP’s implementation of crypt_blowfish differs from the upstream Openwall +version by adding a “PHP Hack”, which allows one to cut short the BCrypt salt +by including a `$` character within the characters that represent the salt. + +Hashes that are affected by the “PHP Hack” may erroneously validate any +password as valid when used with `password_verify` and when comparing the +return value of `crypt()` against the input. + +The PHP Hack exists since the first version of PHP’s own crypt_blowfish +implementation that was added in 1e820eca02dcf322b41fd2fe4ed2a6b8309f8ab5. + +No clear reason is given for the PHP Hack’s existence. This commit removes it, +because BCrypt hashes containing a `$` character in their salt are not valid +BCrypt hashes. + +(cherry picked from commit c840f71524067aa474c00c3eacfb83bd860bfc8a) +--- + ext/standard/crypt_blowfish.c | 8 -- + .../tests/crypt/bcrypt_salt_dollar.phpt | 82 +++++++++++++++++++ + 2 files changed, 82 insertions(+), 8 deletions(-) + create mode 100644 ext/standard/tests/crypt/bcrypt_salt_dollar.phpt + +diff --git a/ext/standard/crypt_blowfish.c b/ext/standard/crypt_blowfish.c +index c1f945f29ed..aa7e1bc2e68 100644 +--- a/ext/standard/crypt_blowfish.c ++++ b/ext/standard/crypt_blowfish.c +@@ -376,7 +376,6 @@ static unsigned char BF_atoi64[0x60] = { + #define BF_safe_atoi64(dst, src) \ + { \ + tmp = (unsigned char)(src); \ +- if (tmp == '$') break; /* PHP hack */ \ + if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ + tmp = BF_atoi64[tmp]; \ + if (tmp > 63) return -1; \ +@@ -404,13 +403,6 @@ static int BF_decode(BF_word *dst, const char *src, int size) + *dptr++ = ((c3 & 0x03) << 6) | c4; + } while (dptr < end); + +- if (end - dptr == size) { +- return -1; +- } +- +- while (dptr < end) /* PHP hack */ +- *dptr++ = 0; +- + return 0; + } + +diff --git a/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +new file mode 100644 +index 00000000000..32e335f4b08 +--- /dev/null ++++ b/ext/standard/tests/crypt/bcrypt_salt_dollar.phpt +@@ -0,0 +1,82 @@ ++--TEST-- ++bcrypt correctly rejects salts containing $ ++--FILE-- ++<?php ++for ($i = 0; $i < 23; $i++) { ++ $salt = '$2y$04$' . str_repeat('0', $i) . '$'; ++ $result = crypt("foo", $salt); ++ var_dump($salt); ++ var_dump($result); ++ var_dump($result === $salt); ++} ++?> ++--EXPECT-- ++string(8) "$2y$04$$" ++string(2) "*0" ++bool(false) ++string(9) "$2y$04$0$" ++string(2) "*0" ++bool(false) ++string(10) "$2y$04$00$" ++string(2) "*0" ++bool(false) ++string(11) "$2y$04$000$" ++string(2) "*0" ++bool(false) ++string(12) "$2y$04$0000$" ++string(2) "*0" ++bool(false) ++string(13) "$2y$04$00000$" ++string(2) "*0" ++bool(false) ++string(14) "$2y$04$000000$" ++string(2) "*0" ++bool(false) ++string(15) "$2y$04$0000000$" ++string(2) "*0" ++bool(false) ++string(16) "$2y$04$00000000$" ++string(2) "*0" ++bool(false) ++string(17) "$2y$04$000000000$" ++string(2) "*0" ++bool(false) ++string(18) "$2y$04$0000000000$" ++string(2) "*0" ++bool(false) ++string(19) "$2y$04$00000000000$" ++string(2) "*0" ++bool(false) ++string(20) "$2y$04$000000000000$" ++string(2) "*0" ++bool(false) ++string(21) "$2y$04$0000000000000$" ++string(2) "*0" ++bool(false) ++string(22) "$2y$04$00000000000000$" ++string(2) "*0" ++bool(false) ++string(23) "$2y$04$000000000000000$" ++string(2) "*0" ++bool(false) ++string(24) "$2y$04$0000000000000000$" ++string(2) "*0" ++bool(false) ++string(25) "$2y$04$00000000000000000$" ++string(2) "*0" ++bool(false) ++string(26) "$2y$04$000000000000000000$" ++string(2) "*0" ++bool(false) ++string(27) "$2y$04$0000000000000000000$" ++string(2) "*0" ++bool(false) ++string(28) "$2y$04$00000000000000000000$" ++string(2) "*0" ++bool(false) ++string(29) "$2y$04$000000000000000000000$" ++string(2) "*0" ++bool(false) ++string(30) "$2y$04$0000000000000000000000$" ++string(60) "$2y$04$000000000000000000000u2a2UpVexIt9k3FMJeAVr3c04F5tcI8K" ++bool(false) +-- +2.39.1 + +From ed0281b588a6840cb95f3134a4e68847a3be5bb7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@bastelstu.be> +Date: Mon, 23 Jan 2023 22:13:57 +0100 +Subject: [PATCH 2/7] crypt: Fix possible buffer overread in php_crypt() + +(cherry picked from commit a92acbad873a05470af1a47cb785a18eadd827b5) +--- + ext/standard/crypt.c | 1 + + ext/standard/tests/password/password_bcrypt_short.phpt | 8 ++++++++ + 2 files changed, 9 insertions(+) + create mode 100644 ext/standard/tests/password/password_bcrypt_short.phpt + +diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c +index 92430b69f77..04487f3fe5a 100644 +--- a/ext/standard/crypt.c ++++ b/ext/standard/crypt.c +@@ -151,6 +151,7 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch + } else if ( + salt[0] == '$' && + salt[1] == '2' && ++ salt[2] != 0 && + salt[3] == '$') { + char output[PHP_MAX_SALT_LEN + 1]; + +diff --git a/ext/standard/tests/password/password_bcrypt_short.phpt b/ext/standard/tests/password/password_bcrypt_short.phpt +new file mode 100644 +index 00000000000..085bc8a2390 +--- /dev/null ++++ b/ext/standard/tests/password/password_bcrypt_short.phpt +@@ -0,0 +1,8 @@ ++--TEST-- ++Test that password_hash() does not overread buffers when a short hash is passed ++--FILE-- ++<?php ++var_dump(password_verify("foo", '$2')); ++?> ++--EXPECT-- ++bool(false) +-- +2.39.1 + diff --git a/php-bug81746.patch b/php-bug81746.patch new file mode 100644 index 0000000..7f4c77f --- /dev/null +++ b/php-bug81746.patch @@ -0,0 +1,98 @@ +From 887cd0710ad856a0d22c329b6ea6c71ebd8621ae Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Fri, 27 Jan 2023 19:28:27 +0100 +Subject: [PATCH 3/7] Fix array overrun when appending slash to paths + +Fix it by extending the array sizes by one character. As the input is +limited to the maximum path length, there will always be place to append +the slash. As the php_check_specific_open_basedir() simply uses the +strings to compare against each other, no new failures related to too +long paths are introduced. +We'll let the DOM and XML case handle a potentially too long path in the +library code. + +(cherry picked from commit ec10b28d64decbc54aa1e585dce580f0bd7a5953) +--- + ext/dom/document.c | 2 +- + ext/xmlreader/php_xmlreader.c | 2 +- + main/fopen_wrappers.c | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/ext/dom/document.c b/ext/dom/document.c +index b478e1a1aab..e683eb8f701 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1379,7 +1379,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so + int validate, recover, resolve_externals, keep_blanks, substitute_ent; + int resolved_path_len; + int old_error_reporting = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + + if (id != NULL) { + intern = Z_DOMOBJ_P(id); +diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c +index 06f569949ce..ecc81ad1470 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -1038,7 +1038,7 @@ PHP_METHOD(xmlreader, XML) + xmlreader_object *intern = NULL; + char *source, *uri = NULL, *encoding = NULL; + int resolved_path_len, ret = 0; +- char *directory=NULL, resolved_path[MAXPATHLEN]; ++ char *directory=NULL, resolved_path[MAXPATHLEN + 1]; + xmlParserInputBufferPtr inputbfr; + xmlTextReaderPtr reader; + +diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c +index 27135020fa3..90de040a218 100644 +--- a/main/fopen_wrappers.c ++++ b/main/fopen_wrappers.c +@@ -138,10 +138,10 @@ PHPAPI ZEND_INI_MH(OnUpdateBaseDir) + */ + PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path) + { +- char resolved_name[MAXPATHLEN]; +- char resolved_basedir[MAXPATHLEN]; ++ char resolved_name[MAXPATHLEN + 1]; ++ char resolved_basedir[MAXPATHLEN + 1]; + char local_open_basedir[MAXPATHLEN]; +- char path_tmp[MAXPATHLEN]; ++ char path_tmp[MAXPATHLEN + 1]; + char *path_file; + size_t resolved_basedir_len; + size_t resolved_name_len; +-- +2.39.1 + +From 614468ce4056c0ef93aae09532dcffdf65b594b5 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Mon, 13 Feb 2023 11:46:47 +0100 +Subject: [PATCH 4/7] NEWS + +--- + NEWS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/NEWS b/NEWS +index 03e8c839c77..8157a20d4b3 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,14 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.28 ++ ++- Core: ++ . Fixed bug #81744 (Password_verify() always return true with some hash). ++ (CVE-2023-0567). (Tim Düsterhus) ++ . Fixed bug #81746 (1-byte array overrun in common path resolve code). ++ (CVE-2023-0568). (Niels Dossche) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + diff --git a/php-cve-2023-0662.patch b/php-cve-2023-0662.patch new file mode 100644 index 0000000..0a18a88 --- /dev/null +++ b/php-cve-2023-0662.patch @@ -0,0 +1,143 @@ +From 3a2fdef1ae38881110006616ee1f0534b082ca45 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:11:18 +0000 +Subject: [PATCH 5/7] Fix repeated warning for file uploads limit exceeding + +--- + main/rfc1867.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/main/rfc1867.c b/main/rfc1867.c +index edef19c16d6..4931b9aeefb 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -922,7 +922,10 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + skip_upload = 1; + } else if (upload_cnt <= 0) { + skip_upload = 1; +- sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ if (upload_cnt == 0) { ++ --upload_cnt; ++ sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded"); ++ } + } + + /* Return with an error if the posted data is garbled */ +-- +2.39.1 + +From 8ec78d28d20c82c75c4747f44c52601cfdb22516 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Thu, 19 Jan 2023 14:31:25 +0000 +Subject: [PATCH 6/7] Introduce max_multipart_body_parts INI + +This fixes GHSA-54hq-v5wp-fqgv DOS vulnerabality by limitting number of +parsed multipart body parts as currently all parts were always parsed. +--- + main/main.c | 1 + + main/rfc1867.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/main/main.c b/main/main.c +index 0b33b2b56c9..d8c465988cc 100644 +--- a/main/main.c ++++ b/main/main.c +@@ -836,6 +836,7 @@ PHP_INI_BEGIN() + PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) + PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) ++ PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) + + STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals) + STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals) +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 4931b9aeefb..1b212c93325 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -694,6 +694,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + void *event_extra_data = NULL; + unsigned int llen = 0; + int upload_cnt = INI_INT("max_file_uploads"); ++ int body_parts_cnt = INI_INT("max_multipart_body_parts"); + const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(); + php_rfc1867_getword_t getword; + php_rfc1867_getword_conf_t getword_conf; +@@ -715,6 +716,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + return; + } + ++ if (body_parts_cnt < 0) { ++ body_parts_cnt = PG(max_input_vars) + upload_cnt; ++ } ++ int body_parts_limit = body_parts_cnt; ++ + /* Get the boundary */ + boundary = strstr(content_type_dup, "boundary"); + if (!boundary) { +@@ -799,6 +805,11 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + char *pair = NULL; + int end = 0; + ++ if (--body_parts_cnt < 0) { ++ php_error_docref(NULL, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit); ++ goto fileupload_done; ++ } ++ + while (isspace(*cd)) { + ++cd; + } +-- +2.39.1 + +From 472db3ee3a00ac00d36019eee0b3b7362334481c Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 09:14:47 +0100 +Subject: [PATCH 7/7] NEWS + +--- + NEWS | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/NEWS b/NEWS +index 8157a20d4b3..c1668368818 100644 +--- a/NEWS ++++ b/NEWS +@@ -9,6 +9,10 @@ Backported from 8.0.28 + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) + ++- FPM: ++ . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart ++ request body). (CVE-2023-0662) (Jakub Zelenka) ++ + Backported from 8.0.27 + + - PDO/SQLite: +-- +2.39.1 + +From c04f310440a906fc4ca885f4ecf6e3e4cd36edc7 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 14 Feb 2023 11:47:22 +0100 +Subject: [PATCH] fix NEWS, not FPM specific + +--- + NEWS | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/NEWS b/NEWS +index c1668368818..3f8739eae78 100644 +--- a/NEWS ++++ b/NEWS +@@ -8,8 +8,6 @@ Backported from 8.0.28 + (CVE-2023-0567). (Tim Düsterhus) + . Fixed bug #81746 (1-byte array overrun in common path resolve code). + (CVE-2023-0568). (Niels Dossche) +- +-- FPM: + . Fixed bug GHSA-54hq-v5wp-fqgv (DOS vulnerability when parsing multipart + request body). (CVE-2023-0662) (Jakub Zelenka) + +-- +2.39.1 + diff --git a/php-cve-2023-3247.patch b/php-cve-2023-3247.patch new file mode 100644 index 0000000..e23aebf --- /dev/null +++ b/php-cve-2023-3247.patch @@ -0,0 +1,152 @@ +From 0cfca9aa1395271833848daec0bace51d965531d Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sun, 16 Apr 2023 15:05:03 +0200 +Subject: [PATCH] Fix missing randomness check and insufficient random bytes + for SOAP HTTP Digest +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If php_random_bytes_throw fails, the nonce will be uninitialized, but +still sent to the server. The client nonce is intended to protect +against a malicious server. See section 5.10 and 5.12 of RFC 7616 [1], +and bullet point 2 below. + +Tim pointed out that even though it's the MD5 of the nonce that gets sent, +enumerating 31 bits is trivial. So we have still a stack information leak +of 31 bits. + +Furthermore, Tim found the following issues: +* The small size of cnonce might cause the server to erroneously reject + a request due to a repeated (cnonce, nc) pair. As per the birthday + problem 31 bits of randomness will return a duplication with 50% + chance after less than 55000 requests and nc always starts counting at 1. +* The cnonce is intended to protect the client and password against a + malicious server that returns a constant server nonce where the server + precomputed a rainbow table between passwords and correct client response. + As storage is fairly cheap, a server could precompute the client responses + for (a subset of) client nonces and still have a chance of reversing the + client response with the same probability as the cnonce duplication. + + Precomputing the rainbow table for all 2^31 cnonces increases the rainbow + table size by factor 2 billion, which is infeasible. But precomputing it + for 2^14 cnonces only increases the table size by factor 16k and the server + would still have a 10% chance of successfully reversing a password with a + single client request. + +This patch fixes the issues by increasing the nonce size, and checking +the return value of php_random_bytes_throw(). In the process we also get +rid of the MD5 hashing of the nonce. + +[1] RFC 7616: https://www.rfc-editor.org/rfc/rfc7616 + +Co-authored-by: Tim Düsterhus <timwolla@php.net> +(cherry picked from commit 126d517ce240e9f638d9a5eaa509eaca49ef562a) +--- + NEWS | 6 ++++++ + ext/soap/php_http.c | 21 +++++++++++++-------- + 2 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/NEWS b/NEWS +index 3f8739eae7..7c07635cad 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.29 ++ ++- Soap: ++ . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random ++ bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla) ++ + Backported from 8.0.28 + + - Core: +diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c +index ee3dcbdc9a..e3a9afdbe9 100644 +--- a/ext/soap/php_http.c ++++ b/ext/soap/php_http.c +@@ -666,18 +666,23 @@ int make_http_soap_request(zval *this_ptr, + if ((digest = zend_hash_str_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest")-1)) != NULL) { + if (Z_TYPE_P(digest) == IS_ARRAY) { + char HA1[33], HA2[33], response[33], cnonce[33], nc[9]; +- zend_long nonce; ++ unsigned char nonce[16]; + PHP_MD5_CTX md5ctx; + unsigned char hash[16]; + +- php_random_bytes_throw(&nonce, sizeof(nonce)); +- nonce &= 0x7fffffff; ++ if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) { ++ ZEND_ASSERT(EG(exception)); ++ php_stream_close(stream); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl")-1); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket")-1); ++ zend_hash_str_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy")-1); ++ smart_str_free(&soap_headers_z); ++ smart_str_free(&soap_headers); ++ return FALSE; ++ } + +- PHP_MD5Init(&md5ctx); +- snprintf(cnonce, sizeof(cnonce), ZEND_LONG_FMT, nonce); +- PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, strlen(cnonce)); +- PHP_MD5Final(hash, &md5ctx); +- make_digest(cnonce, hash); ++ php_hash_bin2hex(cnonce, nonce, sizeof(nonce)); ++ cnonce[32] = 0; + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(digest), "nc", sizeof("nc")-1)) != NULL && + Z_TYPE_P(tmp) == IS_LONG) { +From 40439039c224bb8cdebd1b7b3d03b8cc11e7cce7 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 6 Jun 2023 18:05:22 +0200 +Subject: [PATCH] Fix GH-11382 add missing hash header for bin2hex + +--- + ext/soap/php_http.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c +index e3a9afdbe9f..912b8e341d8 100644 +--- a/ext/soap/php_http.c ++++ b/ext/soap/php_http.c +@@ -22,6 +22,7 @@ + #include "ext/standard/base64.h" + #include "ext/standard/md5.h" + #include "ext/standard/php_random.h" ++#include "ext/hash/php_hash.h" + + static char *get_http_header_value_nodup(char *headers, char *type, size_t *len); + static char *get_http_header_value(char *headers, char *type); +-- +2.40.1 + +From f3021d66d7bb42d2578530cc94f9bde47e58eb10 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 15 Jun 2023 08:47:55 +0200 +Subject: [PATCH] add cve + +--- + NEWS | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/NEWS b/NEWS +index 7c07635cade..899644b3d63 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,7 +5,8 @@ Backported from 8.0.29 + + - Soap: + . Fixed bug GHSA-76gg-c692-v2mw (Missing error check and insufficient random +- bytes in HTTP Digest authentication for SOAP). (nielsdos, timwolla) ++ bytes in HTTP Digest authentication for SOAP). ++ (CVE-2023-3247) (nielsdos, timwolla) + + Backported from 8.0.28 + +-- +2.40.1 + diff --git a/php-cve-2023-3823.patch b/php-cve-2023-3823.patch new file mode 100644 index 0000000..a795564 --- /dev/null +++ b/php-cve-2023-3823.patch @@ -0,0 +1,89 @@ +From c398fe98c044c8e7c23135acdc38d4ef7bedc983 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Mon, 10 Jul 2023 13:25:34 +0200 +Subject: [PATCH 1/4] Fix buffer mismanagement in phar_dir_read() + +Fixes GHSA-jqcx-ccgc-xwhv. + +(cherry picked from commit 80316123f3e9dcce8ac419bd9dd43546e2ccb5ef) +--- + ext/phar/dirstream.c | 15 ++++++++------ + ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt | 27 +++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 6 deletions(-) + create mode 100644 ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt + +diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c +index 4710703c70e..490b14528f1 100644 +--- a/ext/phar/dirstream.c ++++ b/ext/phar/dirstream.c +@@ -91,25 +91,28 @@ static int phar_dir_seek(php_stream *stream, zend_off_t offset, int whence, zend + */ + static ssize_t phar_dir_read(php_stream *stream, char *buf, size_t count) /* {{{ */ + { +- size_t to_read; + HashTable *data = (HashTable *)stream->abstract; + zend_string *str_key; + zend_ulong unused; + ++ if (count != sizeof(php_stream_dirent)) { ++ return -1; ++ } ++ + if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key(data, &str_key, &unused)) { + return 0; + } + + zend_hash_move_forward(data); +- to_read = MIN(ZSTR_LEN(str_key), count); + +- if (to_read == 0 || count < ZSTR_LEN(str_key)) { ++ php_stream_dirent *dirent = (php_stream_dirent *) buf; ++ ++ if (sizeof(dirent->d_name) <= ZSTR_LEN(str_key)) { + return 0; + } + +- memset(buf, 0, sizeof(php_stream_dirent)); +- memcpy(((php_stream_dirent *) buf)->d_name, ZSTR_VAL(str_key), to_read); +- ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0'; ++ memset(dirent, 0, sizeof(php_stream_dirent)); ++ PHP_STRLCPY(dirent->d_name, ZSTR_VAL(str_key), sizeof(dirent->d_name), ZSTR_LEN(str_key)); + + return sizeof(php_stream_dirent); + } +diff --git a/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt +new file mode 100644 +index 00000000000..4e12f05fb62 +--- /dev/null ++++ b/ext/phar/tests/GHSA-jqcx-ccgc-xwhv.phpt +@@ -0,0 +1,27 @@ ++--TEST-- ++GHSA-jqcx-ccgc-xwhv (Buffer overflow and overread in phar_dir_read()) ++--SKIPIF-- ++<?php if (!extension_loaded("phar")) die("skip"); ?> ++--INI-- ++phar.readonly=0 ++--FILE-- ++<?php ++$phar = new Phar(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar'); ++$phar->startBuffering(); ++$phar->addFromString(str_repeat('A', PHP_MAXPATHLEN - 1), 'This is the content of file 1.'); ++$phar->addFromString(str_repeat('B', PHP_MAXPATHLEN - 1).'C', 'This is the content of file 2.'); ++$phar->stopBuffering(); ++ ++$handle = opendir('phar://' . __DIR__ . '/GHSA-jqcx-ccgc-xwhv.phar'); ++var_dump(strlen(readdir($handle))); ++// Must not be a string of length PHP_MAXPATHLEN+1 ++var_dump(readdir($handle)); ++closedir($handle); ++?> ++--CLEAN-- ++<?php ++unlink(__DIR__. '/GHSA-jqcx-ccgc-xwhv.phar'); ++?> ++--EXPECTF-- ++int(%d) ++bool(false) +-- +2.41.0 + diff --git a/php-cve-2023-3824.patch b/php-cve-2023-3824.patch new file mode 100644 index 0000000..4a58ac4 --- /dev/null +++ b/php-cve-2023-3824.patch @@ -0,0 +1,644 @@ +From b3758bd21223b97c042cae7bd26a66cde081ea98 Mon Sep 17 00:00:00 2001 +From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> +Date: Sat, 15 Jul 2023 17:33:52 +0200 +Subject: [PATCH 2/4] Sanitize libxml2 globals before parsing + +Fixes GHSA-3qrf-m4j2-pcrr. + +To parse a document with libxml2, you first need to create a parsing context. +The parsing context contains parsing options (e.g. XML_NOENT to substitute +entities) that the application (in this case PHP) can set. +Unfortunately, libxml2 also supports providing default set options. +For example, if you call xmlSubstituteEntitiesDefault(1) then the XML_NOENT +option will be added to the parsing options every time you create a parsing +context **even if the application never requested XML_NOENT**. + +Third party extensions can override these globals, in particular the +substitute entity global. This causes entity substitution to be +unexpectedly active. + +Fix it by setting the parsing options to a sane known value. +For API calls that depend on global state we introduce +PHP_LIBXML_SANITIZE_GLOBALS() and PHP_LIBXML_RESTORE_GLOBALS(). +For other APIs that work directly with a context we introduce +php_libxml_sanitize_parse_ctxt_options(). + +(cherry picked from commit c283c3ab0ba45d21b2b8745c1f9c7cbfe771c975) +--- + ext/dom/document.c | 15 ++++++++ + ext/dom/documentfragment.c | 2 ++ + ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++ + ext/libxml/php_libxml.h | 36 +++++++++++++++++++ + ext/simplexml/simplexml.c | 6 ++++ + ...xml_global_state_entity_loader_bypass.phpt | 36 +++++++++++++++++++ + ext/soap/php_xml.c | 2 ++ + ext/xml/compat.c | 2 ++ + ext/xmlreader/php_xmlreader.c | 9 +++++ + ...xml_global_state_entity_loader_bypass.phpt | 35 ++++++++++++++++++ + ext/xsl/xsltprocessor.c | 9 +++-- + 11 files changed, 183 insertions(+), 5 deletions(-) + create mode 100644 ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt + create mode 100644 ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt + create mode 100644 ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt + +diff --git a/ext/dom/document.c b/ext/dom/document.c +index e683eb8f701..989b5b3dd24 100644 +--- a/ext/dom/document.c ++++ b/ext/dom/document.c +@@ -1458,6 +1458,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t so + options |= XML_PARSE_NOBLANKS; + } + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + xmlCtxtUseOptions(ctxt, options); + + ctxt->recovery = recover; +@@ -1758,7 +1759,9 @@ PHP_FUNCTION(dom_document_xinclude) + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(xinclude); + err = xmlXIncludeProcessFlags(docp, (int)flags); ++ PHP_LIBXML_RESTORE_GLOBALS(xinclude); + + /* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these + are added via xmlXIncludeProcess to mark beginning and ending of xincluded document +@@ -1798,6 +1801,7 @@ PHP_FUNCTION(dom_document_validate) + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(validate); + cvp = xmlNewValidCtxt(); + + cvp->userData = NULL; +@@ -1809,6 +1813,7 @@ PHP_FUNCTION(dom_document_validate) + } else { + RETVAL_FALSE; + } ++ PHP_LIBXML_RESTORE_GLOBALS(validate); + + xmlFreeValidCtxt(cvp); + +@@ -1843,14 +1848,18 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + + DOM_GET_OBJ(docp, id, xmlDocPtr, intern); + ++ PHP_LIBXML_SANITIZE_GLOBALS(new_parser_ctxt); ++ + switch (type) { + case DOM_LOAD_FILE: + if (CHECK_NULL_PATH(source, source_len)) { ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + php_error_docref(NULL, E_WARNING, "Invalid Schema file source"); + RETURN_FALSE; + } + valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN); + if (!valid_file) { ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + php_error_docref(NULL, E_WARNING, "Invalid Schema file source"); + RETURN_FALSE; + } +@@ -1871,6 +1880,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + parser); + sptr = xmlSchemaParse(parser); + xmlSchemaFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(new_parser_ctxt); + if (!sptr) { + php_error_docref(NULL, E_WARNING, "Invalid Schema"); + RETURN_FALSE; +@@ -1889,11 +1899,13 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type + valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(validate); + xmlSchemaSetValidOptions(vptr, valid_opts); + xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr); + is_valid = xmlSchemaValidateDoc(vptr, docp); + xmlSchemaFree(sptr); + xmlSchemaFreeValidCtxt(vptr); ++ PHP_LIBXML_RESTORE_GLOBALS(validate); + + if (is_valid == 0) { + RETURN_TRUE; +@@ -1964,12 +1976,14 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ + return; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + xmlRelaxNGSetParserErrors(parser, + (xmlRelaxNGValidityErrorFunc) php_libxml_error_handler, + (xmlRelaxNGValidityWarningFunc) php_libxml_error_handler, + parser); + sptr = xmlRelaxNGParse(parser); + xmlRelaxNGFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + if (!sptr) { + php_error_docref(NULL, E_WARNING, "Invalid RelaxNG"); + RETURN_FALSE; +@@ -2068,6 +2082,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ + ctxt->sax->error = php_libxml_ctx_error; + ctxt->sax->warning = php_libxml_ctx_warning; + } ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + if (options) { + htmlCtxtUseOptions(ctxt, (int)options); + } +diff --git a/ext/dom/documentfragment.c b/ext/dom/documentfragment.c +index 9b222586ac5..711c42f939d 100644 +--- a/ext/dom/documentfragment.c ++++ b/ext/dom/documentfragment.c +@@ -131,7 +131,9 @@ PHP_METHOD(domdocumentfragment, appendXML) { + } + + if (data) { ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + err = xmlParseBalancedChunkMemory(nodep->doc, NULL, NULL, 0, (xmlChar *) data, &lst); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + if (err != 0) { + RETURN_FALSE; + } +diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 00000000000..b28afd4694e +--- /dev/null ++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,36 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('dom')) die('skip dom extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++ ++function parseXML($xml) { ++ $doc = new DOMDocument(); ++ @$doc->loadXML($xml); ++ $doc->createDocumentFragment()->appendXML("&bork;"); ++ foreach (libxml_get_errors() as $error) { ++ var_dump(trim($error->message)); ++ } ++} ++ ++parseXML($xml); ++zend_test_override_libxml_global_state(); ++parseXML($xml); ++ ++echo "Done\n"; ++ ++?> ++--EXPECT-- ++string(25) "Entity 'bork' not defined" ++string(25) "Entity 'bork' not defined" ++string(25) "Entity 'bork' not defined" ++Done +diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h +index cf936e95de1..92028d5703e 100644 +--- a/ext/libxml/php_libxml.h ++++ b/ext/libxml/php_libxml.h +@@ -120,6 +120,42 @@ PHP_LIBXML_API void php_libxml_shutdown(void); + ZEND_TSRMLS_CACHE_EXTERN() + #endif + ++/* Other extension may override the global state options, these global options ++ * are copied initially to ctxt->options. Set the options to a known good value. ++ * See libxml2 globals.c and parserInternals.c. ++ * The unique_name argument allows multiple sanitizes and restores within the ++ * same function, even nested is necessary. */ ++#define PHP_LIBXML_SANITIZE_GLOBALS(unique_name) \ ++ int xml_old_loadsubset_##unique_name = xmlLoadExtDtdDefaultValue; \ ++ xmlLoadExtDtdDefaultValue = 0; \ ++ int xml_old_validate_##unique_name = xmlDoValidityCheckingDefaultValue; \ ++ xmlDoValidityCheckingDefaultValue = 0; \ ++ int xml_old_pedantic_##unique_name = xmlPedanticParserDefault(0); \ ++ int xml_old_substitute_##unique_name = xmlSubstituteEntitiesDefault(0); \ ++ int xml_old_linenrs_##unique_name = xmlLineNumbersDefault(0); \ ++ int xml_old_blanks_##unique_name = xmlKeepBlanksDefault(1); ++ ++#define PHP_LIBXML_RESTORE_GLOBALS(unique_name) \ ++ xmlLoadExtDtdDefaultValue = xml_old_loadsubset_##unique_name; \ ++ xmlDoValidityCheckingDefaultValue = xml_old_validate_##unique_name; \ ++ (void) xmlPedanticParserDefault(xml_old_pedantic_##unique_name); \ ++ (void) xmlSubstituteEntitiesDefault(xml_old_substitute_##unique_name); \ ++ (void) xmlLineNumbersDefault(xml_old_linenrs_##unique_name); \ ++ (void) xmlKeepBlanksDefault(xml_old_blanks_##unique_name); ++ ++/* Alternative for above, working directly on the context and not setting globals. ++ * Generally faster because no locking is involved, and this has the advantage that it sets the options to a known good value. */ ++static zend_always_inline void php_libxml_sanitize_parse_ctxt_options(xmlParserCtxtPtr ctxt) ++{ ++ ctxt->loadsubset = 0; ++ ctxt->validate = 0; ++ ctxt->pedantic = 0; ++ ctxt->replaceEntities = 0; ++ ctxt->linenumbers = 0; ++ ctxt->keepBlanks = 1; ++ ctxt->options = 0; ++} ++ + #else /* HAVE_LIBXML */ + #define libxml_module_ptr NULL + #endif +diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c +index 2cdff0e648d..101a9d8fd8c 100644 +--- a/ext/simplexml/simplexml.c ++++ b/ext/simplexml/simplexml.c +@@ -2194,7 +2194,9 @@ PHP_FUNCTION(simplexml_load_file) + RETURN_FALSE; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_file); + docp = xmlReadFile(filename, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_file); + + if (!docp) { + RETURN_FALSE; +@@ -2248,7 +2250,9 @@ PHP_FUNCTION(simplexml_load_string) + RETURN_FALSE; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_memory); + docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_memory); + + if (!docp) { + RETURN_FALSE; +@@ -2298,7 +2302,9 @@ SXE_METHOD(__construct) + return; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory); + docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options); ++ PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory); + + if (!docp) { + ((php_libxml_node_object *)sxe)->document = NULL; +diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 00000000000..2152e012328 +--- /dev/null ++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,36 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('simplexml')) die('skip simplexml extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++zend_test_override_libxml_global_state(); ++ ++echo "--- String test ---\n"; ++simplexml_load_string($xml); ++echo "--- Constructor test ---\n"; ++new SimpleXMLElement($xml); ++echo "--- File test ---\n"; ++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); ++simplexml_load_file("libxml_global_state_entity_loader_bypass.tmp"); ++ ++echo "Done\n"; ++ ++?> ++--CLEAN-- ++<?php ++@unlink("libxml_global_state_entity_loader_bypass.tmp"); ++?> ++--EXPECT-- ++--- String test --- ++--- Constructor test --- ++--- File test --- ++Done +diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c +index 18a266179b7..1bb7fa00a37 100644 +--- a/ext/soap/php_xml.c ++++ b/ext/soap/php_xml.c +@@ -93,6 +93,7 @@ xmlDocPtr soap_xmlParseFile(const char *filename) + if (ctxt) { + zend_bool old; + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + ctxt->keepBlanks = 0; + ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; + ctxt->sax->comment = soap_Comment; +@@ -141,6 +142,7 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size) + if (ctxt) { + zend_bool old; + ++ php_libxml_sanitize_parse_ctxt_options(ctxt); + ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace; + ctxt->sax->comment = soap_Comment; + ctxt->sax->warning = NULL; +diff --git a/ext/xml/compat.c b/ext/xml/compat.c +index fc4525650fc..57eb00dd429 100644 +--- a/ext/xml/compat.c ++++ b/ext/xml/compat.c +@@ -19,6 +19,7 @@ + #include "php.h" + #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT) + #include "expat_compat.h" ++#include "ext/libxml/php_libxml.h" + + typedef struct _php_xml_ns { + xmlNsPtr nsptr; +@@ -471,6 +472,7 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m + return NULL; + } + ++ php_libxml_sanitize_parse_ctxt_options(parser->parser); + xmlCtxtUseOptions(parser->parser, XML_PARSE_OLDSAX); + + parser->parser->replaceEntities = 1; +diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c +index ecc81ad1470..51d6bb9c9f2 100644 +--- a/ext/xmlreader/php_xmlreader.c ++++ b/ext/xmlreader/php_xmlreader.c +@@ -304,6 +304,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz + return NULL; + } + ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); + if (error_func || warn_func) { + xmlRelaxNGSetParserErrors(parser, + (xmlRelaxNGValidityErrorFunc) error_func, +@@ -312,6 +313,7 @@ static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, siz + } + sptr = xmlRelaxNGParse(parser); + xmlRelaxNGFreeParserCtxt(parser); ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + + return sptr; + } +@@ -881,7 +883,9 @@ PHP_METHOD(xmlreader, open) + valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN ); + + if (valid_file) { ++ PHP_LIBXML_SANITIZE_GLOBALS(reader_for_file); + reader = xmlReaderForFile(valid_file, encoding, options); ++ PHP_LIBXML_RESTORE_GLOBALS(reader_for_file); + } + + if (reader == NULL) { +@@ -958,7 +962,9 @@ PHP_METHOD(xmlreader, setSchema) + + intern = Z_XMLREADER_P(id); + if (intern && intern->ptr) { ++ PHP_LIBXML_SANITIZE_GLOBALS(schema); + retval = xmlTextReaderSchemaValidate(intern->ptr, source); ++ PHP_LIBXML_RESTORE_GLOBALS(schema); + + if (retval == 0) { + RETURN_TRUE; +@@ -1082,6 +1088,7 @@ PHP_METHOD(xmlreader, XML) + } + uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path); + } ++ PHP_LIBXML_SANITIZE_GLOBALS(text_reader); + reader = xmlNewTextReader(inputbfr, uri); + + if (reader != NULL) { +@@ -1100,9 +1107,11 @@ PHP_METHOD(xmlreader, XML) + xmlFree(uri); + } + ++ PHP_LIBXML_RESTORE_GLOBALS(text_reader); + return; + } + } ++ PHP_LIBXML_RESTORE_GLOBALS(text_reader); + } + + if (uri) { +diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +new file mode 100644 +index 00000000000..e9ffb04c2bb +--- /dev/null ++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -0,0 +1,35 @@ ++--TEST-- ++GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) ++--SKIPIF-- ++<?php ++if (!extension_loaded('libxml')) die('skip libxml extension not available'); ++if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available'); ++if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++?> ++--FILE-- ++<?php ++ ++$xml = "<?xml version='1.0'?><!DOCTYPE root [<!ENTITY % bork SYSTEM \"php://nope\"> %bork;]><nothing/>"; ++ ++libxml_use_internal_errors(true); ++zend_test_override_libxml_global_state(); ++ ++echo "--- String test ---\n"; ++$reader = XMLReader::xml($xml); ++$reader->read(); ++echo "--- File test ---\n"; ++file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); ++$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); ++$reader->read(); ++ ++echo "Done\n"; ++ ++?> ++--CLEAN-- ++<?php ++@unlink("libxml_global_state_entity_loader_bypass.tmp"); ++?> ++--EXPECT-- ++--- String test --- ++--- File test --- ++Done +diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c +index 079920d0ffa..2d95b2ff4bb 100644 +--- a/ext/xsl/xsltprocessor.c ++++ b/ext/xsl/xsltprocessor.c +@@ -398,7 +398,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) + xmlDoc *doc = NULL, *newdoc = NULL; + xsltStylesheetPtr sheetp, oldsheetp; + xsl_object *intern; +- int prevSubstValue, prevExtDtdValue, clone_docu = 0; ++ int clone_docu = 0; + xmlNode *nodep = NULL; + zval *cloneDocu, member, rv; + +@@ -421,13 +421,12 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) + stylesheet document otherwise the node proxies will be a mess */ + newdoc = xmlCopyDoc(doc, 1); + xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL); +- prevSubstValue = xmlSubstituteEntitiesDefault(1); +- prevExtDtdValue = xmlLoadExtDtdDefaultValue; ++ PHP_LIBXML_SANITIZE_GLOBALS(parse); ++ xmlSubstituteEntitiesDefault(1); + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + + sheetp = xsltParseStylesheetDoc(newdoc); +- xmlSubstituteEntitiesDefault(prevSubstValue); +- xmlLoadExtDtdDefaultValue = prevExtDtdValue; ++ PHP_LIBXML_RESTORE_GLOBALS(parse); + + if (!sheetp) { + xmlFreeDoc(newdoc); +-- +2.41.0 + +From ef1d507acf7be23d7624dc3c891683b2218feb51 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 1 Aug 2023 07:22:33 +0200 +Subject: [PATCH 3/4] NEWS + +--- + NEWS | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/NEWS b/NEWS +index 899644b3d63..4f88029a7d6 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,16 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.0.30 ++ ++- Libxml: ++ . Fixed bug GHSA-3qrf-m4j2-pcrr (Security issue with external entity loading ++ in XML without enabling it). (CVE-2023-3823) (nielsdos, ilutov) ++ ++- Phar: ++ . Fixed bug GHSA-jqcx-ccgc-xwhv (Buffer mismanagement in phar_dir_read()). ++ (CVE-2023-3824) (nielsdos) ++ + Backported from 8.0.29 + + - Soap: +-- +2.41.0 + +From 24e669e790e6aebd219c9a9fa19017455c8646b4 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Tue, 1 Aug 2023 07:37:25 +0200 +Subject: [PATCH 4/4] backport zend_test changes + (zend_test_override_libxml_global_state) + +--- + ...xml_global_state_entity_loader_bypass.phpt | 1 + + ...xml_global_state_entity_loader_bypass.phpt | 1 + + ...xml_global_state_entity_loader_bypass.phpt | 5 +++-- + ext/zend_test/test.c | 22 +++++++++++++++++++ + 4 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +index b28afd4694e..7fc2a249ac7 100644 +--- a/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('dom')) die('skip dom extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +diff --git a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +index 2152e012328..54f9d4941eb 100644 +--- a/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('simplexml')) die('skip simplexml extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +diff --git a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +index e9ffb04c2bb..b0120b325ef 100644 +--- a/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt ++++ b/ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt +@@ -5,6 +5,7 @@ GHSA-3qrf-m4j2-pcrr (libxml global state entity loader bypass) + if (!extension_loaded('libxml')) die('skip libxml extension not available'); + if (!extension_loaded('xmlreader')) die('skip xmlreader extension not available'); + if (!extension_loaded('zend-test')) die('skip zend-test extension not available'); ++if (!function_exists('zend_test_override_libxml_global_state')) die('skip not for Windows'); + ?> + --FILE-- + <?php +@@ -15,11 +16,11 @@ libxml_use_internal_errors(true); + zend_test_override_libxml_global_state(); + + echo "--- String test ---\n"; +-$reader = XMLReader::xml($xml); ++$reader = @XMLReader::xml($xml); + $reader->read(); + echo "--- File test ---\n"; + file_put_contents("libxml_global_state_entity_loader_bypass.tmp", $xml); +-$reader = XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); ++$reader = @XMLReader::open("libxml_global_state_entity_loader_bypass.tmp"); + $reader->read(); + + echo "Done\n"; +diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c +index 4f81adc6ac1..cdfc15571c0 100644 +--- a/ext/zend_test/test.c ++++ b/ext/zend_test/test.c +@@ -25,6 +25,11 @@ + #include "ext/standard/info.h" + #include "php_test.h" + ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++# include <libxml/globals.h> ++# include <libxml/parser.h> ++#endif ++ + static zend_class_entry *zend_test_interface; + static zend_class_entry *zend_test_class; + static zend_class_entry *zend_test_child_class; +@@ -48,6 +53,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_leak_variable, 0, 0, 1) + ZEND_ARG_INFO(0, variable) + ZEND_END_ARG_INFO() + ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++static ZEND_FUNCTION(zend_test_override_libxml_global_state) ++{ ++ ZEND_PARSE_PARAMETERS_NONE(); ++ ++ xmlLoadExtDtdDefaultValue = 1; ++ xmlDoValidityCheckingDefaultValue = 1; ++ (void) xmlPedanticParserDefault(1); ++ (void) xmlSubstituteEntitiesDefault(1); ++ (void) xmlLineNumbersDefault(1); ++ (void) xmlKeepBlanksDefault(0); ++} ++#endif ++ + ZEND_FUNCTION(zend_test_func) + { + /* dummy */ +@@ -297,6 +316,9 @@ static const zend_function_entry zend_test_functions[] = { + ZEND_FE(zend_terminate_string, arginfo_zend_terminate_string) + ZEND_FE(zend_leak_bytes, NULL) + ZEND_FE(zend_leak_variable, arginfo_zend_leak_variable) ++#if defined(HAVE_LIBXML) && !defined(PHP_WIN32) ++ ZEND_FE(zend_test_override_libxml_global_state, NULL) ++#endif + ZEND_FE_END + }; + +-- +2.41.0 + diff --git a/php-fpm-www.conf b/php-fpm-www.conf new file mode 100644 index 0000000..604386c --- /dev/null +++ b/php-fpm-www.conf @@ -0,0 +1,438 @@ +; Start a new pool named 'www'. +; the variable $pool can be used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'access.log' +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or @php_fpm_prefix@) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +; RPM: apache user chosen to provide access to the same directories as httpd +user = apache +; RPM: Keep a group allowed to write in log dir. +group = apache + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = 127.0.0.1:9000 + +; Set listen(2) backlog. +; Default Value: 511 +;listen.backlog = 511 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. +; Default Values: user and group are set as the running user +; mode is set to 0660 +;listen.owner = nobody +;listen.group = nobody +;listen.mode = 0660 + +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = apache,nginx +;listen.acl_groups = + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 + +; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user +; or group is differrent than the master process user. It allows to create process +; core dump and ptrace the process for the pool user. +; Default Value: no +; process.dumpable = yes + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 50 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 5 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 5 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 35 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: @EXPANDED_DATADIR@/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +slowlog = /var/log/php-fpm/www-slow.log + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; Depth of slow log stack trace. +; Default Value: 20 +;request_slowlog_trace_depth = 20 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +;catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; execute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or @prefix@) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +php_admin_value[error_log] = /var/log/php-fpm/www-error.log +php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 128M + +; Set the following data paths to directories owned by the FPM process user. +; +; Do not change the ownership of existing system directories, if the process +; user does not have write permission, create dedicated directories for this +; purpose. +; +; See warning about choosing the location of these directories on your system +; at http://php.net/session.save-path +php_value[session.save_handler] = files +php_value[session.save_path] = /var/lib/php/session +php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache +;php_value[opcache.file_cache] = /var/lib/php/opcache diff --git a/php-fpm.conf b/php-fpm.conf new file mode 100644 index 0000000..53a07b6 --- /dev/null +++ b/php-fpm.conf @@ -0,0 +1,137 @@ +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +; All relative paths in this configuration file are relative to PHP's install +; prefix. + +; Include one or more files. If glob(3) exists, it is used to include a bunch of +; files from a glob(3) pattern. This directive can be used everywhere in the +; file. +include=/etc/php-fpm.d/*.conf + +;;;;;;;;;;;;;;;;;; +; Global Options ; +;;;;;;;;;;;;;;;;;; + +[global] +; Pid file +; Default Value: none +pid = /run/php-fpm/php-fpm.pid + +; Error log file +; If it's set to "syslog", log is sent to syslogd instead of being written +; in a local file. +; Default Value: /var/log/php-fpm.log +error_log = /var/log/php-fpm/error.log + +; syslog_facility is used to specify what type of program is logging the +; message. This lets syslogd specify that messages from different facilities +; will be handled differently. +; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) +; Default Value: daemon +;syslog.facility = daemon + +; syslog_ident is prepended to every message. If you have multiple FPM +; instances running on the same server, you can change the default value +; which must suit common needs. +; Default Value: php-fpm +;syslog.ident = php-fpm + +; Log level +; Possible Values: alert, error, warning, notice, debug +; Default Value: notice +;log_level = notice + +; Log limit on number of characters in the single line (log entry). If the +; line is over the limit, it is wrapped on multiple lines. The limit is for +; all logged characters including message prefix and suffix if present. However +; the new line character does not count into it as it is present only when +; logging to a file descriptor. It means the new line character is not present +; when logging to syslog. +; Default Value: 1024 +;log_limit = 4096 + +; Log buffering specifies if the log line is buffered which means that the +; line is written in a single write operation. If the value is false, then the +; data is written directly into the file descriptor. It is an experimental +; option that can potentionaly improve logging performance and memory usage +; for some heavy logging scenarios. This option is ignored if logging to syslog +; as it has to be always buffered. +; Default value: yes +;log_buffering = no + +; If this number of child processes exit with SIGSEGV or SIGBUS within the time +; interval set by emergency_restart_interval then FPM will restart. A value +; of '0' means 'Off'. +; Default Value: 0 +;emergency_restart_threshold = 0 + +; Interval of time used by emergency_restart_interval to determine when +; a graceful restart will be initiated. This can be useful to work around +; accidental corruptions in an accelerator's shared memory. +; Available Units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;emergency_restart_interval = 0 + +; Time limit for child processes to wait for a reaction on signals from master. +; Available units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;process_control_timeout = 0 + +; The maximum number of processes FPM will fork. This has been designed to control +; the global number of processes when using dynamic PM within a lot of pools. +; Use it with caution. +; Note: A value of 0 indicates no limit +; Default Value: 0 +;process.max = 128 + +; Specify the nice(2) priority to apply to the master process (only if set) +; The value can vary from -19 (highest priority) to 20 (lowest priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool process will inherit the master process priority +; unless specified otherwise +; Default Value: no set +;process.priority = -19 + +; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. +; Default Value: yes +daemonize = yes + +; Set open file descriptor rlimit for the master process. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit for the master process. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Specify the event mechanism FPM will use. The following is available: +; - select (any POSIX os) +; - poll (any POSIX os) +; - epoll (linux >= 2.5.44) +; Default Value: not set (auto detection) +;events.mechanism = epoll + +; When FPM is built with systemd integration, specify the interval, +; in seconds, between health report notification to systemd. +; Set to 0 to disable. +; Available Units: s(econds), m(inutes), h(ours) +; Default Unit: seconds +; Default value: 10 +;systemd_interval = 10 + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +; Multiple pools of child processes may be started with different listening +; ports and different management options. The name of the pool will be +; used in logs and stats. There is no limitation on the number of pools which +; FPM can handle. Your system will tell you anyway :) + +; See /etc/php-fpm.d/*.conf + diff --git a/php-fpm.logrotate b/php-fpm.logrotate new file mode 100644 index 0000000..25f9feb --- /dev/null +++ b/php-fpm.logrotate @@ -0,0 +1,9 @@ +/var/log/php-fpm/*log { + missingok + notifempty + sharedscripts + delaycompress + postrotate + /bin/kill -SIGUSR1 `cat /run/php-fpm/php-fpm.pid 2>/dev/null` 2>/dev/null || true + endscript +} diff --git a/php-fpm.service b/php-fpm.service new file mode 100644 index 0000000..b68765f --- /dev/null +++ b/php-fpm.service @@ -0,0 +1,20 @@ +# It's not recommended to modify this file in-place, because it +# will be overwritten during upgrades. If you want to customize, +# the best way is to use the "systemctl edit" command. + +[Unit] +Description=The PHP FastCGI Process Manager +After=syslog.target network.target + +[Service] +Type=notify +EnvironmentFile=/etc/sysconfig/php-fpm +ExecStart=/usr/sbin/php-fpm --nodaemonize +ExecReload=/bin/kill -USR2 $MAINPID +PrivateTmp=true +RuntimeDirectory=php-fpm +RuntimeDirectoryMode=0755 + +[Install] +WantedBy=multi-user.target + diff --git a/php-fpm.wants b/php-fpm.wants new file mode 100644 index 0000000..5c7c8e4 --- /dev/null +++ b/php-fpm.wants @@ -0,0 +1,3 @@ +[Unit] +Wants=php-fpm.service + diff --git a/php.conf b/php.conf new file mode 100644 index 0000000..d192ccf --- /dev/null +++ b/php.conf @@ -0,0 +1,52 @@ +# +# The following lines prevent .user.ini files from being viewed by Web clients. +# +<Files ".user.ini"> + <IfModule mod_authz_core.c> + Require all denied + </IfModule> + <IfModule !mod_authz_core.c> + Order allow,deny + Deny from all + Satisfy All + </IfModule> +</Files> + +# +# Allow php to handle Multiviews +# +AddType text/html .php + +# +# Add index.php to the list of files that will be served as directory +# indexes. +# +DirectoryIndex index.php + +# mod_php options +<IfModule mod_php7.c> + # + # Cause the PHP interpreter to handle files with a .php extension. + # + <FilesMatch \.(php|phar)$> + SetHandler application/x-httpd-php + </FilesMatch> + + # + # Uncomment the following lines to allow PHP to pretty-print .phps + # files as PHP source code: + # + #<FilesMatch \.phps$> + # SetHandler application/x-httpd-php-source + #</FilesMatch> + + # + # Apache specific PHP configuration options + # those can be override in each configured vhost + # + php_value session.save_handler "files" + php_value session.save_path "/var/lib/php/session" + php_value soap.wsdl_cache_dir "/var/lib/php/wsdlcache" + + #php_value opcache.file_cache "/var/lib/php/opcache" +</IfModule> diff --git a/php.conf2 b/php.conf2 new file mode 100644 index 0000000..aeed80f --- /dev/null +++ b/php.conf2 @@ -0,0 +1,12 @@ + +# Redirect to local php-fpm if mod_php (5 or 7) is not available +<IfModule !mod_php5.c> + <IfModule !mod_php7.c> + # Enable http authorization headers + SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 + + <FilesMatch \.(php|phar)$> + SetHandler "proxy:fcgi://127.0.0.1:9000" + </FilesMatch> + </IfModule> +</IfModule> @@ -0,0 +1,1678 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (usually C:\windows) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it is +; much more verbose when it comes to errors. We recommend using the +; development version only in development environments, as errors shown to +; application users can inadvertently leak otherwise secure information. + +; This is the php.ini-production INI file. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED +; Development Value: E_ALL +; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.sid_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to an empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; <? and ?> tags as PHP source which should be processed as such. It is +; generally recommended that <?php and ?> should be used and that this feature +; should be disabled, as enabling it may result in issues when generating XML +; documents, however this remains supported for backward compatibility reasons. +; Note that this directive does not control the <?= shorthand tag, which can be +; used regardless of this directive. +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/short-open-tag +short_open_tag = Off + +; The number of significant digits displayed in floating point numbers. +; http://php.net/precision +precision = 14 + +; Output buffering is a mechanism for controlling how much output data +; (excluding headers and cookies) PHP should keep internally before pushing that +; data to the client. If your application's output exceeds this setting, PHP +; will send that data in chunks of roughly the size you specify. +; Turning on this setting and managing its maximum buffer size can yield some +; interesting side-effects depending on your application and web server. +; You may be able to send headers and cookies after you've already sent output +; through print or echo. You also may see performance benefits if your server is +; emitting less packets due to buffered output versus PHP streaming the output +; as it gets it. On production servers, 4096 bytes is a good setting for performance +; reasons. +; Note: Output buffering can also be controlled via Output Buffering Control +; functions. +; Possible Values: +; On = Enabled and buffer is unlimited. (Use with caution) +; Off = Disabled +; Integer = Enables the buffer and sets its maximum size in bytes. +; Note: This directive is hardcoded to Off for the CLI SAPI +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 +; http://php.net/output-buffering +output_buffering = 4096 + +; You can redirect all of the output of your scripts to a function. For +; example, if you set output_handler to "mb_output_handler", character +; encoding will be transparently converted to the specified encoding. +; Setting any output handler automatically turns on output buffering. +; Note: People who wrote portable scripts should not depend on this ini +; directive. Instead, explicitly set the output handler using ob_start(). +; Using this ini directive may cause problems unless you know what script +; is doing. +; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler" +; and you cannot use both "ob_gzhandler" and "zlib.output_compression". +; Note: output_handler must be empty if this is set 'On' !!!! +; Instead you must use zlib.output_handler. +; http://php.net/output-handler +;output_handler = + +; URL rewriter function rewrites URL on the fly by using +; output buffer. You can set target tags by this configuration. +; "form" tag is special tag. It will add hidden input tag to pass values. +; Refer to session.trans_sid_tags for usage. +; Default Value: "form=" +; Development Value: "form=" +; Production Value: "form=" +;url_rewriter.tags + +; URL rewriter will not rewrite absolute URL nor form by default. To enable +; absolute URL rewrite, allowed hosts must be defined at RUNTIME. +; Refer to session.trans_sid_hosts for more details. +; Default Value: "" +; Development Value: "" +; Production Value: "" +;url_rewriter.hosts + +; Transparent output compression using the zlib library +; Valid values for this option are 'off', 'on', or a specific buffer size +; to be used for compression (default is 4KB) +; Note: Resulting chunk size may vary due to nature of compression. PHP +; outputs chunks that are few hundreds bytes each as a result of +; compression. If you prefer a larger chunk size for better +; performance, enable output_buffering in addition. +; Note: You need to use zlib.output_handler instead of the standard +; output_handler, or otherwise the output will be corrupted. +; http://php.net/zlib.output-compression +zlib.output_compression = Off + +; http://php.net/zlib.output-compression-level +;zlib.output_compression_level = -1 + +; You cannot specify additional output handlers if zlib.output_compression +; is activated here. This setting does the same as output_handler but in +; a different order. +; http://php.net/zlib.output-handler +;zlib.output_handler = + +; Implicit flush tells PHP to tell the output layer to flush itself +; automatically after every output block. This is equivalent to calling the +; PHP function flush() after each and every call to print() or echo() and each +; and every HTML block. Turning this option on has serious performance +; implications and is generally recommended for debugging purposes only. +; http://php.net/implicit-flush +; Note: This directive is hardcoded to On for the CLI SAPI +implicit_flush = Off + +; The unserialize callback function will be called (with the undefined class' +; name as parameter), if the unserializer finds an undefined class +; which should be instantiated. A warning appears if the specified function is +; not defined, or if the function doesn't include/implement the missing class. +; So only set this entry, if you really want to implement such a +; callback-function. +unserialize_callback_func = + +; The unserialize_max_depth specifies the default depth limit for unserialized +; structures. Setting the depth limit too high may result in stack overflows +; during unserialization. The unserialize_max_depth ini setting can be +; overridden by the max_depth option on individual unserialize() calls. +; A value of 0 disables the depth limit. +;unserialize_max_depth = 4096 + +; When floats & doubles are serialized, store serialize_precision significant +; digits after the floating point. The default value ensures that when floats +; are decoded with unserialize, the data will remain the same. +; The value is also used for json_encode when encoding double values. +; If -1 is used, then dtoa mode 0 is used which automatically select the best +; precision. +serialize_precision = -1 + +; open_basedir, if set, limits all file operations to the defined directory +; and below. This directive makes most sense if used in a per-directory +; or per-virtualhost web server configuration file. +; Note: disables the realpath cache +; http://php.net/open-basedir +;open_basedir = + +; This directive allows you to disable certain functions. +; It receives a comma-delimited list of function names. +; http://php.net/disable-functions +disable_functions = + +; This directive allows you to disable certain classes. +; It receives a comma-delimited list of class names. +; http://php.net/disable-classes +disable_classes = + +; Colors for Syntax Highlighting mode. Anything that's acceptable in +; <span style="color: ???????"> would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; Note: if open_basedir is set, the cache is disabled +; http://php.net/realpath-cache-size +;realpath_cache_size = 4096k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +; Enables or disables the circular reference collector. +; http://php.net/zend.enable-gc +zend.enable_gc = On + +; If enabled, scripts may be written in encodings that are incompatible with +; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such +; encodings. To use this feature, mbstring extension must be enabled. +; Default: Off +;zend.multibyte = Off + +; Allows to set the default encoding for the scripts. This value will be used +; unless "declare(encoding=...)" directive appears at the top of the script. +; Only affects if zend.multibyte is set. +; Default: "" +;zend.script_encoding = + +; Allows to include or exclude arguments from stack traces generated for exceptions +; Default: Off +; In production, it is recommended to turn this setting on to prohibit the output +; of sensitive information in stack traces +zend.exception_ignore_args = On + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = On + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; How many GET/POST/COOKIE input variables may be accepted +;max_input_vars = 1000 + +; Maximum amount of memory a script may consume +; http://php.net/memory-limit +memory_limit = 128M + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it is automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL (Show all errors, warnings and notices including coding standards.) +; E_ALL & ~E_NOTICE (Show all errors, except for notices) +; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED +; Development Value: E_ALL +; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; For production environments, we recommend logging errors rather than +; sending them to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. We strongly recommend you +; set this to 'off' for production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This is only effective in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; This directive is DEPRECATED. +; Default Value: Off +; Development Value: Off +; Production Value: Off +; http://php.net/track-errors +;track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of formatting the +; error message as HTML for easier reading. This directive controls whether +; the error message is formatted as HTML or not. +; Note: This directive is hardcoded to Off for the CLI SAPI +; http://php.net/html-errors +;html_errors = On + +; If html_errors is set to On *and* docref_root is not empty, then PHP +; produces clickable error messages that direct to a page describing the error +; or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty, in which +; case no links to documentation are generated. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "<span style='color: #ff0000'>" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "</span>" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on Windows). +;error_log = syslog + +; The syslog ident is a string which is prepended to every message logged +; to syslog. Only used when error_log is set to syslog. +;syslog.ident = php + +; The syslog facility is used to specify what type of program is logging +; the message. Only used when error_log is set to syslog. +;syslog.facility = user + +; Set this to disable filtering control characters (the default). +; Some loggers only accept NVT-ASCII, others accept anything that's not +; control characters. If your logger accepts everything, then no filtering +; is needed at all. +; Allowed values are: +; ascii (all printable ASCII characters and NL) +; no-ctrl (all characters except control characters) +; all (all characters) +; raw (like "all", but messages are not split at newlines) +; http://php.net/syslog.filter +;syslog.filter = ascii + +;windows.show_crt_warning +; Default value: 0 +; Development value: 0 +; Production value: 0 + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. G,P,C,E & S are abbreviations for the following respective super +; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty +; paid for the registration of these arrays and because ENV is not as commonly +; used as the others, ENV is not recommended on productions servers. You +; can still get access to the environment variables through getenv() should you +; need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "GPCS" + +; This directive determines which super global data (G,P & C) should be +; registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive +; are specified in the same manner as the variables_order directive, +; EXCEPT one. Leaving this value empty will cause PHP to use the value set +; in the variables_order directive. It does not mean it will leave the super +; globals array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the ENV, REQUEST and SERVER variables are created when they're +; first used (Just In Time) instead of when the script starts. If these +; variables are not used within a script, having this directive on will result +; in a performance gain. The PHP directive register_argc_argv must be disabled +; for this directive to have any effect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Whether PHP will read the POST data. +; This option is enabled by default. +; Most likely, you won't want to disable this option globally. It causes $_POST +; and $_FILES to always be empty; the only way you will be able to read the +; POST data will be through the php://input stream wrapper. This can be useful +; to proxy requests or to process the POST data in a memory efficient fashion. +; http://php.net/enable-post-data-reading +;enable_post_data_reading = Off + +; Maximum size of POST data that PHP will accept. +; Its value may be 0 to disable the limit. It is ignored if POST data reading +; is disabled through enable_post_data_reading. +; http://php.net/post-max-size +post_max_size = 8M + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a media type using the Content-Type header. To +; disable this, simply set it to be empty. +; +; PHP's built-in default media type is set to text/html. +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to UTF-8. +; http://php.net/default-charset +default_charset = "UTF-8" + +; PHP internal character encoding is set to empty. +; If empty, default_charset is used. +; http://php.net/internal-encoding +;internal_encoding = + +; PHP input character encoding is set to empty. +; If empty, default_charset is used. +; http://php.net/input-encoding +;input_encoding = + +; PHP output character encoding is set to empty. +; If empty, default_charset is used. +; See also output_buffer. +; http://php.net/output-encoding +;output_encoding = + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/php/includes" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +;extension_dir = "./" +; On windows: +;extension_dir = "ext" + +; Directory where the temporary files should be placed. +; Defaults to the system default (see sys_get_temp_dir) +;sys_temp_dir = "/tmp" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside +; of the web tree and people will not be able to circumvent .htaccess security. +;cgi.discard_path=1 + +; FastCGI under IIS supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1 + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If set to 0, PHP sends Status: header that +; is supported by Apache. When this option is set to 1, PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! +; (shebang) at the top of the running script. This line might be needed if the +; script support running both as stand-alone script and via PHP CGI<. PHP in CGI +; mode skips this line and ignores its content if this directive is turned on. +; http://php.net/cgi.check-shebang-line +;cgi.check_shebang_line=1 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 2M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename +; +; For example: +; +; extension=mysqli +; +; When the extension library to load is not located in the default extension +; directory, You may specify an absolute path to the library file: +; +; extension=/path/to/extension/mysqli.so +; +; Note : The syntax used in previous PHP versions ('extension=<ext>.so' and +; 'extension='php_<ext>.dll') is supported for legacy reasons and may be +; deprecated in a future PHP major version. So, when it is possible, please +; move to the new ('extension=<ext>) syntax. + +;;;; +; Note: packaged extension modules are now loaded via the .ini files +; found in the directory /etc/php.d; these are loaded by default. +;;;; + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[CLI Server] +; Whether the CLI web server uses ANSI color coding in its terminal output. +cli_server.color = On + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +;date.timezone = + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +; Use of this INI entry is deprecated, use global input_encoding instead. +; If empty, default_charset or input_encoding or iconv.input_encoding is used. +; The precedence is: default_charset < input_encoding < iconv.input_encoding +;iconv.input_encoding = + +; Use of this INI entry is deprecated, use global internal_encoding instead. +; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. +; The precedence is: default_charset < internal_encoding < iconv.internal_encoding +;iconv.internal_encoding = + +; Use of this INI entry is deprecated, use global output_encoding instead. +; If empty, default_charset or output_encoding or iconv.output_encoding is used. +; The precedence is: default_charset < output_encoding < iconv.output_encoding +; To use an output encoding conversion, iconv's output handler must be set +; otherwise output encoding conversion cannot be performed. +;iconv.output_encoding = + +[imap] +; rsh/ssh logins are disabled by default. Use this INI entry if you want to +; enable them. Note that the IMAP library does not filter mailbox names before +; passing them to rsh/ssh command, thus passing untrusted data to this function +; with rsh/ssh enabled is insecure. +;imap.enable_insecure_rsh=0 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING +;intl.use_exceptions = 0 + +[sqlite3] +; Directory pointing to SQLite3 extensions +; http://php.net/sqlite3.extension-dir +;sqlite3.extension_dir = + +; SQLite defensive mode flag (only available from SQLite 3.26+) +; When the defensive flag is enabled, language features that allow ordinary +; SQL to deliberately corrupt the database file are disabled. This forbids +; writing directly to the schema, shadow tables (eg. FTS data tables), or +; the sqlite_dbpage virtual table. +; https://www.sqlite.org/c3ref/c_dbconfig_defensive.html +; (for older SQLite versions, this flag has no use) +;sqlite3.defensive = 1 + +[Pcre] +; PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +; PCRE library recursion limit. +; Please note that if you set this value to a high number you may consume all +; the available process stack and eventually crash PHP (due to reaching the +; stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +; Enables or disables JIT compilation of patterns. This requires the PCRE +; library to be compiled with JIT support. +pcre.jit=0 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[mail function] +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +sendmail_path = /usr/sbin/sendmail -t -i + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(). +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = Off + +; The path to a log file that will log all mail() calls. Log entries include +; the full path of the script, line number, To address and headers. +;mail.log = +; Log mail to syslog (Event Log on Windows). +;mail.log = syslog + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysqli_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysqli_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statistics by mysqlnd which can be +; used to tune and monitor MySQL operations. +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statistics by mysqlnd which can be +; used to tune and monitor MySQL operations. +mysqlnd.collect_memory_statistics = Off + +; Records communication from all extensions using mysqlnd to the specified log +; file. +; http://php.net/mysqlnd.debug +;mysqlnd.debug = + +; Defines which queries will be logged. +;mysqlnd.log_mask = 0 + +; Default size of the mysqlnd memory pool, which is used by result sets. +;mysqlnd.mempool_default_size = 16000 + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +;mysqlnd.net_read_buffer_size = 32768 + +; Timeout for network requests in seconds. +;mysqlnd.net_read_timeout = 31536000 + +; SHA-256 Authentication Plugin related. File with the MySQL server public RSA +; key. +;mysqlnd.sha256_server_public_key = + +[OCI8] +; see /etc/php.d/20-oci8.ini + +[PostgreSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Notice message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if +; your OS has problems with many files in one directory, and is +; a more efficient layout for servers that handle many sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path + +; RPM note : session directory must be owned by process owner +; for mod_php, see /etc/httpd/conf.d/php.conf +; for php-fpm, see /etc/php-fpm.d/*conf +;session.save_path = "/tmp" + +; Whether to use strict session mode. +; Strict session mode does not accept an uninitialized session ID, and +; regenerates the session ID if the browser sends an uninitialized session ID. +; Strict mode protects applications from session fixation via a session adoption +; vulnerability. It is disabled by default for maximum compatibility, but +; enabling it is encouraged. +; https://wiki.php.net/rfc/strict_sessions +session.use_strict_mode = 0 + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combating +; session hijacking when not specifying and managing your own session id. It is +; not the be-all and end-all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it +; inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) +; Current valid values are "Strict", "Lax" or "None". When using "None", +; make sure to include the quotes, as `none` is interpreted like `false` in ini files. +; https://tools.ietf.org/html/draft-west-first-party-cookies-07 +session.cookie_samesite = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using gc_probability/gc_divisor, +; e.g. 1/100 means there is a 1% chance that the GC process starts on each request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 1 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using gc_probability/gc_divisor, +; e.g. 1/100 means there is a 1% chance that the GC process starts on each request. +; For high volume production servers, using a value of 1000 is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script is the equivalent of setting +; session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; find /path/to/sessions -cmin +24 -type f | xargs rm + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users' security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publicly accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Set session ID character length. This value could be between 22 to 256. +; Shorter length than default is supported only for compatibility reason. +; Users should use 32 or more chars. +; http://php.net/session.sid-length +; Default Value: 32 +; Development Value: 26 +; Production Value: 26 +session.sid_length = 26 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +; <form> is special; if you include them here, the rewriter will +; add a hidden <input> field with the info which is otherwise appended +; to URLs. <form> tag's action attribute URL will not be modified +; unless it is specified. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=" +; Development Value: "a=href,area=href,frame=src,form=" +; Production Value: "a=href,area=href,frame=src,form=" +; http://php.net/url-rewriter.tags +session.trans_sid_tags = "a=href,area=href,frame=src,form=" + +; URL rewriter does not rewrite absolute URLs by default. +; To enable rewrites for absolute paths, target hosts must be specified +; at RUNTIME. i.e. use ini_set() +; <form> tags is special. PHP will check action attribute's URL regardless +; of session.trans_sid_tags setting. +; If no host is defined, HTTP_HOST will be used for allowed host. +; Example value: php.net,www.php.net,wiki.php.net +; Use "," for multiple hosts. No spaces are allowed. +; Default Value: "" +; Development Value: "" +; Production Value: "" +;session.trans_sid_hosts="" + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.sid_bits_per_character = 5 + +; Enable upload progress tracking in $_SESSION +; Default Value: On +; Development Value: On +; Production Value: On +; http://php.net/session.upload-progress.enabled +;session.upload_progress.enabled = On + +; Cleanup the progress information as soon as all POST data has been read +; (i.e. upload completed). +; Default Value: On +; Development Value: On +; Production Value: On +; http://php.net/session.upload-progress.cleanup +;session.upload_progress.cleanup = On + +; A prefix used for the upload progress key in $_SESSION +; Default Value: "upload_progress_" +; Development Value: "upload_progress_" +; Production Value: "upload_progress_" +; http://php.net/session.upload-progress.prefix +;session.upload_progress.prefix = "upload_progress_" + +; The index name (concatenated with the prefix) in $_SESSION +; containing the upload progress information +; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" +; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" +; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" +; http://php.net/session.upload-progress.name +;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" + +; How frequently the upload progress should be updated. +; Given either in percentages (per-file), or in bytes +; Default Value: "1%" +; Development Value: "1%" +; Production Value: "1%" +; http://php.net/session.upload-progress.freq +;session.upload_progress.freq = "1%" + +; The minimum delay between updates, in seconds +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.upload-progress.min-freq +;session.upload_progress.min_freq = "1" + +; Only write session data when session data is changed. Enabled by default. +; http://php.net/session.lazy-write +;session.lazy_write = On + +[Assertion] +; Switch whether to compile assertions at all (to have no overhead at run-time) +; -1: Do not compile at all +; 0: Jump over assertion at run-time +; 1: Execute assertions +; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) +; Default Value: 1 +; Development Value: 1 +; Production Value: -1 +; http://php.net/zend.assertions +zend.assertions = -1 + +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Throw an AssertionError on failed assertions +; http://php.net/assert.exception +;assert.exception = On + +; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[mbstring] +; language for internal character representation. +; This affects mb_send_mail() and mbstring.detect_order. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; Use of this INI entry is deprecated, use global internal_encoding instead. +; internal/script encoding. +; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) +; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. +; The precedence is: default_charset < internal_encoding < iconv.internal_encoding +;mbstring.internal_encoding = + +; Use of this INI entry is deprecated, use global input_encoding instead. +; http input encoding. +; mbstring.encoding_translation = On is needed to use this setting. +; If empty, default_charset or input_encoding or mbstring.input is used. +; The precedence is: default_charset < input_encoding < mbsting.http_input +; http://php.net/mbstring.http-input +;mbstring.http_input = + +; Use of this INI entry is deprecated, use global output_encoding instead. +; http output encoding. +; mb_output_handler must be registered as output buffer to function. +; If empty, default_charset or output_encoding or mbstring.http_output is used. +; The precedence is: default_charset < output_encoding < mbstring.http_output +; To use an output encoding conversion, mbstring's output handler must be set +; otherwise output encoding conversion cannot be performed. +; http://php.net/mbstring.http-output +;mbstring.http_output = + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; "auto" detect order is changed according to mbstring.language +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +; Default: Off +;mbstring.strict_detection = On + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; This directive specifies maximum stack depth for mbstring regular expressions. It is similar +; to the pcre.recursion_limit for PCRE. +; Default: 100000 +;mbstring.regex_stack_limit=100000 + +; This directive specifies maximum retry count for mbstring regular expressions. It is similar +; to the pcre.backtrack_limit for PCRE. +; Default: 1000000 +;mbstring.regex_retry_limit=1000000 + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 1 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir + +; RPM note : cache directory must be owned by process owner +; for mod_php, see /etc/httpd/conf.d/php.conf +; for php-fpm, see /etc/php-fpm.d/*conf +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[dba] +;dba.default_handler= + +[opcache] +; see /etc/php.d/10-opcache.ini + +[curl] +; A default value for the CURLOPT_CAINFO option. This is required to be an +; absolute path. +;curl.cainfo = + +[openssl] +; The location of a Certificate Authority (CA) file on the local filesystem +; to use when verifying the identity of SSL/TLS peers. Most users should +; not specify a value for this directive as PHP will attempt to use the +; OS-managed cert stores in its absence. If specified, this value may still +; be overridden on a per-stream basis via the "cafile" SSL stream context +; option. +;openssl.cafile= + +; If openssl.cafile is not specified or if the CA file is not found, the +; directory pointed to by openssl.capath is searched for a suitable +; certificate. This value must be a correctly hashed certificate directory. +; Most users should not specify a value for this directive as PHP will +; attempt to use the OS-managed cert stores in its absence. If specified, +; this value may still be overridden on a per-stream basis via the "capath" +; SSL stream context option. +;openssl.capath= + +[ffi] +; see /etc/php.d/20-ffi.ini diff --git a/php.modconf b/php.modconf new file mode 100644 index 0000000..3377f72 --- /dev/null +++ b/php.modconf @@ -0,0 +1,12 @@ +# +# PHP is an HTML-embedded scripting language which attempts to make it +# easy for developers to write dynamically generated webpages. +# + +# Cannot load both php5 and php7 modules +<IfModule !mod_php5.c> + <IfModule prefork.c> + LoadModule php7_module modules/libphp7.so + </IfModule> +</IfModule> + diff --git a/php.spec b/php.spec new file mode 100644 index 0000000..7405776 --- /dev/null +++ b/php.spec @@ -0,0 +1,1310 @@ +%global apiver 20190902 +%global zendver 20190902 +%global pdover 20170320 +%global fileinfover 1.0.5 +%global oci8ver 2.2.0 +%global zipver 1.13.0 +%global _hardened_build 1 +%global embed_version 7.4 +%global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock) + +%global oraclever 21.10 +%global oraclelib 21.1 +%ifarch aarc64 +%global oraclever 19.19 +%global oraclelib 19.1 +%endif + +%undefine _strict_symbol_defs_build +%{!?runselftest: %global runselftest 1} + +%{!?_httpd_apxs: %{expand: %%global _httpd_apxs %%{_sbindir}/apxs}} +%{!?_httpd_mmn: %{expand: %%global _httpd_mmn %%(cat %{_includedir}/httpd/.mmn 2>/dev/null || echo 0-0)}} +%{!?_httpd_confdir: %{expand: %%global _httpd_confdir %%{_sysconfdir}/httpd/conf.d}} +# /etc/httpd/conf.d with httpd < 2.4 and defined as /etc/httpd/conf.modules.d with httpd >= 2.4 +%{!?_httpd_modconfdir: %{expand: %%global _httpd_modconfdir %%{_sysconfdir}/httpd/conf.d}} +%{!?_httpd_moddir: %{expand: %%global _httpd_moddir %%{_libdir}/httpd/modules}} +%{!?_httpd_contentdir: %{expand: %%global _httpd_contentdir /var/www}} + +%global with_argon2 1 +%global with_dtrace 1 +%global with_libgd 1 +%global with_zip 0 +%global with_libzip 1 +%global with_zts 0 +%global with_firebird 0 +%global with_imap 0 +%global with_freetds 0 +%global with_sodium 1 +%global with_pspell 0 +%global with_lmdb 0 +%global with_oci8 1 +%global upver 7.4.33 + +Name: php +Version: %{upver} +Release: 1 +Summary: PHP scripting language for creating dynamic web sites +License: PHP and Zend and BSD and MIT and ASL 1.0 and NCSA LGPL-2.1+ and Apache-2.0 and Artistic-1.0-Perl +URL: http://www.php.net/ +Source0: http://www.php.net/distributions/php-%{upver}%{?rcver}.tar.xz +Source1: php.conf +Source2: php.ini +Source3: macros.php +Source4: php-fpm.conf +Source5: php-fpm-www.conf +Source6: php-fpm.service +Source7: php-fpm.logrotate +Source9: php.modconf +Source10: php.ztsmodconf +Source11: php.conf2 +Source12: php-fpm.wants +Source13: nginx-fpm.conf +Source14: nginx-php.conf +# Configuration files for some extensions +Source50: 10-opcache.ini +Source51: opcache-default.blacklist +Source52: 20-oci8.ini +Source53: 20-ffi.ini + +# Build fixes +Patch1: php-7.4.0-httpd.patch +Patch5: php-7.2.0-includedir.patch +Patch6: php-7.4.0-embed.patch +Patch8: php-7.2.0-libdb.patch +Patch9: php-7.0.7-curl.patch + +# Functional changes +Patch42: php-7.3.3-systzdata-v19.patch +# See http://bugs.php.net/53436 +Patch43: php-7.4.0-phpize.patch +# Use -lldap_r for OpenLDAP +Patch45: php-7.4.0-ldap_r.patch +# Ignore unsupported "threads" option on password_hash +Patch46: php-7.4.20-argon2.patch +# drop "Configure command" from phpinfo output +# and add build system and provider (from 8.0) +Patch47: php-7.4.8-phpinfo.patch +# fix snmp build without DES (from 8.0) +Patch48: php-7.4.26-snmp.patch +# compatibility with OpenSSL 3.0, from 8.1 +Patch50: php-7.4.26-openssl3.patch + +# RC Patch +Patch91: php-7.2.0-oci8conf.patch + +# Upstream fixes (100+) + +# Security fixes (200+) +Patch200: php-bug81740.patch +Patch201: php-bug81744.patch +Patch202: php-bug81746.patch +Patch203: php-cve-2023-0662.patch +Patch204: php-cve-2023-3247.patch +Patch205: php-cve-2023-3823.patch +Patch206: php-cve-2023-3824.patch + +# Fixes for tests (300+) +# Factory is droped from system tzdata +Patch300: php-7.0.10-datetests.patch + +BuildRequires: bzip2-devel +BuildRequires: pkgconfig(libcurl) >= 7.15.5 +BuildRequires: httpd-devel >= 2.0.46-1 +BuildRequires: pam-devel +BuildRequires: httpd-filesystem +BuildRequires: nginx-filesystem +%if %{with_libzip} +BuildRequires: libzip-devel >= 0.11 +%endif +%if %{with_dtrace} +BuildRequires: systemtap-sdt-devel +%endif +%if %{with_argon2} +BuildRequires: libargon2-devel +%endif +%if %{with_zts} +Provides: php-zts = %{version}-%{release}, php-zts%{?_isa} = %{version}-%{release} +%endif + +Requires: httpd-mmn = %{_httpd_mmn}, php-common%{?_isa} = %{version}-%{release}, php-cli%{?_isa} = %{version}-%{release} +Provides: mod_php = %{version}-%{release}, php(httpd) +Recommends: %{name}-help = %{version}-%{release} + +%description +PHP is an HTML-embedded scripting language. PHP attempts to make it +easy for developers to write dynamically generated web pages. PHP also +offers built-in database integration for several commercial and +non-commercial database management systems, so writing a +database-enabled webpage with PHP is fairly simple. The most common +use of PHP coding is probably as a replacement for CGI scripts. +The php package contains the module (often referred to as mod_php) +which adds support for the PHP language to Apache HTTP Server. + +%package cli +Summary: Command-line interface for PHP +License: PHP and Zend and BSD and MIT and ASL 1.0 and NCSA and PostgreSQL +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-cgi = %{version}-%{release}, php-cgi%{?_isa} = %{version}-%{release}, php-pcntl, php-pcntl%{?_isa} +Provides: php-readline, php-readline%{?_isa} + +%description cli +The php-cli package contains the command-line interface +executing PHP scripts, /usr/bin/php, and the CGI interface. + +%package dbg +Summary: The interactive PHP debugger +Requires: php-common%{?_isa} = %{version}-%{release} + +%description dbg +The php-dbg package contains the interactive PHP debugger. + +%package fpm +Summary: PHP FastCGI Process Manager +BuildRequires: libacl-devel +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: systemd-devel +%{?systemd_requires} +Requires(pre): httpd-filesystem +Requires: httpd-filesystem >= 2.4.10, nginx-filesystem +Provides: php(httpd) + +%description fpm +PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI +implementation with some additional features useful for sites of +any size, especially busier sites. + +%package common +Summary: Common files for PHP +License: PHP and BSD +Provides: php(api) = %{apiver}-%{__isa_bits}, php(zend-abi) = %{zendver}-%{__isa_bits} +Provides: php(language) = %{version}, php(language)%{?_isa} = %{version}, php-bz2, php-bz2%{?_isa} +Provides: php-calendar, php-calendar%{?_isa}, php-core = %{version}, php-core%{?_isa} = %{version} +Provides: php-ctype, php-ctype%{?_isa}, php-curl, php-curl%{?_isa}, php-date, php-date%{?_isa} +Provides: bundled(timelib), php-exif, php-exif%{?_isa}, php-fileinfo, php-fileinfo%{?_isa}, bundled(libmagic) = 5.29 +Provides: php-filter, php-filter%{?_isa}, php-ftp, php-ftp%{?_isa}, php-gettext, php-gettext%{?_isa} +Provides: php-hash, php-hash%{?_isa}, php-mhash = %{version}, php-mhash%{?_isa} = %{version}, php-zlib, php-zlib%{?_isa} +Provides: php-iconv, php-iconv%{?_isa}, php-libxml, php-libxml%{?_isa}, php-openssl, php-openssl%{?_isa} +Provides: php-phar, php-phar%{?_isa}, php-pcre, php-pcre%{?_isa}, php-reflection, php-reflection%{?_isa} +Provides: php-session, php-session%{?_isa}, php-sockets, php-sockets%{?_isa}, php-spl, php-spl%{?_isa} +Provides: php-standard = %{version}, php-standard%{?_isa} = %{version}, php-tokenizer, php-tokenizer%{?_isa} +%if %{with_zip} +Provides: php-zip, php-zip%{?_isa} +Obsoletes: php-pecl-zip < 1.11 +%endif + +%description common +The php-common package contains files used by both the php +package and the php-cli package. + +%package devel +Summary: Files needed for building PHP extensions +Requires: php-cli%{?_isa} = %{version}-%{release}, autoconf, automake, gcc, gcc-c++, libtool, pcre-devel%{?_isa} +Obsoletes: php-pecl-json-devel < %{version}, php-pecl-jsonc-devel < %{version} +%if %{with_zts} +Provides: php-zts-devel = %{version}-%{release}, php-zts-devel%{?_isa} = %{version}-%{release} +%endif + +%description devel +The php-devel package contains the files needed for building PHP +extensions. If you need to compile your own PHP extensions, you will +need to install this package. + +%package opcache +Summary: The Zend OPcache +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-pecl-zendopcache = %{version}, php-pecl-zendopcache%{?_isa} = %{version}, php-pecl(opcache) = %{version} +Provides: php-pecl(opcache)%{?_isa} = %{version} + +%description opcache +The Zend OPcache provides faster PHP execution through opcode caching and +optimization. It improves PHP performance by storing precompiled script +bytecode in the shared memory. This eliminates the stages of reading code from +the disk and compiling it on future access. In addition, it applies a few +bytecode optimization patterns that make code execution faster. + +%if %{with_imap} +%package imap +Summary: A module for PHP applications that use IMAP +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: krb5-devel, openssl-devel, libc-client-devel + +%description imap +The php-imap module will add IMAP (Internet Message Access Protocol) +support to PHP. IMAP is a protocol for retrieving and uploading e-mail +messages on mail servers. PHP is an HTML-embedded scripting language. +%endif + +%package ldap +Summary: A module for PHP applications that use LDAP +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: cyrus-sasl-devel, openldap-devel, openssl-devel + +%description ldap +The php-ldap adds Lightweight Directory Access Protocol (LDAP) +support to PHP. LDAP is a set of protocols for accessing directory +services over the Internet. PHP is an HTML-embedded scripting +language. + +%package pdo +Summary: A database access abstraction module for PHP applications +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-pdo-abi = %{pdover}-%{__isa_bits}, php(pdo-abi) = %{pdover}-%{__isa_bits}, php-sqlite3, php-sqlite3%{?_isa} +Provides: php-pdo_sqlite, php-pdo_sqlite%{?_isa} + +%description pdo +The php-pdo package contains a dynamic shared object that will add +a database access abstraction layer to PHP. This module provides +a common interface for accessing MySQL, PostgreSQL or other +databases. + +%package mysqlnd +Summary: A module for PHP applications that use MySQL databases +License: PHP +Requires: php-pdo%{?_isa} = %{version}-%{release} +Provides: php_database, php-mysqli = %{version}-%{release}, php-mysqli%{?_isa} = %{version}-%{release},php-pdo_mysql +Provides: php-pdo_mysql%{?_isa} + +%description mysqlnd +The php-mysqlnd package contains a dynamic shared object that will add +MySQL database support to PHP. MySQL is an object-relational database +management system. PHP is an HTML-embeddable scripting language. If +you need MySQL support for PHP applications, you will need to install +this package and the php package. +This package use the MySQL Native Driver + +%package pgsql +Summary: A PostgreSQL database module for PHP +License: PHP +Requires: php-pdo%{?_isa} = %{version}-%{release} +Provides: php_database, php-pdo_pgsql, php-pdo_pgsql%{?_isa} +BuildRequires: krb5-devel, openssl-devel, postgresql-devel + +%description pgsql +The php-pgsql package add PostgreSQL database support to PHP. +PostgreSQL is an object-relational database management +system that supports almost all SQL constructs. PHP is an +HTML-embedded scripting language. If you need back-end support for +PostgreSQL, you should install this package in addition to the main +php package. + + + +%package process +Summary: Modules for PHP script using system process interfaces +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-posix, php-posix%{?_isa}, php-shmop, php-shmop%{?_isa}, php-sysvsem, php-sysvsem%{?_isa} +Provides: php-sysvshm, php-sysvshm%{?_isa}, php-sysvmsg, php-sysvmsg%{?_isa} + +%description process +The php-process package contains dynamic shared objects which add +support to PHP using system interfaces for inter-process +communication. + +%package odbc +Summary: A module for PHP applications that use ODBC databases +License: PHP +Requires: php-pdo%{?_isa} = %{version}-%{release} +Provides: php_database, php-pdo_odbc, php-pdo_odbc%{?_isa} +BuildRequires: unixODBC-devel + +%description odbc +The php-odbc package contains a dynamic shared object that will add +database support through ODBC to PHP. ODBC is an open specification +which provides a consistent API for developers to use for accessing +data sources (which are often, but not always, databases). PHP is an +HTML-embeddable scripting language. If you need ODBC support for PHP +applications, you will need to install this package and the php +package. + +%package soap +Summary: A module for PHP applications that use the SOAP protocol +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: libxml2-devel + +%description soap +The php-soap package contains a dynamic shared object that will add +support to PHP for using the SOAP web services protocol. + +%if %{with_firebird} +%package interbase +Summary: A module for PHP applications that use Interbase/Firebird databases +License: PHP +BuildRequires: firebird-devel +Requires: php-pdo%{?_isa} = %{version}-%{release} +Provides: php_database, php-firebird, php-firebird%{?_isa}, php-pdo_firebird, php-pdo_firebird%{?_isa} + +%description interbase +The php-interbase package contains a dynamic shared object that will add +database support through Interbase/Firebird to PHP. +InterBase is the name of the closed-source variant of this RDBMS that was +developed by Borland/Inprise. +Firebird is a commercially independent project of C and C++ programmers, +technical advisors and supporters developing and enhancing a multi-platform +relational database management system based on the source code released by +Inprise Corp (now known as Borland Software Corp) under the InterBase Public +License. +%endif + +%if %{with_oci8} +%package oci8 +Summary: A module for PHP applications that use OCI8 databases +Group: Development/Languages +# All files licensed under PHP version 3.01 +License: PHP +BuildRequires: oracle-instantclient-devel >= %{oraclever} +Requires: php-pdo%{?_isa} = %{version}-%{release} +Provides: php_database +Provides: php-pdo_oci +Provides: php-pdo_oci%{?_isa} +Obsoletes: php-pecl-oci8 <= %{oci8ver} +Conflicts: php-pecl-oci8 > %{oci8ver} +Provides: php-pecl(oci8) = %{oci8ver} +Provides: php-pecl(oci8)%{?_isa} = %{oci8ver} +# Should requires libclntsh.so.18.3, but it's not provided by Oracle RPM. +AutoReq: 0 + +%description oci8 +The php-oci8 packages provides the OCI8 extension version %{oci8ver} +and the PDO driver to access Oracle Database. + +The extension is linked with Oracle client libraries %{oraclever} +(Oracle Instant Client). For details, see Oracle's note +"Oracle Client / Server Interoperability Support" (ID 207303.1). + +You must install libclntsh.so.%{oraclelib} to use this package, provided +in the database installation, or in the free Oracle Instant Client +available from Oracle. + +Notice: +- php-oci8 provides oci8 and pdo_oci extensions from php sources. +- php-pecl-oci8 only provides oci8 extension. + +Documentation is at http://php.net/oci8 and http://php.net/pdo_oci +%endif + +%package snmp +Summary: A module for PHP applications that query SNMP-managed devices +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release}, net-snmp +BuildRequires: net-snmp-devel + +%description snmp +The php-snmp package contains a dynamic shared object that will add +support for querying SNMP devices to PHP. PHP is an HTML-embeddable +scripting language. If you need SNMP support for PHP applications, you +will need to install this package and the php package. + +%package xml +Summary: A module for PHP applications which use XML +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-dom, php-dom%{?_isa}, php-domxml, php-domxml%{?_isa}, php-simplexml, php-simplexml%{?_isa} +Provides: php-wddx, php-wddx%{?_isa}, php-xmlreader, php-xmlreader%{?_isa}, php-xmlwriter, php-xmlwriter%{?_isa} +Provides: php-xsl, php-xsl%{?_isa} +BuildRequires: libxslt-devel >= 1.0.18-1, libxml2-devel >= 2.4.14-1 + +%description xml +The php-xml package contains dynamic shared objects which add support +to PHP for manipulating XML documents using the DOM tree, +and performing XSL transformations on XML documents. + +%package xmlrpc +Summary: A module for PHP applications which use the XML-RPC protocol +License: PHP and BSD +Requires: php-xml%{?_isa} = %{version}-%{release} + +%description xmlrpc +The php-xmlrpc package contains a dynamic shared object that will add +support for the XML-RPC protocol to PHP. + +%package mbstring +Summary: A module for PHP applications which need multi-byte string handling +License: PHP and LGPLv2 and OpenLDAP +BuildRequires: oniguruma-devel +Provides: bundled(libmbfl) = 1.3.2 +Requires: php-common%{?_isa} = %{version}-%{release} + +%description mbstring +The php-mbstring package contains a dynamic shared object that will add +support for multi-byte string handling to PHP. + +%package gd +Summary: A module for PHP applications for using the gd graphics library +%if %{with_libgd} +License: PHP +%else +License: PHP and BSD +%endif +Requires: php-common%{?_isa} = %{version}-%{release} +%if %{with_libgd} +BuildRequires: gd-devel >= 2.1.0 +%else +BuildRequires: libjpeg-devel, libpng-devel, freetype-devel, libXpm-devel, libwebp-devel +Provides: bundled(gd) = 2.0.35 +%endif + +%description gd +The php-gd package contains a dynamic shared object that will add +support for using the gd graphics library to PHP. + +%package bcmath +Summary: A module for PHP applications for using the bcmath library +License: PHP and LGPLv2+ +Requires: php-common%{?_isa} = %{version}-%{release} + +%description bcmath +The php-bcmath package contains a dynamic shared object that will add +support for using the bcmath library to PHP. + +%package gmp +Summary: A module for PHP applications for using the GNU MP library +License: PHP +BuildRequires: gmp-devel +Requires: php-common%{?_isa} = %{version}-%{release} + +%description gmp +These functions allow you to work with arbitrary-length integers +using the GNU MP library. + +%package dba +Summary: A database abstraction layer module for PHP applications +License: PHP +BuildRequires: libdb-devel, tokyocabinet-devel +%if %{with_lmdb} +BuildRequires: lmdb-devel +%endif +Requires: php-common%{?_isa} = %{version}-%{release} + +%description dba +The php-dba package contains a dynamic shared object that will add +support for using the DBA database abstraction layer to PHP. + +%package tidy +Summary: Standard PHP module provides tidy library support +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: libtidy-devel + +%description tidy +The php-tidy package contains a dynamic shared object that will add +support for using the tidy library to PHP. + +%if %{with_freetds} +%package pdo-dblib +Summary: PDO driver Microsoft SQL Server and Sybase databases +License: PHP +Requires: php-pdo%{?_isa} = %{version}-%{release} +BuildRequires: freetds-devel +Provides: php-pdo_dblib, php-pdo_dblib%{?_isa} + +%description pdo-dblib +The php-pdo-dblib package contains a dynamic shared object +that implements the PHP Data Objects (PDO) interface to enable access from +PHP to Microsoft SQL Server and Sybase databases through the FreeTDS libary. +%endif + +%package embedded +Summary: PHP library for embedding in applications +Requires: php-common%{?_isa} = %{version}-%{release} +Provides: php-embedded-devel = %{version}-%{release}, php-embedded-devel%{?_isa} = %{version}-%{release} + +%description embedded +The php-embedded package contains a library which can be embedded +into applications to provide PHP scripting language support. + +%if %{with_pspell} +%package pspell +Summary: A module for PHP applications for using pspell interfaces +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: aspell-devel >= 0.50.0 + +%description pspell +The php-pspell package contains a dynamic shared object that will add +support for using the pspell library to PHP. +%endif + +%package recode +Summary: A module for PHP applications for using the recode library +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: recode-devel + +%description recode +The php-recode package contains a dynamic shared object that will add +support for using the recode library to PHP. + +%package intl +Summary: Internationalization extension for PHP applications +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: libicu-devel >= 4.0 + +%description intl +The php-intl package contains a dynamic shared object that will add +support for using the ICU library to PHP. + +%package enchant +Summary: Enchant spelling extension for PHP applications +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +BuildRequires: enchant-devel >= 1.2.4 + +%description enchant +The php-enchant package contains a dynamic shared object that will add +support for using the enchant library to PHP. + +%package json +Summary: JavaScript Object Notation extension for PHP +License: PHP +Requires: php-common%{?_isa} = %{version}-%{release} +Obsoletes: php-pecl-json < %{version} +Obsoletes: php-pecl-jsonc < %{version} +Provides: php-pecl(json) = %{version}, php-pecl(json)%{?_isa} = %{version}, php-pecl-json = %{version} +Provides: php-pecl-json%{?_isa} = %{version} + +%description json +The php-json package provides an extension that will add +support for JavaScript Object Notation (JSON) to PHP. + +%if %{with_sodium} +%package sodium +Summary: Wrapper for the Sodium cryptographic library +License: PHP +BuildRequires: pkgconfig(libsodium) >= 1.0.9 + +Requires: php-common%{?_isa} = %{version}-%{release} +Obsoletes: php-pecl-libsodium2 < 3 +Provides: php-pecl(libsodium) = %{version}, php-pecl(libsodium)%{?_isa} = %{version} + +%description sodium +The php-sodium package provides a simple, +low-level PHP extension for the libsodium cryptographic library. +%endif + +%package help +Summary: help + +%description help +help + +%prep +%autosetup -n php-%{upver}%{?rcver} -p1 + +cp Zend/LICENSE ZEND_LICENSE +cp TSRM/LICENSE TSRM_LICENSE +cp sapi/fpm/LICENSE fpm_LICENSE +cp ext/mbstring/libmbfl/LICENSE libmbfl_LICENSE +cp ext/fileinfo/libmagic/LICENSE libmagic_LICENSE +cp ext/bcmath/libbcmath/LICENSE libbcmath_LICENSE +cp ext/date/lib/LICENSE.rst timelib_LICENSE + +mkdir build-cgi build-apache build-embedded \ +%if %{with_zts} + build-zts build-ztscli \ +%endif + build-fpm + +rm ext/date/tests/timezone_location_get.phpt +rm ext/date/tests/timezone_version_get.phpt +rm ext/date/tests/timezone_version_get_basic1.phpt +rm ext/sockets/tests/mcast_ipv?_recv.phpt +rm Zend/tests/bug54268.phpt +rm Zend/tests/bug68412.phpt + +pver=$(sed -n '/#define PHP_VERSION /{s/.* "//;s/".*$//;p}' main/php_version.h) +if test "x${pver}" != "x%{upver}%{?rcver}"; then + : Error: Upstream PHP version is now ${pver}, expecting %{upver}%{?rcver}. + : Update the version/rcver macros and rebuild. + exit 1 +fi + +vapi=`sed -n '/#define PHP_API_VERSION/{s/.* //;p}' main/php.h` +if test "x${vapi}" != "x%{apiver}"; then + : Error: Upstream API version is now ${vapi}, expecting %{apiver}. + : Update the apiver macro and rebuild. + exit 1 +fi + +vzend=`sed -n '/#define ZEND_MODULE_API_NO/{s/^[^0-9]*//;p;}' Zend/zend_modules.h` +if test "x${vzend}" != "x%{zendver}"; then + : Error: Upstream Zend ABI version is now ${vzend}, expecting %{zendver}. + : Update the zendver macro and rebuild. + exit 1 +fi + +vpdo=`sed -n '/#define PDO_DRIVER_API/{s/.*[ ]//;p}' ext/pdo/php_pdo_driver.h` +if test "x${vpdo}" != "x%{pdover}"; then + : Error: Upstream PDO ABI version is now ${vpdo}, expecting %{pdover}. + : Update the pdover macro and rebuild. + exit 1 +fi + +# Check for some extension version +ver=$(sed -n '/#define PHP_OCI8_VERSION /{s/.* "//;s/".*$//;p}' ext/oci8/php_oci8.h) +if test "$ver" != "%{oci8ver}"; then + : Error: Upstream OCI8 version is now ${ver}, expecting %{oci8ver}. + : Update the oci8ver macro and rebuild. + exit 1 +fi + +%if %{with_zip} +ver=$(sed -n '/#define PHP_ZIP_VERSION /{s/.* "//;s/".*$//;p}' ext/zip/php_zip.h) +if test "$ver" != "%{zipver}"; then + : Error: Upstream ZIP version is now ${ver}, expecting %{zipver}. + : Update the %{zipver} macro and rebuild. + exit 1 +fi +%endif + +rm -f TSRM/tsrm_win32.h TSRM/tsrm_config.w32.h Zend/zend_config.w32.h ext/mysqlnd/config-win.h \ + ext/standard/winver.h main/win32_internal_function_disabled.h main/win95nt.h + +find . -name \*.[ch] -exec chmod 644 {} \; +chmod 644 README.* + +cp %{SOURCE50} 10-opcache.ini + +%ifarch x86_64 +sed -e '/opcache.huge_code_pages/s/0/1/' -i 10-opcache.ini +%endif + +%build +export SOURCE_DATE_EPOCH=$(date +%s -r NEWS) + +cat `aclocal --print-ac-dir`/{libtool,ltoptions,ltsugar,ltversion,lt~obsolete}.m4 >>aclocal.m4 + +libtoolize --force --copy +cat `aclocal --print-ac-dir`/{libtool,ltoptions,ltsugar,ltversion,lt~obsolete}.m4 >build/libtool.m4 + +touch configure.ac +./buildconf --force + +CFLAGS=$(echo $RPM_OPT_FLAGS -fno-strict-aliasing -Wno-pointer-sign | sed 's/-mstackrealign//') +export CFLAGS + +EXTENSION_DIR=%{_libdir}/php/modules; export EXTENSION_DIR + +PEAR_INSTALLDIR=%{_datadir}/pear; export PEAR_INSTALLDIR + +build() { +mkdir Zend && cp ../Zend/zend_{language,ini}_{parser,scanner}.[ch] Zend + +ln -sf ../configure +%configure \ + --cache-file=../config.cache --with-libdir=%{_lib} --with-config-file-path=%{_sysconfdir} \ + --with-config-file-scan-dir=%{_sysconfdir}/php.d --disable-debug --with-pic --disable-rpath \ + --without-pear --with-freetype-dir=%{_prefix} --with-png-dir=%{_prefix} \ + --with-xpm-dir=%{_prefix} --without-gdbm --with-jpeg-dir=%{_prefix} --with-openssl --with-system-ciphers \ + --with-pcre-regex=%{_prefix} --with-zlib --with-layout=GNU --with-kerberos --with-libxml-dir=%{_prefix} \ + --with-system-tzdata --with-mhash \ +%if %{with_argon2} + --with-password-argon2 \ +%endif +%if %{with_dtrace} + --enable-dtrace \ +%endif + $* +if test $? != 0; then + tail -500 config.log + : configure failed + exit 1 +fi + +make %{?_smp_mflags} +} + +pushd build-cgi + +build --libdir=%{_libdir}/php --enable-pcntl --enable-opcache --enable-opcache-file --enable-phpdbg \ +%if %{with_imap} + --with-imap=shared --with-imap-ssl \ +%endif + --enable-mbstring=shared --with-onig=%{_prefix} --enable-mbregex \ +%if %{with_libgd} + --with-gd=shared,%{_prefix} \ +%else + --with-gd=shared \ +%endif + --with-gmp=shared --enable-calendar=shared --enable-bcmath=shared --with-bz2=shared --enable-ctype=shared \ + --enable-dba=shared --with-db4=%{_prefix} --with-tcadb=%{_prefix} \ +%if %{with_lmdb} + --with-lmdb=%{_prefix} \ +%endif + --enable-exif=shared --enable-ftp=shared --with-gettext=shared --with-iconv=shared --enable-sockets=shared \ + --enable-tokenizer=shared --with-xmlrpc=shared --with-ldap=shared --with-ldap-sasl --enable-mysqlnd=shared \ + --with-mysqli=shared,mysqlnd --with-mysql-sock=%{mysql_sock} \ +%if %{with_oci8} +%ifarch x86_64 aarch64 + --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ + --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ +%endif +%endif +%if %{with_firebird} + --with-interbase=shared --with-pdo-firebird=shared \ +%endif + --enable-dom=shared --with-pgsql=shared --enable-simplexml=shared --enable-xml=shared --enable-wddx=shared \ + --with-snmp=shared,%{_prefix} --enable-soap=shared --with-xsl=shared,%{_prefix} --enable-xmlreader=shared \ + --enable-xmlwriter=shared --with-curl=shared,%{_prefix} --enable-pdo=shared \ + --with-pdo-odbc=shared,unixODBC,%{_prefix} --with-pdo-mysql=shared,mysqlnd --with-pdo-pgsql=shared,%{_prefix} \ + --with-pdo-sqlite=shared,%{_prefix} \ +%if %{with_freetds} + --with-pdo-dblib=shared,%{_prefix} \ +%endif + --with-sqlite3=shared,%{_prefix} --enable-json=shared \ +%if %{with_zip} + --enable-zip=shared \ +%if %{with_libzip} + --with-libzip \ +%endif +%endif + --without-readline --with-libedit \ +%if %{with_pspell} + --with-pspell=shared \ +%endif + --enable-phar=shared --with-tidy=shared,%{_prefix} --enable-sysvmsg=shared --enable-sysvshm=shared \ + --enable-sysvsem=shared --enable-shmop=shared --enable-posix=shared --with-unixODBC=shared,%{_prefix} \ + --enable-fileinfo=shared \ +%if %{with_sodium} + --with-sodium=shared \ +%else + --without-sodium \ +%endif + --enable-intl=shared --with-icu-dir=%{_prefix} --with-enchant=shared,%{_prefix} --with-recode=shared,%{_prefix} +popd + +without_shared="--without-gd --disable-dom --disable-dba --without-unixODBC --disable-opcache --disable-json \ + --disable-xmlreader --disable-xmlwriter --without-sodium --without-sqlite3 --disable-phar --disable-fileinfo \ + --without-pspell --disable-wddx --without-curl --disable-posix --disable-xml --disable-simplexml --disable-exif \ + --without-gettext --without-iconv --disable-ftp --without-bz2 --disable-ctype --disable-shmop --disable-sockets \ + --disable-tokenizer --disable-sysvmsg --disable-sysvshm --disable-sysvsem" + +pushd build-apache +build --with-apxs2=%{_httpd_apxs} --libdir=%{_libdir}/php --without-mysqli --disable-pdo \ + ${without_shared} +popd + +pushd build-fpm +build --enable-fpm --with-fpm-acl --with-fpm-systemd --libdir=%{_libdir}/php --without-mysqli --disable-pdo \ + ${without_shared} +popd + +pushd build-embedded +build --enable-embed --without-mysqli --disable-pdo \ + ${without_shared} +popd + +%if %{with_zts} +pushd build-ztscli + +EXTENSION_DIR=%{_libdir}/php-zts/modules +build --includedir=%{_includedir}/php-zts --libdir=%{_libdir}/php-zts --enable-maintainer-zts --program-prefix=zts- \ + --disable-cgi --with-config-file-scan-dir=%{_sysconfdir}/php-zts.d --enable-pcntl --enable-opcache \ + --enable-opcache-file \ +%if %{with_imap} + --with-imap=shared --with-imap-ssl \ +%endif + --enable-mbstring=shared --with-onig=%{_prefix} --enable-mbregex \ +%if %{with_libgd} + --with-gd=shared,%{_prefix} \ +%else + --with-gd=shared \ +%endif + --with-gmp=shared --enable-calendar=shared --enable-bcmath=shared --with-bz2=shared --enable-ctype=shared \ + --enable-dba=shared --with-db4=%{_prefix} --with-tcadb=%{_prefix} \ +%if %{with_lmdb} + --with-lmdb=%{_prefix} \ +%endif + --with-gettext=shared --with-iconv=shared --enable-sockets=shared --enable-tokenizer=shared --enable-exif=shared \ + --enable-ftp=shared --with-xmlrpc=shared --with-ldap=shared --with-ldap-sasl --enable-mysqlnd=shared \ + --with-mysqli=shared,mysqlnd --with-mysql-sock=%{mysql_sock} --enable-mysqlnd-threading \ +%if %{with_oci8} +%ifarch x86_64 aarch64 + --with-oci8=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ + --with-pdo-oci=shared,instantclient,%{_libdir}/oracle/%{oraclever}/client64/lib,%{oraclever} \ +%endif +%endif +%if %{with_firebird} + --with-interbase=shared --with-pdo-firebird=shared \ +%endif + --enable-dom=shared --with-pgsql=shared --enable-simplexml=shared --enable-xml=shared --enable-wddx=shared \ + --with-snmp=shared,%{_prefix} --enable-soap=shared --with-xsl=shared,%{_prefix} --enable-xmlreader=shared \ + --enable-xmlwriter=shared --with-curl=shared,%{_prefix} --enable-pdo=shared \ + --with-pdo-odbc=shared,unixODBC,%{_prefix} --with-pdo-mysql=shared,mysqlnd --with-pdo-pgsql=shared,%{_prefix} \ + --with-pdo-sqlite=shared,%{_prefix} \ +%if %{with_freetds} + --with-pdo-dblib=shared,%{_prefix} \ +%endif + --with-sqlite3=shared,%{_prefix} --enable-json=shared \ +%if %{with_zip} + --enable-zip=shared \ +%if %{with_libzip} + --with-libzip \ +%endif +%endif + --without-readline --with-libedit \ +%if %{with_pspell} + --with-pspell=shared \ +%endif + --enable-phar=shared --with-tidy=shared,%{_prefix} --enable-sysvmsg=shared --enable-sysvshm=shared \ + --enable-sysvsem=shared --enable-shmop=shared --enable-posix=shared --with-unixODBC=shared,%{_prefix} \ + --enable-fileinfo=shared \ +%if %{with_sodium} + --with-sodium=shared \ +%else + --without-sodium \ +%endif + --enable-intl=shared --with-icu-dir=%{_prefix} --with-enchant=shared,%{_prefix} --with-recode=shared,%{_prefix} +popd + +pushd build-zts +build --with-apxs2=%{_httpd_apxs} --includedir=%{_includedir}/php-zts --libdir=%{_libdir}/php-zts \ + --enable-maintainer-zts --with-config-file-scan-dir=%{_sysconfdir}/php-zts.d --without-mysqli --disable-pdo \ + ${without_shared} +popd +%endif + +%check +%if %runselftest +cd build-apache + +export NO_INTERACTION=1 REPORT_EXIT_STATUS=1 MALLOC_CHECK_=2 +export SKIP_ONLINE_TESTS=1 +export SKIP_IO_CAPTURE_TESTS=1 +unset TZ LANG LC_ALL +if ! make test; then + set +x + for f in $(find .. -name \*.diff -type f -print); do + if ! grep -q XFAIL "${f/.diff/.phpt}" + then + echo "TEST FAILURE: $f --" + cat "$f" + echo -e "\n-- $f result ends." + fi + done + set -x + #exit 1 +fi +unset NO_INTERACTION REPORT_EXIT_STATUS MALLOC_CHECK_ +%endif + +%install +%if %{with_zts} +make -C build-ztscli install \ + INSTALL_ROOT=$RPM_BUILD_ROOT +%endif + +make -C build-embedded install-sapi install-headers \ + INSTALL_ROOT=$RPM_BUILD_ROOT + +make -C build-fpm install-fpm \ + INSTALL_ROOT=$RPM_BUILD_ROOT + +make -C build-cgi install \ + INSTALL_ROOT=$RPM_BUILD_ROOT + +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/ +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/php.ini +install -m 755 -d $RPM_BUILD_ROOT%{_datadir}/php/prload +install -m 755 -d $RPM_BUILD_ROOT%{_httpd_moddir} +install -m 755 build-apache/libs/libphp7.so $RPM_BUILD_ROOT%{_httpd_moddir} + +%if %{with_zts} +install -m 755 build-zts/libs/libphp7.so $RPM_BUILD_ROOT%{_httpd_moddir}/libphp7-zts.so +%endif + +install -D -m 644 %{SOURCE9} $RPM_BUILD_ROOT%{_httpd_modconfdir}/15-php.conf +%if %{with_zts} +cat %{SOURCE10} >>$RPM_BUILD_ROOT%{_httpd_modconfdir}/15-php.conf +%endif +install -D -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_httpd_confdir}/php.conf + +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/php.d +%if %{with_zts} +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/php-zts.d +%endif +install -m 755 -d $RPM_BUILD_ROOT%{_sharedstatedir}/php +install -m 755 -d $RPM_BUILD_ROOT%{_sharedstatedir}/php/peclxml +install -m 700 -d $RPM_BUILD_ROOT%{_sharedstatedir}/php/session +install -m 700 -d $RPM_BUILD_ROOT%{_sharedstatedir}/php/wsdlcache +install -m 700 -d $RPM_BUILD_ROOT%{_sharedstatedir}/php/opcache +install -m 755 -d $RPM_BUILD_ROOT%{_docdir}/pecl +install -m 755 -d $RPM_BUILD_ROOT%{_datadir}/tests/pecl +install -m 755 -d $RPM_BUILD_ROOT%{_localstatedir}/log/php-fpm +install -m 755 -d $RPM_BUILD_ROOT/run/php-fpm +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.d +install -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.conf +install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.d/www.conf +mv $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.conf.default . +mv $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.d/www.conf.default . +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/php-fpm.service.d +install -Dm 644 %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}/php-fpm.service +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/httpd.service.d/php-fpm.conf +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/nginx.service.d/php-fpm.conf +install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/php-fpm +install -D -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_sysconfdir}/nginx/conf.d/php-fpm.conf +install -D -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_sysconfdir}/nginx/default.d/php.conf + +for mod in pgsql odbc ldap snmp xmlrpc \ +%if %{with_imap} + imap \ +%endif + json \ + mysqlnd mysqli pdo_mysql \ + mbstring gd dom xsl soap bcmath dba xmlreader xmlwriter \ + simplexml bz2 calendar ctype exif ftp gettext gmp iconv \ + sockets tokenizer opcache \ + pdo pdo_pgsql pdo_odbc pdo_sqlite \ +%if %{with_oci8} + oci8 pdo_oci \ +%endif +%if %{with_zip} + zip \ +%endif +%if %{with_firebird} + interbase pdo_firebird \ +%endif + sqlite3 \ + enchant phar fileinfo intl \ + tidy \ +%if %{with_freetds} + pdo_dblib \ +%endif +%if %{with_pspell} + pspell \ +%endif + curl wddx \ +%if %{with_sodium} + sodium \ +%endif + posix shmop sysvshm sysvsem sysvmsg recode xml \ + ; do + case $mod in + opcache) + ini=10-${mod}.ini;; + pdo_*|mysqli|wddx|xmlreader|xmlrpc) + ini=30-${mod}.ini;; + *) + ini=20-${mod}.ini;; + esac + if [ -f ${ini} ]; then + cp -p ${ini} $RPM_BUILD_ROOT%{_sysconfdir}/php.d/${ini} +%if %{with_zts} + cp -p ${ini} $RPM_BUILD_ROOT%{_sysconfdir}/php-zts.d/${ini} +%endif + else + cat > $RPM_BUILD_ROOT%{_sysconfdir}/php.d/${ini} <<EOF +; Enable ${mod} extension module +extension=${mod} +EOF +%if %{with_zts} + cat > $RPM_BUILD_ROOT%{_sysconfdir}/php-zts.d/${ini} <<EOF +; Enable ${mod} extension module +extension=${mod} +EOF +%endif + fi + cat > files.${mod} <<EOF +%{_libdir}/php/modules/${mod}.so +%config(noreplace) %{_sysconfdir}/php.d/${ini} +%if %{with_zts} +%{_libdir}/php-zts/modules/${mod}.so +%config(noreplace) %{_sysconfdir}/php-zts.d/${ini} +%endif +EOF +done + +cat files.dom files.xsl files.xml{reader,writer} files.wddx \ + files.simplexml >> files.xml + +cat files.mysqli \ + files.pdo_mysql \ + >> files.mysqlnd + +cat files.pdo_pgsql >> files.pgsql +cat files.pdo_odbc >> files.odbc +%if %{with_oci8} +cat files.pdo_oci >> files.oci8 +%endif +%if %{with_firebird} +cat files.pdo_firebird >> files.interbase +%endif + +cat files.shmop files.sysv* files.posix > files.process +cat files.pdo_sqlite >> files.pdo +cat files.sqlite3 >> files.pdo +cat files.curl files.phar files.fileinfo \ + files.exif files.gettext files.iconv files.calendar \ + files.ftp files.bz2 files.ctype files.sockets \ + files.tokenizer > files.common +%if %{with_zip} +cat files.zip >> files.common +%endif + +install -m 644 %{SOURCE51} $RPM_BUILD_ROOT%{_sysconfdir}/php.d/opcache-default.blacklist +%if %{with_zts} +install -m 644 %{SOURCE51} $RPM_BUILD_ROOT%{_sysconfdir}/php-zts.d/opcache-default.blacklist +sed -e '/blacklist_filename/s/php.d/php-zts.d/' \ + -i $RPM_BUILD_ROOT%{_sysconfdir}/php-zts.d/10-opcache.ini +%endif + +sed -e "s/@PHP_APIVER@/%{apiver}-%{__isa_bits}/" \ + -e "s/@PHP_ZENDVER@/%{zendver}-%{__isa_bits}/" \ + -e "s/@PHP_PDOVER@/%{pdover}-%{__isa_bits}/" \ + -e "s/@PHP_VERSION@/%{upver}/" \ +%if ! %{with_zts} + -e "/zts/d" \ +%endif + < %{SOURCE3} > macros.php +install -m 644 -D macros.php \ + $RPM_BUILD_ROOT%{_rpmconfigdir}/macros.d/macros.php + +rm -rf $RPM_BUILD_ROOT%{_libdir}/php/modules/*.a \ + $RPM_BUILD_ROOT%{_libdir}/php-zts/modules/*.a \ + $RPM_BUILD_ROOT%{_bindir}/{phptar} \ + $RPM_BUILD_ROOT%{_datadir}/pear \ + $RPM_BUILD_ROOT%{_libdir}/libphp7.la + +rm -f README.{Zeus,QNX,CVS-RULES} + +%post fpm +%systemd_post php-fpm.service + +%preun fpm +%systemd_preun php-fpm.service + +%transfiletriggerin fpm -- %{_sysconfdir}/php-fpm.d %{_sysconfdir}/php.d +systemctl try-restart php-fpm.service >/dev/null 2>&1 || : + +%files +%{_httpd_moddir}/libphp7.so +%if %{with_zts} +%{_httpd_moddir}/libphp7-zts.so +%endif +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/session +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/wsdlcache +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/opcache +%config(noreplace) %{_httpd_confdir}/php.conf +%config(noreplace) %{_httpd_modconfdir}/15-php.conf +%{_httpd_contentdir}/icons/php.gif + +%files common -f files.common +%license LICENSE TSRM_LICENSE +%license libmagic_LICENSE +%license phar_LICENSE +%license timelib_LICENSE +%config(noreplace) %{_sysconfdir}/php.ini +%dir %{_sysconfdir}/php.d +%dir %{_libdir}/php +%dir %{_libdir}/php/modules +%if %{with_zts} +%dir %{_sysconfdir}/php-zts.d +%dir %{_libdir}/php-zts +%dir %{_libdir}/php-zts/modules +%endif +%dir %{_sharedstatedir}/php +%dir %{_sharedstatedir}/php/peclxml +%dir %{_datadir}/php +%dir %{_docdir}/pecl +%dir %{_datadir}/tests +%dir %{_datadir}/tests/pecl + +%files cli +%{_bindir}/php +%if %{with_zts} +%{_bindir}/zts-php +%endif +%{_bindir}/php-cgi +%{_bindir}/phar.phar +%{_bindir}/phar +%{_bindir}/phpize + +%files dbg +%{_bindir}/phpdbg +%if %{with_zts} +%{_bindir}/zts-phpdbg +%endif + +%files fpm +%license fpm_LICENSE +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/session +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/wsdlcache +%attr(0770,root,apache) %dir %{_sharedstatedir}/php/opcache +%config(noreplace) %{_httpd_confdir}/php.conf +%config(noreplace) %{_sysconfdir}/php-fpm.conf +%config(noreplace) %{_sysconfdir}/php-fpm.d/www.conf +%config(noreplace) %{_sysconfdir}/logrotate.d/php-fpm +%config(noreplace) %{_sysconfdir}/nginx/conf.d/php-fpm.conf +%config(noreplace) %{_sysconfdir}/nginx/default.d/php.conf +%{_unitdir}/php-fpm.service +%{_unitdir}/httpd.service.d/php-fpm.conf +%{_unitdir}/nginx.service.d/php-fpm.conf +%{_sbindir}/php-fpm +%dir %{_sysconfdir}/systemd/system/php-fpm.service.d +%dir %{_sysconfdir}/php-fpm.d +%attr(770,apache,root) %dir %{_localstatedir}/log/php-fpm +%dir %ghost /run/php-fpm +%dir %{_datadir}/fpm +%{_datadir}/fpm/status.html + +%files devel +%{_bindir}/php-config +%{_includedir}/php +%{_libdir}/php/build +%if %{with_zts} +%{_bindir}/zts-php-config +%{_bindir}/zts-phpize +%{_includedir}/php-zts +%{_libdir}/php-zts/build +%endif +%{_rpmconfigdir}/macros.d/macros.php + +%files embedded +%{_libdir}/libphp7.so +%{_libdir}/libphp7-%{embed_version}.so + +%files pgsql -f files.pgsql +%files odbc -f files.odbc +%if %{with_imap} +%files imap -f files.imap +%endif +%files ldap -f files.ldap +%files snmp -f files.snmp +%files xml -f files.xml +%files xmlrpc -f files.xmlrpc +%files mbstring -f files.mbstring +%license libmbfl_LICENSE +%license ucgendat_LICENSE +%files gd -f files.gd +%if ! %{with_libgd} +%license libgd_README +%license libgd_COPYING +%endif +%files soap -f files.soap +%files bcmath -f files.bcmath +%license libbcmath_COPYING +%files gmp -f files.gmp +%files dba -f files.dba +%files pdo -f files.pdo +%files tidy -f files.tidy +%if %{with_freetds} +%files pdo-dblib -f files.pdo_dblib +%endif +%if %{with_pspell} +%files pspell -f files.pspell +%endif +%files intl -f files.intl +%files process -f files.process +%files recode -f files.recode +%if %{with_firebird} +%files interbase -f files.interbase +%endif +%files enchant -f files.enchant +%files mysqlnd -f files.mysqlnd +%files opcache -f files.opcache +%config(noreplace) %{_sysconfdir}/php.d/opcache-default.blacklist +%if %{with_zts} +%config(noreplace) %{_sysconfdir}/php-zts.d/opcache-default.blacklist +%endif +%if %{with_oci8} +%files oci8 -f files.oci8 +%endif +%files json -f files.json +%if %{with_sodium} +%files sodium -f files.sodium +%endif + +%files help +%defattr(-,root,root) +%doc CODING_STANDARDS CREDITS EXTENSIONS NEWS README* sapi/cgi/README* sapi/cli/README sapi/phpdbg/{README.md,CREDITS} +%doc php-fpm.conf.default www.conf.default php.ini-* +%{_mandir}/* + + +%changelog +* Fri Aug 18 2023 Fund Wang <fundawang@yeah.net> - 7.4.33-1 +- New version 7.4.33 + +* Sun Dec 11 2022 Funda Wang <fundawang@yeah.net> - 7.2.34-2 +- Fix php BUG#81738 / CVE-2022-37454 + +* Thu Oct 6 2022 Funda Wang <fundawang@yeah.net> - 7.2.34-1 +- New version 7.2.34 +- Sync with remi's patches + +* Sat Jun 18 2022 Hugel <gengqihu1@h-partners.com> - 7.2.10-20 +- Fix CVE-2022-31625 CVE-2022-31626 + +* Mon Feb 28 2022 wangchen <wangchen137@h-partners.com> - 7.2.10-19 +- Fix CVE-2019-11038 CVE-2019-11039 CVE-2019-11040 + +* Wed Feb 23 2022 panxiaohe <panxh.life@foxmail.com> - 7.2.10-18 +- Fix CVE-2020-7067 + +* Thu Dec 2 2021 fuanan <fuanan3@huawei.com> - 7.2.10-17 +- Fix CVE-2021-21707 + +* Thu Nov 4 2021 panxiaohe <panxiaohe@huawei.com> - 7.2.10-16 +- Fix CVE-2021-21703 + +* Tue Oct 12 2021 wangchen <wangchen137@huawei.com> - 7.2.10-15 +- Fix CVE-2021-21704 + +* Wed Sep 29 2021 fuanan <fuanan3@huawei.com> - 7.2.10-14 +- refix CVE-2020-7071 and fix CVE-2021-21705 + +* Wed Feb 3 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 7.2.10-13 +- Fix CVE-2020-7069 CVE-2020-7070 + +* Tue Feb 2 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 7.2.10-12 +- Fix CVE-2020-7060 + +* Wed Jan 20 2021 Hugel <gengqihu1@huawei.com> - 7.2.10-11 +- Fix CVE-2020-7062 CVE-2020-7071 + +* Fri Jan 15 2021 panxiaohe <panxiaohe@huawei.com> - 7.2.10-10 +- Fix CVE-2020-7059 + +* Wed Dec 16 2020 zhanghua <zhanghua40@huawei.com> - 7.2.10-9 +- fix CVE-2020-7063 + +* Sat Nov 07 2020 liuweibo <liuweibo10@huawei.com> - 7.2.10-8 +- Append help recommends to main package + +* Mon Sep 21 2020 shaoqiang kang <kangshqoaing1@huawei.com> - 7.2.10-7 +- Fix CVE-2020-7068 + +* Tue Jul 21 2020 wangyue <wangyue92@huawei.com> - 7.2.10-6 +- Type:cves +- ID:CVE-2019-11048 +- SUG:restart +- DESC:fix CVE-2019-11048 + +* Mon May 18 2020 wangchen <wangchen137@huawei.com> - 7.2.10-5 +- rebuild for php + +* Fri Apr 24 2020 openEuler Buildteam <buildteam@openeuler.org> - 7.2.10-4 +- Type:cves +- ID:CVE-2020-7064 CVE-2020-7066 +- SUG:restart +- DESC:fix CVE-2020-7064 CVE-2020-7066 + +* Mon Mar 16 2020 shijian <shijian16@huawei.com> - 7.2.10-3 +- Type:cves +- ID:CVE-2018-19518 CVE-2019-6977 +- SUG:restart +- DESC:fix CVE-2018-19518 CVE-2019-6977 + +* Thu Mar 12 2020 openEuler Buildteam <buildteam@openeuler.org> - 7.2.10-2 +- Add CVE patches + +* Fri Feb 14 2020 openEuler Buildteam <buildteam@openeuler.org> - 7.2.10-1 +- Package init diff --git a/php.ztsmodconf b/php.ztsmodconf new file mode 100644 index 0000000..8085cbd --- /dev/null +++ b/php.ztsmodconf @@ -0,0 +1,6 @@ + +<IfModule !mod_php5.c> + <IfModule !prefork.c> + LoadModule php7_module modules/libphp7-zts.so + </IfModule> +</IfModule> @@ -0,0 +1 @@ +f098632163cd47f2c1ffe2bdc6ef1ff2 php-7.4.33.tar.xz |