The debdiff
diff -Nru php-cas-1.3.8/debian/changelog php-cas-1.3.8/debian/changelog --- php-cas-1.3.8/debian/changelog 2019-12-07 20:07:56.000000000 +0000 +++ php-cas-1.3.8/debian/changelog 2024-07-11 10:16:11.000000000 +0000 @@ -1,3 +1,22 @@ +php-cas (1.3.8-1+deb11u1) bullseye-security; urgency=high + + * Security upload + * Fix CVE-2022-39369: The phpCAS library uses HTTP headers + to determine the service URL used to validate tickets. + This allows an attacker to control the host header + and use a valid ticket granted for any authorized service in the same + SSO realm (CAS server) to authenticate to the service protected by + phpCAS. Depending on the settings of the CAS server service registry in + worst case this may be any other service URL (if the allowed URLs are + configured to "^(https)://.*") or may be strictly limited to known and + authorized services in the same SSO federation if proper URL service + validation is applied. + The fix for this vulnerabilty requires an API breaking change + in php-cas and will require that software using the library be updated. + (Closes: #1023571) + + -- Bastien Roucariès <rouca@debian.org> Thu, 11 Jul 2024 10:16:11 +0000 + php-cas (1.3.8-1) unstable; urgency=medium * Bump debhelper compatibility level to 12 diff -Nru php-cas-1.3.8/debian/control php-cas-1.3.8/debian/control --- php-cas-1.3.8/debian/control 2019-12-07 20:07:56.000000000 +0000 +++ php-cas-1.3.8/debian/control 2024-07-11 10:16:11.000000000 +0000 @@ -19,7 +19,10 @@ ${phppear:Debian-Depends} Recommends: ${phppear:Debian-Recommends} Suggests: ${phppear:Debian-Suggests} -Breaks: ${phppear:Debian-Breaks} +Breaks: ${phppear:Debian-Breaks}, + fusiondirectory (<= 1.3-4+deb11u1~), + fusiondirectory-schema (<= 1.3-4+deb11u1~), + ocsinventory-reports (<= 2.8.1+dfsg1-1+deb11u1~) Description: Central Authentication Service client library in php phpCAS is an authentication library that allows PHP applications to easily authenticate users via a Central Authentication Service (CAS) server. diff -Nru php-cas-1.3.8/debian/NEWS php-cas-1.3.8/debian/NEWS --- php-cas-1.3.8/debian/NEWS 1970-01-01 00:00:00.000000000 +0000 +++ php-cas-1.3.8/debian/NEWS 2024-07-11 10:16:11.000000000 +0000 @@ -0,0 +1,44 @@ +php-cas (1.3.8-1+deb11u1) bullseye-security; urgency=medium + + * A vulnerability has been found in phpCAS, a Central Authentication + Service client library in php, which may allow an attacker to gain + access to a victim's account on a vulnerable CASified service without + victim's knowledge, when the victim visits attacker's website while + being logged in to the same CAS server. + + The fix for this vulnerabilty requires an API breaking change in php-cas + and will require that software using the library be updated. + + For bullseye, all packages in the Debian repositories which are using + php-cas have been updated, though additional manual configuration is to + be expected, as php-cas needs additional site information -- the service + base URL -- for it to function. The DLAs for the respective packages + will have additional information, as well as the package's NEWS files. + + For 3rd party software using php-cas, please be note that upstream + provided following instructions how to update this software [1]: + + phpCAS now requires an additional service base URL argument when + constructing the client class. It accepts any argument of: + + 1. A service base URL string. The service URL discovery will always use + this server name (protocol, hostname and port number) without using + any external host names. + 2. An array of service base URL strings. The service URL discovery + will check against this list before using the auto discovered base URL. + If there is no match, the first base URL in the array will be used as + the default. This option is helpful if your PHP website is accessible + through multiple domains without a canonical name, or through both + HTTP and HTTPS. + 3. A class that implements CAS_ServiceBaseUrl_Interface. If you need to + customize the base URL discovery behavior, you can pass in a class that + implements the interface. + + Constructing the client class is usually done with phpCAS::client(). + + For example, using the first possiblity: + phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context); + could become: + phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context, "https://casified-service.example.org:8080";); + + -- Bastien Roucariès <rouca@debian.org> Thu, 11 Jul 2024 10:17:22 +0000 diff -Nru php-cas-1.3.8/debian/patches/CVE-2022-39369.patch php-cas-1.3.8/debian/patches/CVE-2022-39369.patch --- php-cas-1.3.8/debian/patches/CVE-2022-39369.patch 1970-01-01 00:00:00.000000000 +0000 +++ php-cas-1.3.8/debian/patches/CVE-2022-39369.patch 2024-07-11 10:13:17.000000000 +0000 @@ -0,0 +1,967 @@ +From b759361d904a2cb2a3bcee9411fc348cfde5d163 Mon Sep 17 00:00:00 2001 +From: Phy <git@phy25.com> +Date: Mon, 31 Oct 2022 16:34:25 -0400 +Subject: [PATCH] Merge pull request from GHSA-8q72-6qq8-xv64 + +* Add ServerName classes and required service_name constructor argument + +This includes a refactoring of moving Client->_getClientUrl() method to a new class. + +Unit tests are also added and updated for the new constructor argument. + +* Add service_name argument to the static helper class and examples + +* Update docs for 1.6.0 release + +* Update versions for the 1.6.0 release + +* Rename ServerName class to ServiceBaseUrl and add protocol in allowedlist check + +* Update docs for the ServiceBaseUrl class and argument change + +* Minor typo fixes +--- + docs/ChangeLog | 31 ++- + docs/Upgrading | 34 +++ + docs/examples/config.example.php | 3 + + docs/examples/create_pgt_storage_db_table.php | 2 +- + docs/examples/example_advanced_saml11.php | 2 +- + docs/examples/example_custom_urls.php | 2 +- + docs/examples/example_gateway.php | 2 +- + docs/examples/example_hardening.php | 2 +- + docs/examples/example_html.php | 2 +- + docs/examples/example_lang.php | 2 +- + docs/examples/example_logout.php | 2 +- + .../examples/example_no_ssl_cn_validation.php | 2 +- + docs/examples/example_pgt_storage_db.php | 2 +- + docs/examples/example_pgt_storage_file.php | 2 +- + docs/examples/example_proxy_GET.php | 2 +- + docs/examples/example_proxy_POST.php | 2 +- + docs/examples/example_proxy_rebroadcast.php | 2 +- + docs/examples/example_proxy_serviceWeb.php | 2 +- + .../example_proxy_serviceWeb_chaining.php | 2 +- + docs/examples/example_renew.php | 2 +- + docs/examples/example_service.php | 2 +- + docs/examples/example_service_POST.php | 2 +- + .../examples/example_service_that_proxies.php | 2 +- + docs/examples/example_simple.php | 2 +- + source/CAS.php | 26 +- + source/CAS/Client.php | 109 ++++---- + .../ServiceBaseUrl/AllowedListDiscovery.php | 152 +++++++++++ + source/CAS/ServiceBaseUrl/Base.php | 98 +++++++ + source/CAS/ServiceBaseUrl/Interface.php | 61 +++++ + source/CAS/ServiceBaseUrl/Static.php | 69 +++++ + test/CAS/Tests/AuthenticationTest.php | 1 + + test/CAS/Tests/CallbackTest.php | 1 + + test/CAS/Tests/Cas20AttributesTest.php | 1 + + test/CAS/Tests/LogTest.php | 2 + + test/CAS/Tests/ProxyTicketValidationTest.php | 1 + + test/CAS/Tests/ServiceBaseUrlTest.php | 244 ++++++++++++++++++ + test/CAS/Tests/ServiceMailTest.php | 1 + + .../CAS/Tests/ServiceTicketValidationTest.php | 1 + + test/CAS/Tests/ServiceWebTest.php | 1 + + utils/version.properties | 2 +- + 40 files changed, 789 insertions(+), 91 deletions(-) + create mode 100644 source/CAS/ServiceBaseUrl/AllowedListDiscovery.php + create mode 100644 source/CAS/ServiceBaseUrl/Base.php + create mode 100644 source/CAS/ServiceBaseUrl/Interface.php + create mode 100644 source/CAS/ServiceBaseUrl/Static.php + create mode 100644 test/CAS/Tests/ServiceBaseUrlTest.php + +Index: php-cas/source/CAS/Client.php +=================================================================== +--- php-cas.orig/source/CAS/Client.php ++++ php-cas/source/CAS/Client.php +@@ -896,6 +896,14 @@ class CAS_Client + * @param bool $changeSessionID Allow phpCAS to change the session_id + * (Single Sign Out/handleLogoutRequests + * is based on that change) ++ * @param string|string[]|CAS_ServiceBaseUrl_Interface ++ * $service_base_url the base URL (protocol, host and the ++ * optional port) of the CAS client; pass ++ * in an array to use auto discovery with ++ * an allowlist; pass in ++ * CAS_ServiceBaseUrl_Interface for custom ++ * behavior. Added in 1.6.0. Similar to ++ * serverName config in other CAS clients. + * + * @return self a newly created CAS_Client object + */ +@@ -905,6 +913,7 @@ class CAS_Client + $server_hostname, + $server_port, + $server_uri, ++ $service_base_url, + $changeSessionID = true + ) { + // Argument validation +@@ -921,6 +930,8 @@ class CAS_Client + if (gettype($changeSessionID) != 'boolean') + throw new CAS_TypeMismatchException($changeSessionID, '$changeSessionID', 'boolean'); + ++ $this->_setServiceBaseUrl($service_base_url); ++ + phpCAS::traceBegin(); + // true : allow to change the session_id(), false session_id won't be + // change and logout won't be handle because of that +@@ -1013,7 +1024,7 @@ class CAS_Client + + if ( $this->_isCallbackMode() ) { + //callback mode: check that phpCAS is secured +- if ( !$this->_isHttps() ) { ++ if ( !$this->getServiceBaseUrl()->isHttps() ) { + phpCAS::error( + 'CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server' + ); +@@ -2391,8 +2402,7 @@ class CAS_Client + // the URL is built when needed only + if ( empty($this->_callback_url) ) { + // remove the ticket if present in the URL +- $final_uri = 'https://'; +- $final_uri .= $this->_getClientUrl(); ++ $final_uri = $this->getServiceBaseUrl()->get(); + $request_uri = $_SERVER['REQUEST_URI']; + $request_uri = preg_replace('/\?.*$/', '', $request_uri); + $final_uri .= $request_uri; +@@ -3565,10 +3575,7 @@ class CAS_Client + // the URL is built when needed only + if ( empty($this->_url) ) { + // remove the ticket if present in the URL +- $final_uri = ($this->_isHttps()) ? 'https' : 'http'; +- $final_uri .= '://'; +- +- $final_uri .= $this->_getClientUrl(); ++ $final_uri = $this->getServiceBaseUrl()->get(); + $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2); + $final_uri .= $request_uri[0]; + +@@ -3605,65 +3612,62 @@ class CAS_Client + return $this->_server['base_url'] = $url; + } + +- + /** +- * Try to figure out the phpCAS client URL with possible Proxys / Ports etc. ++ * The ServiceBaseUrl object that provides base URL during service URL ++ * discovery process. ++ * ++ * @var CAS_ServiceBaseUrl_Interface ++ * ++ * @hideinitializer ++ */ ++ private $_serviceBaseUrl = null; ++ ++ ++ /** ++ * Answer the CAS_ServiceBaseUrl_Interface object for this client. + * +- * @return string Server URL with domain:port ++ * @return CAS_ServiceBaseUrl_Interface + */ +- private function _getClientUrl() ++ public function getServiceBaseUrl() + { +- if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { +- // explode the host list separated by comma and use the first host +- $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); +- // see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default +- return $hosts[0]; +- } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) { +- $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER']; +- } else { +- if (empty($_SERVER['SERVER_NAME'])) { +- $server_url = $_SERVER['HTTP_HOST']; +- } else { +- $server_url = $_SERVER['SERVER_NAME']; +- } ++ if (empty($this->_serviceBaseUrl)) { ++ phpCAS::error("ServiceBaseUrl object is not initialized"); + } +- if (!strpos($server_url, ':')) { +- if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) { +- $server_port = $_SERVER['SERVER_PORT']; +- } else { +- $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']); +- $server_port = $ports[0]; +- } +- +- if ( ($this->_isHttps() && $server_port!=443) +- || (!$this->_isHttps() && $server_port!=80) +- ) { +- $server_url .= ':'; +- $server_url .= $server_port; +- } +- } +- return $server_url; ++ return $this->_serviceBaseUrl; + } + + /** +- * This method checks to see if the request is secured via HTTPS ++ * This method sets the service base URL used during service URL discovery process. ++ * ++ * This is required since phpCAS 1.6.0 to protect the integrity of the authentication. ++ * ++ * @since phpCAS 1.6.0 ++ * ++ * @param $name can be any of the following: ++ * - A base URL string. The service URL discovery will always use this (protocol, ++ * hostname and optional port number) without using any external host names. ++ * - An array of base URL strings. The service URL discovery will check against ++ * this list before using the auto discovered base URL. If there is no match, ++ * the first base URL in the array will be used as the default. This option is ++ * helpful if your PHP website is accessible through multiple domains without a ++ * canonical name, or through both HTTP and HTTPS. ++ * - A class that implements CAS_ServiceBaseUrl_Interface. If you need to customize ++ * the base URL discovery behavior, you can pass in a class that implements the ++ * interface. + * +- * @return bool true if https, false otherwise ++ * @return void + */ +- private function _isHttps() ++ private function _setServiceBaseUrl($name) + { +- if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) { +- return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'); +- } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) { +- return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https'); +- } elseif ( isset($_SERVER['HTTPS']) +- && !empty($_SERVER['HTTPS']) +- && strcasecmp($_SERVER['HTTPS'], 'off') !== 0 +- ) { +- return true; ++ if (is_array($name)) { ++ $this->_serviceBaseUrl = new CAS_ServiceBaseUrl_AllowedListDiscovery($name); ++ } else if (is_string($name)) { ++ $this->_serviceBaseUrl = new CAS_ServiceBaseUrl_Static($name); ++ } else if ($name instanceof CAS_ServiceBaseUrl_Interface) { ++ $this->_serviceBaseUrl = $name; ++ } else { ++ throw new CAS_TypeMismatchException($name, '$name', 'array, string, or CAS_ServiceBaseUrl_Interface object'); + } +- return false; +- + } + + /** +Index: php-cas/source/CAS/ServiceBaseUrl/AllowedListDiscovery.php +=================================================================== +--- /dev/null ++++ php-cas/source/CAS/ServiceBaseUrl/AllowedListDiscovery.php +@@ -0,0 +1,152 @@ ++<?php ++ ++/** ++ * Licensed to Jasig under one or more contributor license ++ * agreements. See the NOTICE file distributed with this work for ++ * additional information regarding copyright ownership. ++ * ++ * Jasig licenses this file to you under the Apache License, ++ * Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at: ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * PHP Version 7 ++ * ++ * @file CAS/ServiceBaseUrl/AllowedListDiscovery.php ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++ ++/** ++ * Class that gets the service base URL of the PHP server by HTTP header ++ * discovery and allowlist check. This is used to generate service URL ++ * and PGT callback URL. ++ * ++ * @class CAS_ServiceBaseUrl_AllowedListDiscovery ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++class CAS_ServiceBaseUrl_AllowedListDiscovery ++extends CAS_ServiceBaseUrl_Base ++{ ++ private $_list = array(); ++ ++ public function __construct($list) { ++ if (is_array($list)) { ++ if (count($list) === 0) { ++ throw new CAS_InvalidArgumentException('$list should not be empty'); ++ } ++ foreach ($list as $value) { ++ $this->allow($value); ++ } ++ } else { ++ throw new CAS_TypeMismatchException($list, '$list', 'array'); ++ } ++ } ++ ++ /** ++ * Add a base URL to the allowed list. ++ * ++ * @param $url protocol, host name and port to add to the allowed list ++ * ++ * @return void ++ */ ++ public function allow($url) ++ { ++ $this->_list[] = $this->removeStandardPort($url); ++ } ++ ++ /** ++ * Check if the server name is allowed by configuration. ++ * ++ * @param $name server name to check ++ * ++ * @return bool whether the allowed list contains the server name ++ */ ++ protected function isAllowed($name) ++ { ++ return in_array($name, $this->_list); ++ } ++ ++ /** ++ * Discover the server name through HTTP headers. ++ * ++ * We read: ++ * - HTTP header X-Forwarded-Host ++ * - HTTP header X-Forwarded-Server and X-Forwarded-Port ++ * - HTTP header Host and SERVER_PORT ++ * - PHP SERVER_NAME (which can change based on the HTTP server used) ++ * ++ * The standard port will be omitted (80 for HTTP, 443 for HTTPS). ++ * ++ * @return string the discovered, unsanitized server protocol, hostname and port ++ */ ++ protected function discover() ++ { ++ $isHttps = $this->isHttps(); ++ $protocol = $isHttps ? 'https' : 'http'; ++ $protocol .= '://'; ++ if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { ++ // explode the host list separated by comma and use the first host ++ $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); ++ // see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default ++ return $protocol . $hosts[0]; ++ } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) { ++ $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER']; ++ } else { ++ if (empty($_SERVER['SERVER_NAME'])) { ++ $server_url = $_SERVER['HTTP_HOST']; ++ } else { ++ $server_url = $_SERVER['SERVER_NAME']; ++ } ++ } ++ if (!strpos($server_url, ':')) { ++ if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) { ++ $server_port = $_SERVER['SERVER_PORT']; ++ } else { ++ $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']); ++ $server_port = $ports[0]; ++ } ++ ++ $server_url .= ':'; ++ $server_url .= $server_port; ++ } ++ return $protocol . $server_url; ++ } ++ ++ /** ++ * Get PHP server base URL. ++ * ++ * @return string the server protocol, hostname and port ++ */ ++ public function get() ++ { ++ phpCAS::traceBegin(); ++ $result = $this->removeStandardPort($this->discover()); ++ phpCAS::trace("Discovered server base URL: " . $result); ++ if ($this->isAllowed($result)) { ++ phpCAS::trace("Server base URL is allowed"); ++ phpCAS::traceEnd(true); ++ } else { ++ $result = $this->_list[0]; ++ phpCAS::trace("Server base URL is not allowed, using default: " . $result); ++ phpCAS::traceEnd(false); ++ } ++ return $result; ++ } ++} +Index: php-cas/source/CAS/ServiceBaseUrl/Base.php +=================================================================== +--- /dev/null ++++ php-cas/source/CAS/ServiceBaseUrl/Base.php +@@ -0,0 +1,98 @@ ++<?php ++ ++/** ++ * Licensed to Jasig under one or more contributor license ++ * agreements. See the NOTICE file distributed with this work for ++ * additional information regarding copyright ownership. ++ * ++ * Jasig licenses this file to you under the Apache License, ++ * Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at: ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * PHP Version 7 ++ * ++ * @file CAS/ServiceBaseUrl/Base.php ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++/** ++ * Base class of CAS/ServiceBaseUrl that implements isHTTPS method. ++ * ++ * @class CAS_ServiceBaseUrl_Base ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++abstract class CAS_ServiceBaseUrl_Base ++implements CAS_ServiceBaseUrl_Interface ++{ ++ ++ /** ++ * Get PHP server name. ++ * ++ * @return string the server hostname and port of the server ++ */ ++ abstract public function get(); ++ ++ /** ++ * Check whether HTTPS is used. ++ * ++ * This is used to construct the protocol in the URL. ++ * ++ * @return bool true if HTTPS is used ++ */ ++ public function isHttps() { ++ if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) { ++ return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'); ++ } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) { ++ return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https'); ++ } elseif ( isset($_SERVER['HTTPS']) ++ && !empty($_SERVER['HTTPS']) ++ && strcasecmp($_SERVER['HTTPS'], 'off') !== 0 ++ ) { ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Remove standard HTTP and HTTPS port for discovery and allowlist input. ++ * ++ * @param $url URL as https://domain:port without trailing slash ++ * @return standardized URL, or the original URL ++ * @throws CAS_InvalidArgumentException if the URL does not include the protocol ++ */ ++ protected function removeStandardPort($url) { ++ if (strpos($url, "://") === false) { ++ throw new CAS_InvalidArgumentException( ++ "Configured base URL should include the protocol string: " . $url); ++ } ++ ++ $url = rtrim($url, '/'); ++ ++ if (strpos($url, "https://") === 0 && substr_compare($url, ':443', -4) === 0) { ++ return substr($url, 0, -4); ++ } ++ ++ if (strpos($url, "http://") === 0 && substr_compare($url, ':80', -3) === 0) { ++ return substr($url, 0, -3); ++ } ++ ++ return $url; ++ } ++ ++} +Index: php-cas/source/CAS/ServiceBaseUrl/Interface.php +=================================================================== +--- /dev/null ++++ php-cas/source/CAS/ServiceBaseUrl/Interface.php +@@ -0,0 +1,61 @@ ++<?php ++ ++/** ++ * Licensed to Jasig under one or more contributor license ++ * agreements. See the NOTICE file distributed with this work for ++ * additional information regarding copyright ownership. ++ * ++ * Jasig licenses this file to you under the Apache License, ++ * Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at: ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * PHP Version 7 ++ * ++ * @file CAS/ServerHostname/Interface.php ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++/** ++ * An interface for classes that gets the server name of the PHP server. ++ * This is used to generate service URL and PGT callback URL. ++ * ++ * @class CAS_ServiceBaseUrl_Interface ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++interface CAS_ServiceBaseUrl_Interface ++{ ++ ++ /** ++ * Get PHP HTTP protocol and server name. ++ * ++ * @return string protocol, server hostname, and optionally port, ++ * without trailing slash (https://localhost:8443) ++ */ ++ public function get(); ++ ++ /** ++ * Check whether HTTPS is used. ++ * ++ * This is used to construct the protocol in the URL. ++ * ++ * @return bool true if HTTPS is used ++ */ ++ public function isHttps(); ++ ++} +Index: php-cas/source/CAS/ServiceBaseUrl/Static.php +=================================================================== +--- /dev/null ++++ php-cas/source/CAS/ServiceBaseUrl/Static.php +@@ -0,0 +1,69 @@ ++<?php ++ ++/** ++ * Licensed to Jasig under one or more contributor license ++ * agreements. See the NOTICE file distributed with this work for ++ * additional information regarding copyright ownership. ++ * ++ * Jasig licenses this file to you under the Apache License, ++ * Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at: ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * PHP Version 7 ++ * ++ * @file CAS/ServiceBaseUrl/Static.php ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++ ++/** ++ * Class that gets the server name of the PHP server by statically set ++ * hostname and port. This is used to generate service URL and PGT ++ * callback URL. ++ * ++ * @class CAS_ServiceBaseUrl_Static ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++class CAS_ServiceBaseUrl_Static ++extends CAS_ServiceBaseUrl_Base ++{ ++ private $_name = null; ++ ++ public function __construct($name) { ++ if (is_string($name)) { ++ $this->_name = $this->removeStandardPort($name); ++ } else { ++ throw new CAS_TypeMismatchException($name, '$name', 'string'); ++ } ++ } ++ ++ /** ++ * Get the server name through static config. ++ * ++ * @return string the server hostname and port of the server configured ++ */ ++ public function get() ++ { ++ phpCAS::traceBegin(); ++ phpCAS::trace("Returning static server name: " . $this->_name); ++ phpCAS::traceEnd(true); ++ return $this->_name; ++ } ++} +\ No newline at end of file +Index: php-cas/test/CAS/Tests/ServiceBaseUrlTest.php +=================================================================== +--- /dev/null ++++ php-cas/test/CAS/Tests/ServiceBaseUrlTest.php +@@ -0,0 +1,244 @@ ++<?php ++ ++/** ++ * Licensed to Jasig under one or more contributor license ++ * agreements. See the NOTICE file distributed with this work for ++ * additional information regarding copyright ownership. ++ * ++ * Jasig licenses this file to you under the Apache License, ++ * Version 2.0 (the "License"); you may not use this file except in ++ * compliance with the License. You may obtain a copy of the License at: ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * PHP Version 7 ++ * ++ * @file CAS/Tests/ServiceBaseUrlTest.php ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++ ++namespace PhpCas\Tests; ++ ++use PHPUnit\Framework\TestCase; ++ ++/** ++ * Test class for verifying the operation of the ServiceBaseUrl classes. ++ * ++ * @class ServiceBaseUrlTest ++ * @category Authentication ++ * @package PhpCAS ++ * @author Henry Pan <git@phy25.com> ++ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 ++ * @link https://wiki.jasig.org/display/CASC/phpCAS ++ */ ++class ServiceBaseUrlTest extends TestCase ++{ ++ /** ++ * @var CAS_Client ++ */ ++ protected $object; ++ ++ const DEFAULT_NAME = 'https://default.domain'; ++ ++ const DOMAIN_1 = 'http://domain1'; ++ ++ /** ++ * Sets up the fixture, for example, opens a network connection. ++ * This method is called before a test is executed. ++ */ ++ protected function setUp(): void ++ { ++ $this->object = new \CAS_ServiceBaseUrl_AllowedListDiscovery(array(self::DEFAULT_NAME, self::DOMAIN_1)); ++ } ++ ++ /** ++ * Tears down the fixture, for example, closes a network connection. ++ * This method is called after a test is executed. ++ */ ++ protected function tearDown(): void ++ { ++ ++ } ++ ++ /********************************************************* ++ * Tests of public (interface) methods ++ *********************************************************/ ++ ++ /** ++ * Verify that non allowlisted SERVER_NAME will return default name. ++ * ++ * @return void ++ */ ++ public function testNonAllowlistedServerName() ++ { ++ $_SERVER['SERVER_NAME'] = 'domain1:8080'; ++ ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that non allowlisted HTTP_HOST will return default name. ++ * ++ * @return void ++ */ ++ public function testNonAllowlistedHttpHost() ++ { ++ $_SERVER['HTTP_HOST'] = 'domain1:8080'; ++ $_SERVER['SERVER_NAME'] = ''; ++ ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that non allowlisted HTTP_X_FORWARDED_SERVER will return default name. ++ * ++ * @return void ++ */ ++ public function testNonAllowlistedXForwardedServer() ++ { ++ $_SERVER['HTTP_X_FORWARDED_SERVER'] = 'domain1'; ++ $_SERVER['HTTP_X_FORWARDED_PORT'] = '8080'; ++ ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that non allowlisted HTTP_X_FORWARDED_SERVER will return. ++ * ++ * @return void ++ */ ++ public function testNonAllowlistedXForwardedHost() ++ { ++ $_SERVER['HTTP_X_FORWARDED_HOST'] = 'domain1:8080'; ++ ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted SERVER_NAME will return in standarized form. ++ * ++ * @return void ++ */ ++ public function testAllowlistedServerName() ++ { ++ $_SERVER['SERVER_NAME'] = 'domain1'; ++ $_SERVER['HTTP_X_FORWARDED_PORT'] = '80'; ++ ++ $this->assertSame(self::DOMAIN_1, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_HOST will return. ++ * ++ * @return void ++ */ ++ public function testAllowlistedHttpHost() ++ { ++ $_SERVER['HTTP_HOST'] = 'domain1'; ++ $_SERVER['SERVER_NAME'] = ''; ++ $_SERVER['HTTP_X_FORWARDED_PORT'] = '80'; ++ ++ $this->assertSame(self::DOMAIN_1, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_X_FORWARDED_SERVER will return. ++ * ++ * @return void ++ */ ++ public function testAllowlistedXForwardedServer() ++ { ++ $_SERVER['HTTP_X_FORWARDED_SERVER'] = 'domain1'; ++ $_SERVER['HTTP_X_FORWARDED_PORT'] = '80'; ++ ++ $this->assertSame(self::DOMAIN_1, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_X_FORWARDED_HOST will return. ++ * ++ * @return void ++ */ ++ public function testAllowlistedXForwardedHost() ++ { ++ $_SERVER['HTTP_X_FORWARDED_HOST'] = 'domain1'; ++ ++ $this->assertSame(self::DOMAIN_1, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_X_FORWARDED_HOST will return with a HTTP allowlist ++ * that needs to be standardized. ++ * ++ * @return void ++ */ ++ public function testAllowlistedXForwardedHostHttpStandardized() ++ { ++ $_SERVER['HTTP_X_FORWARDED_HOST'] = 'domain1'; ++ ++ $this->object = new \CAS_ServiceBaseUrl_AllowedListDiscovery(array(self::DEFAULT_NAME, "http://domain1:80/")); ++ $this->assertSame(self::DOMAIN_1, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_X_FORWARDED_HOST will return with a HTTP allowlist ++ * that needs to be standardized. ++ * ++ * @return void ++ */ ++ public function testAllowlistedXForwardedHostWithSslHttpsStandardized() ++ { ++ $_SERVER['HTTPS'] = 'on'; ++ $_SERVER['HTTP_X_FORWARDED_HOST'] = 'default.domain:443'; ++ ++ $this->object = new \CAS_ServiceBaseUrl_AllowedListDiscovery(array("https://default.domain:443/", self::DOMAIN_1)); ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that allowlisted HTTP_X_FORWARDED_HOST will return with a HTTP allowlist ++ * that needs to be standardized. ++ * ++ * @return void ++ */ ++ public function testAllowlistedXForwardedHostHttpsStandardized() ++ { ++ $_SERVER['HTTP_X_FORWARDED_HOST'] = 'default.domain:443'; ++ ++ $this->object = new \CAS_ServiceBaseUrl_AllowedListDiscovery(array("https://default.domain:443/", "http://default.domain:443/")); ++ $this->assertSame("http://default.domain:443", $this->object->get()); ++ } ++ ++ /** ++ * Verify that static configuration always return the standardized base URL. ++ * ++ * @return void ++ */ ++ public function testStaticHappyPath() ++ { ++ $this->object = new \CAS_ServiceBaseUrl_Static("https://default.domain:443/"); ++ $this->assertSame(self::DEFAULT_NAME, $this->object->get()); ++ } ++ ++ /** ++ * Verify that static configuration always return the standardized base URL. ++ * ++ * @return void ++ */ ++ public function testStaticNoProtocol() ++ { ++ $this->expectException(\CAS_InvalidArgumentException::class); ++ $this->object = new \CAS_ServiceBaseUrl_Static("default.domain/"); ++ } ++ ++} +Index: php-cas/source/CAS.php +=================================================================== +--- php-cas.orig/source/CAS.php ++++ php-cas/source/CAS.php +@@ -334,6 +334,14 @@ class phpCAS + * @param string $server_hostname the hostname of the CAS server + * @param int $server_port the port the CAS server is running on + * @param string $server_uri the URI the CAS server is responding on ++ * @param string|string[]|CAS_ServiceBaseUrl_Interface ++ * $service_base_url the base URL (protocol, host and the ++ * optional port) of the CAS client; pass ++ * in an array to use auto discovery with ++ * an allowlist; pass in ++ * CAS_ServiceBaseUrl_Interface for custom ++ * behavior. Added in 1.6.0. Similar to ++ * serverName config in other CAS clients. + * @param bool $changeSessionID Allow phpCAS to change the session_id (Single + * Sign Out/handleLogoutRequests is based on that change) + * +@@ -343,7 +351,7 @@ class phpCAS + * and phpCAS::setDebug()). + */ + public static function client($server_version, $server_hostname, +- $server_port, $server_uri, $changeSessionID = true ++ $server_port, $server_uri, $service_base_url, $changeSessionID = true + ) { + phpCAS :: traceBegin(); + if (is_object(self::$_PHPCAS_CLIENT)) { +@@ -362,7 +370,7 @@ class phpCAS + // initialize the object $_PHPCAS_CLIENT + try { + self::$_PHPCAS_CLIENT = new CAS_Client( +- $server_version, false, $server_hostname, $server_port, $server_uri, ++ $server_version, false, $server_hostname, $server_port, $server_uri, $service_base_url, + $changeSessionID + ); + } catch (Exception $e) { +@@ -378,6 +386,14 @@ class phpCAS + * @param string $server_hostname the hostname of the CAS server + * @param int $server_port the port the CAS server is running on + * @param string $server_uri the URI the CAS server is responding on ++ * @param string|string[]|CAS_ServiceBaseUrl_Interface ++ * $service_base_url the base URL (protocol, host and the ++ * optional port) of the CAS client; pass ++ * in an array to use auto discovery with ++ * an allowlist; pass in ++ * CAS_ServiceBaseUrl_Interface for custom ++ * behavior. Added in 1.6.0. Similar to ++ * serverName config in other CAS clients. + * @param bool $changeSessionID Allow phpCAS to change the session_id (Single + * Sign Out/handleLogoutRequests is based on that change) + * +@@ -387,7 +403,7 @@ class phpCAS + * and phpCAS::setDebug()). + */ + public static function proxy($server_version, $server_hostname, +- $server_port, $server_uri, $changeSessionID = true ++ $server_port, $server_uri, $service_base_url, $changeSessionID = true + ) { + phpCAS :: traceBegin(); + if (is_object(self::$_PHPCAS_CLIENT)) { +@@ -406,7 +422,7 @@ class phpCAS + // initialize the object $_PHPCAS_CLIENT + try { + self::$_PHPCAS_CLIENT = new CAS_Client( +- $server_version, true, $server_hostname, $server_port, $server_uri, ++ $server_version, true, $server_hostname, $server_port, $server_uri, $service_base_url, + $changeSessionID + ); + } catch (Exception $e) { diff -Nru php-cas-1.3.8/debian/patches/series php-cas-1.3.8/debian/patches/series --- php-cas-1.3.8/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ php-cas-1.3.8/debian/patches/series 2023-07-08 11:45:35.000000000 +0000 @@ -0,0 +1 @@ +CVE-2022-39369.patch
Attachment:
signature.asc
Description: This is a digitally signed message part.