[saml] Update Composer dependency ahead of release

- Updating onelogin/php-saml (4.0.0 => 4.1.0)
This commit is contained in:
Hypolite Petovan 2024-03-19 23:01:21 -04:00
parent d910502a17
commit 7bff983d21
14 changed files with 256 additions and 185 deletions

17
saml/composer.lock generated
View file

@ -8,16 +8,16 @@
"packages": [
{
"name": "onelogin/php-saml",
"version": "4.0.0",
"version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979"
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/f30f5062f3653c4d2082892d207f4dc3e577d979",
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979",
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d",
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d",
"shasum": ""
},
"require": {
@ -55,12 +55,7 @@
"onelogin",
"saml"
],
"support": {
"email": "sixto.garcia@onelogin.com",
"issues": "https://github.com/onelogin/php-saml/issues",
"source": "https://github.com/onelogin/php-saml/"
},
"time": "2021-03-02T10:19:19+00:00"
"time": "2022-07-15T20:44:36+00:00"
},
{
"name": "robrichards/xmlseclibs",
@ -113,5 +108,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.0.0"
"plugin-api-version": "1.1.0"
}

View file

@ -37,13 +37,11 @@ namespace Composer\Autoload;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
private $vendorDir;
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
@ -59,13 +57,6 @@ class ClassLoader
private $missingClasses = array();
private $apcuPrefix;
private static $registeredLoaders = array();
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@ -309,17 +300,6 @@ class ClassLoader
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
@ -328,10 +308,6 @@ class ClassLoader
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
@ -391,16 +367,6 @@ class ClassLoader
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup

View file

@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View file

@ -22,15 +22,13 @@ class ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::getInitializer($loader));
} else {

View file

@ -28,16 +28,11 @@ class ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$classMap;
}, null, ClassLoader::class);
}

View file

@ -1,18 +1,17 @@
{
"packages": [
[
{
"name": "onelogin/php-saml",
"version": "4.0.0",
"version_normalized": "4.0.0.0",
"version": "4.1.0",
"version_normalized": "4.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979"
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/f30f5062f3653c4d2082892d207f4dc3e577d979",
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979",
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d",
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d",
"shasum": ""
},
"require": {
@ -33,7 +32,7 @@
"ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)",
"ext-zlib": "Install zlib"
},
"time": "2021-03-02T10:19:19+00:00",
"time": "2022-07-15T20:44:36+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -51,13 +50,7 @@
"SAML2",
"onelogin",
"saml"
],
"support": {
"email": "sixto.garcia@onelogin.com",
"issues": "https://github.com/onelogin/php-saml/issues",
"source": "https://github.com/onelogin/php-saml/"
},
"install-path": "../onelogin/php-saml"
]
},
{
"name": "robrichards/xmlseclibs",
@ -101,10 +94,6 @@
"support": {
"issues": "https://github.com/robrichards/xmlseclibs/issues",
"source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1"
},
"install-path": "../robrichards/xmlseclibs"
}
],
"dev": true,
"dev-package-names": []
}
]

View file

@ -0,0 +1,54 @@
# This workflow will install PHP dependencies, run tests and lint with a variety of PHP versions
# For more information see: https://github.com/marketplace/actions/setup-php-action
name: php-saml 4.x package
on:
push:
branches: [ 4.* ]
pull_request:
branches: [ 4.* ]
jobs:
test:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: ['ubuntu-latest']
php-versions: [7.3, 7.4, 8.0, 8.1]
steps:
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, intl, mcrypt, xml
tools: composer:v2
ini-values: post_max_size=256M, max_execution_time=180
coverage: xdebug
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v2
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install Composer dependencies
run: |
composer self-update
composer install --prefer-source --no-interaction
- name: Syntax check PHP
run: |
php vendor/bin/phpcpd --exclude tests --exclude vendor .
php vendor/bin/phploc src/.
mkdir -p tests/build/dependences
php vendor/bin/pdepend --summary-xml=tests/build/logs/dependence-summary.xml --jdepend-chart=tests/build/dependences/jdepend.svg --overview-pyramid=tests/build/dependences/pyramid.svg src/.
- name: PHP Code Sniffer
run: php vendor/bin/phpcs --standard=tests/ZendModStandard src/Saml2 demo1 demo2 endpoints tests/src
- name: Run unit tests
run: vendor/bin/phpunit --verbose --debug

View file

@ -148,6 +148,37 @@ environment is not secure and will be exposed to attacks.
In production also we highly recommended to register on the settings the IdP certificate instead of using the fingerprint method. The fingerprint, is a hash, so at the end is open to a collision attack that can end on a signature validation bypass. Other SAML toolkits deprecated that mechanism, we maintain it for compatibility and also to be used on test environment.
### Avoiding Open Redirect attacks ###
Some implementations uses the RelayState parameter as a way to control the flow when SSO and SLO succeeded. So basically the
user is redirected to the value of the RelayState.
If you are using Signature Validation on the HTTP-Redirect binding, you will have the RelayState value integrity covered, otherwise, and
on HTTP-POST binding, you can't trust the RelayState so before
executing the validation, you need to verify that its value belong
a trusted and expected URL.
Read more about Open Redirect [CWE-601](https://cwe.mitre.org/data/definitions/601.html).
### Avoiding Reply attacks ###
A reply attack is basically try to reuse an intercepted valid SAML Message in order to impersonate a SAML action (SSO or SLO).
SAML Messages have a limited timelife (NotBefore, NotOnOrAfter) that
make harder this kind of attacks, but they are still possible.
In order to avoid them, the SP can keep a list of SAML Messages or Assertion IDs alredy valdidated and processed. Those values only need
to be stored the amount of time of the SAML Message life time, so
we don't need to store all processed message/assertion Ids, but the most recent ones.
The OneLogin_Saml2_Auth class contains the [getLastRequestID](https://github.com/onelogin/php-saml/blob/b8214b74dd72960fa6aa88ab454667c64cea935c/src/Saml2/Auth.php#L657), [getLastMessageId](https://github.com/onelogin/php-saml/blob/b8214b74dd72960fa6aa88ab454667c64cea935c/src/Saml2/Auth.php#L762) and [getLastAssertionId](https://github.com/onelogin/php-saml/blob/b8214b74dd72960fa6aa88ab454667c64cea935c/src/Saml2/Auth.php#L770) methods to retrieve the IDs
Checking that the ID of the current Message/Assertion does not exists in the list of the ones already processed will prevent reply
attacks.
Getting started
---------------
@ -754,6 +785,8 @@ $_SESSION['samlNameidSPNameQualifier'] = $auth->getNameIdSPNameQualifier();
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
// To avoid 'Open Redirect' attacks, before execute the
// redirection confirm the value of $_POST['RelayState'] is a // trusted URL.
$auth->redirectTo($_POST['RelayState']);
}
@ -1092,6 +1125,8 @@ if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the I
$_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
// To avoid 'Open Redirect' attacks, before execute the
// redirection confirm the value of $_POST['RelayState'] is a // trusted URL.
$auth->redirectTo($_POST['RelayState']); // Redirect if there is a
} // relayState set
} else if (isset($_GET['sls'])) { // Single Logout Service
@ -1100,7 +1135,7 @@ if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the I
if (empty($errors)) {
echo '<p>Sucessfully logged out</p>';
} else {
echo '<p>' . implode(', ', $errors) . '</p>';
echo '<p>' . htmlentities(implode(', ', $errors)) . '</p>';
}
}
@ -1384,6 +1419,8 @@ Auxiliary class that contains several methods to retrieve and process IdP metada
* `parseXML` - Get IdP Metadata Info from XML.
* `injectIntoSettings` - Inject metadata info into php-saml settings array.
The class does not validate in any way the URL that is introduced on methods like parseRemoteXML in order to retrieve the remove XML. Usually is the same administrator that handles the Service Provider the ones that set the URL that should belong to a trusted third-party IdP.
But there are other scenarios, like a SAAS app where the administrator of the app delegates on other administrators. In such case, extra protection should be taken in order to validate such URL inputs and avoid attacks like SSRF.
For more info, look at the source code; each method is documented and details
about what it does and how to use it are provided. Make sure to also check the doc folder where

View file

@ -168,13 +168,14 @@ class Auth
* Initializes the SP SAML instance.
*
* @param array|null $settings Setting data
* @param bool $spValidationOnly if true, The library will only validate the SAML SP settings,
*
* @throws Exception
* @throws Error
*/
public function __construct(array $settings = null)
public function __construct(array $settings = null, bool $spValidationOnly = false)
{
$this->_settings = new Settings($settings);
$this->_settings = new Settings($settings, $spValidationOnly);
}
/**
@ -251,7 +252,6 @@ class Auth
$this->_errors[] = 'invalid_response';
$this->_lastErrorException = $response->getErrorException();
$this->_lastError = $response->getError();
$this->_errors[] = $this->_lastError;
}
} else {
$this->_errors[] = 'invalid_binding';

View file

@ -26,6 +26,10 @@ class IdPMetadataParser
/**
* Get IdP Metadata Info from URL
*
* This class does not validate in any way the URL that is introduced,
* make sure to validate it properly before use it in the parseRemoteXML
* method in order to avoid security issues like SSRF attacks.
*
* @param string $url URL where the IdP metadata is published
* @param string $entityId Entity Id of the desired IdP, if no
* entity Id is provided and the XML
@ -43,6 +47,9 @@ class IdPMetadataParser
try {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP);
curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS | CURLPROTO_HTTP);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

View file

@ -269,7 +269,10 @@ class Response
// Check destination
if ($this->document->documentElement->hasAttribute('Destination')) {
$destination = trim($this->document->documentElement->getAttribute('Destination'));
$destination = $this->document->documentElement->getAttribute('Destination');
if (isset($destination)) {
$destination = trim($destination);
}
if (empty($destination)) {
if (!$security['relaxDestinationValidation']) {
throw new ValidationError(
@ -308,6 +311,7 @@ class Response
// Check the issuers
$issuers = $this->getIssuers();
foreach ($issuers as $issuer) {
if (isset($issuer)) {
$trimmedIssuer = trim($issuer);
if (empty($trimmedIssuer) || $trimmedIssuer !== $idPEntityId) {
throw new ValidationError(
@ -316,6 +320,7 @@ class Response
);
}
}
}
// Check the session Expiration
$sessionExpiration = $this->getSessionNotOnOrAfter();
@ -554,7 +559,10 @@ class Response
$entries = $this->_queryAssertion('/saml:Conditions/saml:AudienceRestriction/saml:Audience');
foreach ($entries as $entry) {
$value = trim($entry->textContent);
$value = $entry->textContent;
if (isset($value)) {
$value = trim($value);
}
if (!empty($value)) {
$audiences[] = $value;
}
@ -814,7 +822,7 @@ class Response
continue;
}
$attributeKeyName = $attributeKeyNode->nodeValue;
if (in_array($attributeKeyName, array_keys($attributes))) {
if (in_array($attributeKeyName, array_keys($attributes), true)) {
if (!$allowRepeatAttributeName) {
throw new ValidationError(
"Found an Attribute element with duplicated ".$keyName,
@ -830,7 +838,7 @@ class Response
}
}
if (in_array($attributeKeyName, array_keys($attributes))) {
if (in_array($attributeKeyName, array_keys($attributes), true)) {
$attributes[$attributeKeyName] = array_merge($attributes[$attributeKeyName], $attributeValues);
} else {
$attributes[$attributeKeyName] = $attributeValues;

View file

@ -122,7 +122,7 @@ class Settings
* @throws Error If any settings parameter is invalid
* @throws Exception If Settings is incorrectly supplied
*/
public function __construct(array $settings = null, $spValidationOnly = false)
public function __construct(array $settings = null,bool $spValidationOnly = false)
{
$this->_spValidationOnly = $spValidationOnly;
$this->_loadPaths();

View file

@ -221,6 +221,10 @@ class Utils
*/
public static function formatCert($cert, $heads = true)
{
if (is_null($cert)) {
return;
}
$x509cert = str_replace(array("\x0D", "\r", "\n"), "", $cert);
if (!empty($x509cert)) {
$x509cert = str_replace('-----BEGIN CERTIFICATE-----', "", $x509cert);
@ -245,6 +249,10 @@ class Utils
*/
public static function formatPrivateKey($key, $heads = true)
{
if (is_null($key)) {
return;
}
$key = str_replace(array("\x0D", "\r", "\n"), "", $key);
if (!empty($key)) {
if (strpos($key, '-----BEGIN PRIVATE KEY-----') !== false) {
@ -319,7 +327,12 @@ class Utils
* Verify that the URL matches the regex for the protocol.
* By default this will check for http and https
*/
$wrongProtocol = !preg_match(self::$_protocolRegex, $url);
if (isset(self::$_protocolRegex)) {
$protocol = self::$_protocolRegex;
} else {
$protocol = "";
}
$wrongProtocol = !preg_match($protocol, $url);
$url = filter_var($url, FILTER_VALIDATE_URL);
if ($wrongProtocol || empty($url)) {
throw new Error(
@ -743,7 +756,7 @@ class Utils
*/
public static function generateUniqueID()
{
return 'ONELOGIN_' . sha1(uniqid((string)mt_rand(), true));
return 'ONELOGIN_' . sha1(random_bytes(20));
}
/**
@ -773,6 +786,10 @@ class Utils
*/
public static function parseSAML2Time($time)
{
if (empty($time)) {
return null;
}
$matches = array();
/* We use a very strict regex to parse the timestamp. */
@ -1010,7 +1027,10 @@ class Utils
if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
break;
}
$data .= trim($curData);
if (isset($curData)) {
$curData = trim($curData);
}
$data .= $curData;
}
}
@ -1043,6 +1063,9 @@ class Utils
*/
public static function formatFingerPrint($fingerprint)
{
if (is_null($fingerprint)) {
return;
}
$formatedFingerprint = str_replace(':', '', $fingerprint);
$formatedFingerprint = strtolower($formatedFingerprint);
return $formatedFingerprint;

View file

@ -1,7 +1,7 @@
{
"php-saml": {
"version": "4.0.0",
"released": "02/03/2021"
"version": "4.1.0",
"released": "07/15/2022"
}
}