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.