[saml] Update Composer dependency ahead of release
- Updating onelogin/php-saml (4.0.0 => 4.1.0)
This commit is contained in:
parent
d910502a17
commit
7bff983d21
14 changed files with 256 additions and 185 deletions
17
saml/composer.lock
generated
17
saml/composer.lock
generated
|
@ -8,16 +8,16 @@
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "onelogin/php-saml",
|
"name": "onelogin/php-saml",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/onelogin/php-saml.git",
|
"url": "https://github.com/onelogin/php-saml.git",
|
||||||
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979"
|
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/f30f5062f3653c4d2082892d207f4dc3e577d979",
|
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d",
|
||||||
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979",
|
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -55,12 +55,7 @@
|
||||||
"onelogin",
|
"onelogin",
|
||||||
"saml"
|
"saml"
|
||||||
],
|
],
|
||||||
"support": {
|
"time": "2022-07-15T20:44:36+00:00"
|
||||||
"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"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "robrichards/xmlseclibs",
|
"name": "robrichards/xmlseclibs",
|
||||||
|
@ -113,5 +108,5 @@
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.0.0"
|
"plugin-api-version": "1.1.0"
|
||||||
}
|
}
|
||||||
|
|
38
saml/vendor/composer/ClassLoader.php
vendored
38
saml/vendor/composer/ClassLoader.php
vendored
|
@ -37,13 +37,11 @@ namespace Composer\Autoload;
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
* @see https://www.php-fig.org/psr/psr-0/
|
* @see http://www.php-fig.org/psr/psr-0/
|
||||||
* @see https://www.php-fig.org/psr/psr-4/
|
* @see http://www.php-fig.org/psr/psr-4/
|
||||||
*/
|
*/
|
||||||
class ClassLoader
|
class ClassLoader
|
||||||
{
|
{
|
||||||
private $vendorDir;
|
|
||||||
|
|
||||||
// PSR-4
|
// PSR-4
|
||||||
private $prefixLengthsPsr4 = array();
|
private $prefixLengthsPsr4 = array();
|
||||||
private $prefixDirsPsr4 = array();
|
private $prefixDirsPsr4 = array();
|
||||||
|
@ -59,13 +57,6 @@ class ClassLoader
|
||||||
private $missingClasses = array();
|
private $missingClasses = array();
|
||||||
private $apcuPrefix;
|
private $apcuPrefix;
|
||||||
|
|
||||||
private static $registeredLoaders = array();
|
|
||||||
|
|
||||||
public function __construct($vendorDir = null)
|
|
||||||
{
|
|
||||||
$this->vendorDir = $vendorDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPrefixes()
|
public function getPrefixes()
|
||||||
{
|
{
|
||||||
if (!empty($this->prefixesPsr0)) {
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
@ -309,17 +300,6 @@ class ClassLoader
|
||||||
public function register($prepend = false)
|
public function register($prepend = false)
|
||||||
{
|
{
|
||||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
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()
|
public function unregister()
|
||||||
{
|
{
|
||||||
spl_autoload_unregister(array($this, 'loadClass'));
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
if (null !== $this->vendorDir) {
|
|
||||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,16 +367,6 @@ class ClassLoader
|
||||||
return $file;
|
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)
|
private function findFileWithExtension($class, $ext)
|
||||||
{
|
{
|
||||||
// PSR-4 lookup
|
// PSR-4 lookup
|
||||||
|
|
1
saml/vendor/composer/autoload_classmap.php
vendored
1
saml/vendor/composer/autoload_classmap.php
vendored
|
@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||||
$baseDir = dirname($vendorDir);
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
|
||||||
);
|
);
|
||||||
|
|
6
saml/vendor/composer/autoload_real.php
vendored
6
saml/vendor/composer/autoload_real.php
vendored
|
@ -22,15 +22,13 @@ class ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704
|
||||||
return self::$loader;
|
return self::$loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
require __DIR__ . '/platform_check.php';
|
|
||||||
|
|
||||||
spl_autoload_register(array('ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704', 'loadClassLoader'), true, true);
|
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'));
|
spl_autoload_unregister(array('ComposerAutoloaderInit6ecac07d47dd9d108b36bee3eda76704', 'loadClassLoader'));
|
||||||
|
|
||||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||||
if ($useStaticLoader) {
|
if ($useStaticLoader) {
|
||||||
require __DIR__ . '/autoload_static.php';
|
require_once __DIR__ . '/autoload_static.php';
|
||||||
|
|
||||||
call_user_func(\Composer\Autoload\ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::getInitializer($loader));
|
call_user_func(\Composer\Autoload\ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::getInitializer($loader));
|
||||||
} else {
|
} else {
|
||||||
|
|
5
saml/vendor/composer/autoload_static.php
vendored
5
saml/vendor/composer/autoload_static.php
vendored
|
@ -28,16 +28,11 @@ class ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $classMap = array (
|
|
||||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
|
||||||
);
|
|
||||||
|
|
||||||
public static function getInitializer(ClassLoader $loader)
|
public static function getInitializer(ClassLoader $loader)
|
||||||
{
|
{
|
||||||
return \Closure::bind(function () use ($loader) {
|
return \Closure::bind(function () use ($loader) {
|
||||||
$loader->prefixLengthsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixLengthsPsr4;
|
$loader->prefixLengthsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixLengthsPsr4;
|
||||||
$loader->prefixDirsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixDirsPsr4;
|
$loader->prefixDirsPsr4 = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$prefixDirsPsr4;
|
||||||
$loader->classMap = ComposerStaticInit6ecac07d47dd9d108b36bee3eda76704::$classMap;
|
|
||||||
|
|
||||||
}, null, ClassLoader::class);
|
}, null, ClassLoader::class);
|
||||||
}
|
}
|
||||||
|
|
29
saml/vendor/composer/installed.json
vendored
29
saml/vendor/composer/installed.json
vendored
|
@ -1,18 +1,17 @@
|
||||||
{
|
[
|
||||||
"packages": [
|
|
||||||
{
|
{
|
||||||
"name": "onelogin/php-saml",
|
"name": "onelogin/php-saml",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"version_normalized": "4.0.0.0",
|
"version_normalized": "4.1.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/onelogin/php-saml.git",
|
"url": "https://github.com/onelogin/php-saml.git",
|
||||||
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979"
|
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/f30f5062f3653c4d2082892d207f4dc3e577d979",
|
"url": "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d",
|
||||||
"reference": "f30f5062f3653c4d2082892d207f4dc3e577d979",
|
"reference": "b22a57ebd13e838b90df5d3346090bc37056409d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -33,7 +32,7 @@
|
||||||
"ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)",
|
"ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)",
|
||||||
"ext-zlib": "Install zlib"
|
"ext-zlib": "Install zlib"
|
||||||
},
|
},
|
||||||
"time": "2021-03-02T10:19:19+00:00",
|
"time": "2022-07-15T20:44:36+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -51,13 +50,7 @@
|
||||||
"SAML2",
|
"SAML2",
|
||||||
"onelogin",
|
"onelogin",
|
||||||
"saml"
|
"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",
|
"name": "robrichards/xmlseclibs",
|
||||||
|
@ -101,10 +94,6 @@
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/robrichards/xmlseclibs/issues",
|
"issues": "https://github.com/robrichards/xmlseclibs/issues",
|
||||||
"source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1"
|
"source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1"
|
||||||
},
|
|
||||||
"install-path": "../robrichards/xmlseclibs"
|
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"dev-package-names": []
|
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
|
54
saml/vendor/onelogin/php-saml/.github/workflows/php-package.yml
vendored
Normal file
54
saml/vendor/onelogin/php-saml/.github/workflows/php-package.yml
vendored
Normal 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
|
39
saml/vendor/onelogin/php-saml/README.md
vendored
39
saml/vendor/onelogin/php-saml/README.md
vendored
|
@ -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.
|
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
|
Getting started
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -754,6 +785,8 @@ $_SESSION['samlNameidSPNameQualifier'] = $auth->getNameIdSPNameQualifier();
|
||||||
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
|
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
|
||||||
|
|
||||||
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
|
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']);
|
$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
|
$_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
|
||||||
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
|
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
|
$auth->redirectTo($_POST['RelayState']); // Redirect if there is a
|
||||||
} // relayState set
|
} // relayState set
|
||||||
} else if (isset($_GET['sls'])) { // Single Logout Service
|
} 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)) {
|
if (empty($errors)) {
|
||||||
echo '<p>Sucessfully logged out</p>';
|
echo '<p>Sucessfully logged out</p>';
|
||||||
} else {
|
} 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.
|
* `parseXML` - Get IdP Metadata Info from XML.
|
||||||
* `injectIntoSettings` - Inject metadata info into php-saml settings array.
|
* `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
|
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
|
about what it does and how to use it are provided. Make sure to also check the doc folder where
|
||||||
|
|
|
@ -168,13 +168,14 @@ class Auth
|
||||||
* Initializes the SP SAML instance.
|
* Initializes the SP SAML instance.
|
||||||
*
|
*
|
||||||
* @param array|null $settings Setting data
|
* @param array|null $settings Setting data
|
||||||
|
* @param bool $spValidationOnly if true, The library will only validate the SAML SP settings,
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
* @throws Error
|
* @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->_errors[] = 'invalid_response';
|
||||||
$this->_lastErrorException = $response->getErrorException();
|
$this->_lastErrorException = $response->getErrorException();
|
||||||
$this->_lastError = $response->getError();
|
$this->_lastError = $response->getError();
|
||||||
$this->_errors[] = $this->_lastError;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->_errors[] = 'invalid_binding';
|
$this->_errors[] = 'invalid_binding';
|
||||||
|
|
|
@ -26,6 +26,10 @@ class IdPMetadataParser
|
||||||
/**
|
/**
|
||||||
* Get IdP Metadata Info from URL
|
* 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 $url URL where the IdP metadata is published
|
||||||
* @param string $entityId Entity Id of the desired IdP, if no
|
* @param string $entityId Entity Id of the desired IdP, if no
|
||||||
* entity Id is provided and the XML
|
* entity Id is provided and the XML
|
||||||
|
@ -43,6 +47,9 @@ class IdPMetadataParser
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$ch = curl_init($url);
|
$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_CUSTOMREQUEST, "GET");
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
|
|
@ -269,7 +269,10 @@ class Response
|
||||||
|
|
||||||
// Check destination
|
// Check destination
|
||||||
if ($this->document->documentElement->hasAttribute('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 (empty($destination)) {
|
||||||
if (!$security['relaxDestinationValidation']) {
|
if (!$security['relaxDestinationValidation']) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
|
@ -308,6 +311,7 @@ class Response
|
||||||
// Check the issuers
|
// Check the issuers
|
||||||
$issuers = $this->getIssuers();
|
$issuers = $this->getIssuers();
|
||||||
foreach ($issuers as $issuer) {
|
foreach ($issuers as $issuer) {
|
||||||
|
if (isset($issuer)) {
|
||||||
$trimmedIssuer = trim($issuer);
|
$trimmedIssuer = trim($issuer);
|
||||||
if (empty($trimmedIssuer) || $trimmedIssuer !== $idPEntityId) {
|
if (empty($trimmedIssuer) || $trimmedIssuer !== $idPEntityId) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
|
@ -316,6 +320,7 @@ class Response
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check the session Expiration
|
// Check the session Expiration
|
||||||
$sessionExpiration = $this->getSessionNotOnOrAfter();
|
$sessionExpiration = $this->getSessionNotOnOrAfter();
|
||||||
|
@ -554,7 +559,10 @@ class Response
|
||||||
|
|
||||||
$entries = $this->_queryAssertion('/saml:Conditions/saml:AudienceRestriction/saml:Audience');
|
$entries = $this->_queryAssertion('/saml:Conditions/saml:AudienceRestriction/saml:Audience');
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$value = trim($entry->textContent);
|
$value = $entry->textContent;
|
||||||
|
if (isset($value)) {
|
||||||
|
$value = trim($value);
|
||||||
|
}
|
||||||
if (!empty($value)) {
|
if (!empty($value)) {
|
||||||
$audiences[] = $value;
|
$audiences[] = $value;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +822,7 @@ class Response
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$attributeKeyName = $attributeKeyNode->nodeValue;
|
$attributeKeyName = $attributeKeyNode->nodeValue;
|
||||||
if (in_array($attributeKeyName, array_keys($attributes))) {
|
if (in_array($attributeKeyName, array_keys($attributes), true)) {
|
||||||
if (!$allowRepeatAttributeName) {
|
if (!$allowRepeatAttributeName) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
"Found an Attribute element with duplicated ".$keyName,
|
"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);
|
$attributes[$attributeKeyName] = array_merge($attributes[$attributeKeyName], $attributeValues);
|
||||||
} else {
|
} else {
|
||||||
$attributes[$attributeKeyName] = $attributeValues;
|
$attributes[$attributeKeyName] = $attributeValues;
|
||||||
|
|
|
@ -122,7 +122,7 @@ class Settings
|
||||||
* @throws Error If any settings parameter is invalid
|
* @throws Error If any settings parameter is invalid
|
||||||
* @throws Exception If Settings is incorrectly supplied
|
* @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->_spValidationOnly = $spValidationOnly;
|
||||||
$this->_loadPaths();
|
$this->_loadPaths();
|
||||||
|
|
|
@ -221,6 +221,10 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function formatCert($cert, $heads = true)
|
public static function formatCert($cert, $heads = true)
|
||||||
{
|
{
|
||||||
|
if (is_null($cert)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$x509cert = str_replace(array("\x0D", "\r", "\n"), "", $cert);
|
$x509cert = str_replace(array("\x0D", "\r", "\n"), "", $cert);
|
||||||
if (!empty($x509cert)) {
|
if (!empty($x509cert)) {
|
||||||
$x509cert = str_replace('-----BEGIN CERTIFICATE-----', "", $x509cert);
|
$x509cert = str_replace('-----BEGIN CERTIFICATE-----', "", $x509cert);
|
||||||
|
@ -245,6 +249,10 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function formatPrivateKey($key, $heads = true)
|
public static function formatPrivateKey($key, $heads = true)
|
||||||
{
|
{
|
||||||
|
if (is_null($key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$key = str_replace(array("\x0D", "\r", "\n"), "", $key);
|
$key = str_replace(array("\x0D", "\r", "\n"), "", $key);
|
||||||
if (!empty($key)) {
|
if (!empty($key)) {
|
||||||
if (strpos($key, '-----BEGIN PRIVATE KEY-----') !== false) {
|
if (strpos($key, '-----BEGIN PRIVATE KEY-----') !== false) {
|
||||||
|
@ -319,7 +327,12 @@ class Utils
|
||||||
* Verify that the URL matches the regex for the protocol.
|
* Verify that the URL matches the regex for the protocol.
|
||||||
* By default this will check for http and https
|
* 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);
|
$url = filter_var($url, FILTER_VALIDATE_URL);
|
||||||
if ($wrongProtocol || empty($url)) {
|
if ($wrongProtocol || empty($url)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -743,7 +756,7 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function generateUniqueID()
|
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)
|
public static function parseSAML2Time($time)
|
||||||
{
|
{
|
||||||
|
if (empty($time)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$matches = array();
|
$matches = array();
|
||||||
|
|
||||||
/* We use a very strict regex to parse the timestamp. */
|
/* We use a very strict regex to parse the timestamp. */
|
||||||
|
@ -1010,7 +1027,10 @@ class Utils
|
||||||
if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
|
if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$data .= trim($curData);
|
if (isset($curData)) {
|
||||||
|
$curData = trim($curData);
|
||||||
|
}
|
||||||
|
$data .= $curData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,6 +1063,9 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function formatFingerPrint($fingerprint)
|
public static function formatFingerPrint($fingerprint)
|
||||||
{
|
{
|
||||||
|
if (is_null($fingerprint)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$formatedFingerprint = str_replace(':', '', $fingerprint);
|
$formatedFingerprint = str_replace(':', '', $fingerprint);
|
||||||
$formatedFingerprint = strtolower($formatedFingerprint);
|
$formatedFingerprint = strtolower($formatedFingerprint);
|
||||||
return $formatedFingerprint;
|
return $formatedFingerprint;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"php-saml": {
|
"php-saml": {
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"released": "02/03/2021"
|
"released": "07/15/2022"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue