Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/user_saml.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern Schiessle <bjoern@schiessle.org>2018-10-04 16:36:44 +0300
committerBjoern Schiessle <bjoern@schiessle.org>2018-10-09 23:08:33 +0300
commita9fbc8703e723b325493040ecf4711a6084edf39 (patch)
tree2d49f0647881187ffdc3343a65bbc7939901468b /3rdparty
parenta0e05af6c85f35a573871420acdf3d4d4f86a7db (diff)
update to php-saml 3.0.0 without mcrypt dependecy
Signed-off-by: Bjoern Schiessle <bjoern@schiessle.org>
Diffstat (limited to '3rdparty')
-rw-r--r--3rdparty/composer.json2
-rw-r--r--3rdparty/composer.lock82
-rw-r--r--3rdparty/vendor/composer/autoload_classmap.php35
-rw-r--r--3rdparty/vendor/composer/autoload_psr4.php2
-rw-r--r--3rdparty/vendor/composer/autoload_static.php51
-rw-r--r--3rdparty/vendor/composer/installed.json84
-rw-r--r--3rdparty/vendor/onelogin/php-saml/.coveralls.yml7
-rw-r--r--3rdparty/vendor/onelogin/php-saml/.gitignore14
-rw-r--r--3rdparty/vendor/onelogin/php-saml/.travis.yml36
-rw-r--r--3rdparty/vendor/onelogin/php-saml/CHANGELOG30
-rw-r--r--3rdparty/vendor/onelogin/php-saml/README.md462
-rw-r--r--3rdparty/vendor/onelogin/php-saml/_toolkit_loader.php29
-rw-r--r--3rdparty/vendor/onelogin/php-saml/advanced_settings_example.php26
-rw-r--r--3rdparty/vendor/onelogin/php-saml/compatibility.php12
-rw-r--r--3rdparty/vendor/onelogin/php-saml/composer.json33
-rw-r--r--3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php1721
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml/AuthRequest.php65
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml/Metadata.php39
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml/Response.php39
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml/Settings.php80
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml/XmlSec.php110
-rw-r--r--3rdparty/vendor/onelogin/php-saml/lib/Saml2/version.json6
-rw-r--r--3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.mobin200 -> 0 bytes
-rw-r--r--3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.po26
-rw-r--r--3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.mobin405 -> 0 bytes
-rw-r--r--3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.po27
-rw-r--r--3rdparty/vendor/onelogin/php-saml/phpdoc.xml37
-rw-r--r--3rdparty/vendor/onelogin/php-saml/settings_example.php50
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Auth.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Auth.php)353
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php)49
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Constants.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Constants.php)19
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Error.php66
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/IdPMetadataParser.php237
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutRequest.php)276
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutResponse.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutResponse.php)213
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Metadata.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Metadata.php)73
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Response.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Response.php)583
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Settings.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Settings.php)292
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/Utils.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Utils.php)611
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/ValidationError.php (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/Error.php)69
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-assertion-2.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-assertion-2.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-2.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-2.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-metadata-2.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-metadata-2.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-protocol-2.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-protocol-2.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-metadata-attr.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-metadata-attr.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-attribute-ext.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-attribute-ext.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xenc-schema.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xenc-schema.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xml.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xml.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xmldsig-core-schema.xsd (renamed from 3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xmldsig-core-schema.xsd)0
-rw-r--r--3rdparty/vendor/onelogin/php-saml/src/Saml2/version.json6
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/CHANGELOG.txt (renamed from 3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/CHANGELOG.txt)63
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/LICENSE (renamed from 3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/LICENSE)4
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/README.md84
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/composer.json21
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/src/Utils/XPath.php44
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php510
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php1142
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php749
-rw-r--r--3rdparty/vendor/robrichards/xmlseclibs/xmlseclibs.php47
62 files changed, 5042 insertions, 3574 deletions
diff --git a/3rdparty/composer.json b/3rdparty/composer.json
index 228781bf..8735f1f3 100644
--- a/3rdparty/composer.json
+++ b/3rdparty/composer.json
@@ -4,7 +4,7 @@
"classmap-authoritative": true
},
"require": {
- "onelogin/php-saml": "2.10.5",
+ "onelogin/php-saml": "^3.0",
"firebase/php-jwt": "^4.0"
}
}
diff --git a/3rdparty/composer.lock b/3rdparty/composer.lock
index 17b7cc4e..916107f8 100644
--- a/3rdparty/composer.lock
+++ b/3rdparty/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "c0b54acdb5e61d572c6c95652de525ed",
+ "content-hash": "f3e661f8388070704bd9b01b48752bf0",
"packages": [
{
"name": "firebase/php-jwt",
@@ -51,57 +51,91 @@
},
{
"name": "onelogin/php-saml",
- "version": "2.10.5",
+ "version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
- "reference": "3319d7707f342e38291eee6b01a4a5f8df1b333b"
+ "reference": "920c2240e48c9a74aad4129720f48fbf3d5fee47"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/onelogin/php-saml/zipball/3319d7707f342e38291eee6b01a4a5f8df1b333b",
- "reference": "3319d7707f342e38291eee6b01a4a5f8df1b333b",
+ "url": "https://api.github.com/repos/onelogin/php-saml/zipball/920c2240e48c9a74aad4129720f48fbf3d5fee47",
+ "reference": "920c2240e48c9a74aad4129720f48fbf3d5fee47",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-mcrypt": "*",
- "ext-openssl": "*",
- "php": ">=5.3.2"
+ "php": ">=5.4",
+ "robrichards/xmlseclibs": "^3.0"
},
"require-dev": {
- "pdepend/pdepend": "1.1.0",
- "phploc/phploc": "*",
- "phpunit/phpunit": "4.8",
- "satooshi/php-coveralls": "1.0.1",
- "sebastian/phpcpd": "*",
- "squizlabs/php_codesniffer": "*"
+ "pdepend/pdepend": "^2.5.0",
+ "php-coveralls/php-coveralls": "^1.0.2 || ^2.0",
+ "phploc/phploc": "^2.1 || ^3.0 || ^4.0",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1",
+ "sebastian/phpcpd": "^2.0 || ^3.0 || ^4.0",
+ "squizlabs/php_codesniffer": "^3.1.1"
},
"suggest": {
+ "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs",
"ext-gettext": "Install gettext and php5-gettext libs to handle translations",
- "ext-mcrypt": "Install mcrypt and php5-mcrypt libs in order to support encryption",
- "lib-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)"
},
"type": "library",
"autoload": {
- "classmap": [
- "extlib/xmlseclibs",
- "lib/Saml",
- "lib/Saml2"
- ]
+ "psr-4": {
+ "OneLogin\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "OneLogin PHP SAML Toolkit",
- "homepage": "https://onelogin.zendesk.com/hc/en-us/sections/200245634-SAML-Toolkits",
+ "homepage": "https://developers.onelogin.com/saml/php",
"keywords": [
"SAML2",
"onelogin",
"saml"
],
- "time": "2017-03-13T09:56:49+00:00"
+ "time": "2018-10-02T16:02:37+00:00"
+ },
+ {
+ "name": "robrichards/xmlseclibs",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/robrichards/xmlseclibs.git",
+ "reference": "1f4de0c0d121922aafd8c62c2a9f5e528830cf38"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/1f4de0c0d121922aafd8c62c2a9f5e528830cf38",
+ "reference": "1f4de0c0d121922aafd8c62c2a9f5e528830cf38",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "php": ">= 5.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "RobRichards\\XMLSecLibs\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "A PHP library for XML Security",
+ "homepage": "https://github.com/robrichards/xmlseclibs",
+ "keywords": [
+ "security",
+ "signature",
+ "xml",
+ "xmldsig"
+ ],
+ "time": "2018-09-27T13:24:13+00:00"
}
],
"packages-dev": [],
diff --git a/3rdparty/vendor/composer/autoload_classmap.php b/3rdparty/vendor/composer/autoload_classmap.php
index 12172bf6..b8d5737e 100644
--- a/3rdparty/vendor/composer/autoload_classmap.php
+++ b/3rdparty/vendor/composer/autoload_classmap.php
@@ -10,23 +10,20 @@ return array(
'Firebase\\JWT\\ExpiredException' => $vendorDir . '/firebase/php-jwt/src/ExpiredException.php',
'Firebase\\JWT\\JWT' => $vendorDir . '/firebase/php-jwt/src/JWT.php',
'Firebase\\JWT\\SignatureInvalidException' => $vendorDir . '/firebase/php-jwt/src/SignatureInvalidException.php',
- 'OneLogin_Saml2_Auth' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Auth.php',
- 'OneLogin_Saml2_AuthnRequest' => $vendorDir . '/onelogin/php-saml/lib/Saml2/AuthnRequest.php',
- 'OneLogin_Saml2_Constants' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Constants.php',
- 'OneLogin_Saml2_Error' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Error.php',
- 'OneLogin_Saml2_LogoutRequest' => $vendorDir . '/onelogin/php-saml/lib/Saml2/LogoutRequest.php',
- 'OneLogin_Saml2_LogoutResponse' => $vendorDir . '/onelogin/php-saml/lib/Saml2/LogoutResponse.php',
- 'OneLogin_Saml2_Metadata' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Metadata.php',
- 'OneLogin_Saml2_Response' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Response.php',
- 'OneLogin_Saml2_Settings' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Settings.php',
- 'OneLogin_Saml2_Utils' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Utils.php',
- 'OneLogin_Saml2_ValidationError' => $vendorDir . '/onelogin/php-saml/lib/Saml2/Error.php',
- 'OneLogin_Saml_AuthRequest' => $vendorDir . '/onelogin/php-saml/lib/Saml/AuthRequest.php',
- 'OneLogin_Saml_Metadata' => $vendorDir . '/onelogin/php-saml/lib/Saml/Metadata.php',
- 'OneLogin_Saml_Response' => $vendorDir . '/onelogin/php-saml/lib/Saml/Response.php',
- 'OneLogin_Saml_Settings' => $vendorDir . '/onelogin/php-saml/lib/Saml/Settings.php',
- 'OneLogin_Saml_XmlSec' => $vendorDir . '/onelogin/php-saml/lib/Saml/XmlSec.php',
- 'XMLSecEnc' => $vendorDir . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
- 'XMLSecurityDSig' => $vendorDir . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
- 'XMLSecurityKey' => $vendorDir . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
+ 'OneLogin\\Saml2\\Auth' => $vendorDir . '/onelogin/php-saml/src/Saml2/Auth.php',
+ 'OneLogin\\Saml2\\AuthnRequest' => $vendorDir . '/onelogin/php-saml/src/Saml2/AuthnRequest.php',
+ 'OneLogin\\Saml2\\Constants' => $vendorDir . '/onelogin/php-saml/src/Saml2/Constants.php',
+ 'OneLogin\\Saml2\\Error' => $vendorDir . '/onelogin/php-saml/src/Saml2/Error.php',
+ 'OneLogin\\Saml2\\IdPMetadataParser' => $vendorDir . '/onelogin/php-saml/src/Saml2/IdPMetadataParser.php',
+ 'OneLogin\\Saml2\\LogoutRequest' => $vendorDir . '/onelogin/php-saml/src/Saml2/LogoutRequest.php',
+ 'OneLogin\\Saml2\\LogoutResponse' => $vendorDir . '/onelogin/php-saml/src/Saml2/LogoutResponse.php',
+ 'OneLogin\\Saml2\\Metadata' => $vendorDir . '/onelogin/php-saml/src/Saml2/Metadata.php',
+ 'OneLogin\\Saml2\\Response' => $vendorDir . '/onelogin/php-saml/src/Saml2/Response.php',
+ 'OneLogin\\Saml2\\Settings' => $vendorDir . '/onelogin/php-saml/src/Saml2/Settings.php',
+ 'OneLogin\\Saml2\\Utils' => $vendorDir . '/onelogin/php-saml/src/Saml2/Utils.php',
+ 'OneLogin\\Saml2\\ValidationError' => $vendorDir . '/onelogin/php-saml/src/Saml2/ValidationError.php',
+ 'RobRichards\\XMLSecLibs\\Utils\\XPath' => $vendorDir . '/robrichards/xmlseclibs/src/Utils/XPath.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecEnc' => $vendorDir . '/robrichards/xmlseclibs/src/XMLSecEnc.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecurityDSig' => $vendorDir . '/robrichards/xmlseclibs/src/XMLSecurityDSig.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecurityKey' => $vendorDir . '/robrichards/xmlseclibs/src/XMLSecurityKey.php',
);
diff --git a/3rdparty/vendor/composer/autoload_psr4.php b/3rdparty/vendor/composer/autoload_psr4.php
index 00bfd9cd..5cd4e924 100644
--- a/3rdparty/vendor/composer/autoload_psr4.php
+++ b/3rdparty/vendor/composer/autoload_psr4.php
@@ -6,5 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
+ 'RobRichards\\XMLSecLibs\\' => array($vendorDir . '/robrichards/xmlseclibs/src'),
+ 'OneLogin\\' => array($vendorDir . '/onelogin/php-saml/src'),
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
);
diff --git a/3rdparty/vendor/composer/autoload_static.php b/3rdparty/vendor/composer/autoload_static.php
index 22802983..012668c0 100644
--- a/3rdparty/vendor/composer/autoload_static.php
+++ b/3rdparty/vendor/composer/autoload_static.php
@@ -7,6 +7,14 @@ namespace Composer\Autoload;
class ComposerStaticInitcc75f134f7630c1ee3a8e4d7c86f3bcc
{
public static $prefixLengthsPsr4 = array (
+ 'R' =>
+ array (
+ 'RobRichards\\XMLSecLibs\\' => 23,
+ ),
+ 'O' =>
+ array (
+ 'OneLogin\\' => 9,
+ ),
'F' =>
array (
'Firebase\\JWT\\' => 13,
@@ -14,6 +22,14 @@ class ComposerStaticInitcc75f134f7630c1ee3a8e4d7c86f3bcc
);
public static $prefixDirsPsr4 = array (
+ 'RobRichards\\XMLSecLibs\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/robrichards/xmlseclibs/src',
+ ),
+ 'OneLogin\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/onelogin/php-saml/src',
+ ),
'Firebase\\JWT\\' =>
array (
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
@@ -25,25 +41,22 @@ class ComposerStaticInitcc75f134f7630c1ee3a8e4d7c86f3bcc
'Firebase\\JWT\\ExpiredException' => __DIR__ . '/..' . '/firebase/php-jwt/src/ExpiredException.php',
'Firebase\\JWT\\JWT' => __DIR__ . '/..' . '/firebase/php-jwt/src/JWT.php',
'Firebase\\JWT\\SignatureInvalidException' => __DIR__ . '/..' . '/firebase/php-jwt/src/SignatureInvalidException.php',
- 'OneLogin_Saml2_Auth' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Auth.php',
- 'OneLogin_Saml2_AuthnRequest' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/AuthnRequest.php',
- 'OneLogin_Saml2_Constants' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Constants.php',
- 'OneLogin_Saml2_Error' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Error.php',
- 'OneLogin_Saml2_LogoutRequest' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/LogoutRequest.php',
- 'OneLogin_Saml2_LogoutResponse' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/LogoutResponse.php',
- 'OneLogin_Saml2_Metadata' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Metadata.php',
- 'OneLogin_Saml2_Response' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Response.php',
- 'OneLogin_Saml2_Settings' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Settings.php',
- 'OneLogin_Saml2_Utils' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Utils.php',
- 'OneLogin_Saml2_ValidationError' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml2/Error.php',
- 'OneLogin_Saml_AuthRequest' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml/AuthRequest.php',
- 'OneLogin_Saml_Metadata' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml/Metadata.php',
- 'OneLogin_Saml_Response' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml/Response.php',
- 'OneLogin_Saml_Settings' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml/Settings.php',
- 'OneLogin_Saml_XmlSec' => __DIR__ . '/..' . '/onelogin/php-saml/lib/Saml/XmlSec.php',
- 'XMLSecEnc' => __DIR__ . '/..' . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
- 'XMLSecurityDSig' => __DIR__ . '/..' . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
- 'XMLSecurityKey' => __DIR__ . '/..' . '/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php',
+ 'OneLogin\\Saml2\\Auth' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Auth.php',
+ 'OneLogin\\Saml2\\AuthnRequest' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/AuthnRequest.php',
+ 'OneLogin\\Saml2\\Constants' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Constants.php',
+ 'OneLogin\\Saml2\\Error' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Error.php',
+ 'OneLogin\\Saml2\\IdPMetadataParser' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/IdPMetadataParser.php',
+ 'OneLogin\\Saml2\\LogoutRequest' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/LogoutRequest.php',
+ 'OneLogin\\Saml2\\LogoutResponse' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/LogoutResponse.php',
+ 'OneLogin\\Saml2\\Metadata' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Metadata.php',
+ 'OneLogin\\Saml2\\Response' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Response.php',
+ 'OneLogin\\Saml2\\Settings' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Settings.php',
+ 'OneLogin\\Saml2\\Utils' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/Utils.php',
+ 'OneLogin\\Saml2\\ValidationError' => __DIR__ . '/..' . '/onelogin/php-saml/src/Saml2/ValidationError.php',
+ 'RobRichards\\XMLSecLibs\\Utils\\XPath' => __DIR__ . '/..' . '/robrichards/xmlseclibs/src/Utils/XPath.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecEnc' => __DIR__ . '/..' . '/robrichards/xmlseclibs/src/XMLSecEnc.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecurityDSig' => __DIR__ . '/..' . '/robrichards/xmlseclibs/src/XMLSecurityDSig.php',
+ 'RobRichards\\XMLSecLibs\\XMLSecurityKey' => __DIR__ . '/..' . '/robrichards/xmlseclibs/src/XMLSecurityKey.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/3rdparty/vendor/composer/installed.json b/3rdparty/vendor/composer/installed.json
index 77fcbf58..5e69b077 100644
--- a/3rdparty/vendor/composer/installed.json
+++ b/3rdparty/vendor/composer/installed.json
@@ -46,58 +46,94 @@
},
{
"name": "onelogin/php-saml",
- "version": "2.10.5",
- "version_normalized": "2.10.5.0",
+ "version": "v3.0.0",
+ "version_normalized": "3.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/onelogin/php-saml.git",
- "reference": "3319d7707f342e38291eee6b01a4a5f8df1b333b"
+ "reference": "920c2240e48c9a74aad4129720f48fbf3d5fee47"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/onelogin/php-saml/zipball/3319d7707f342e38291eee6b01a4a5f8df1b333b",
- "reference": "3319d7707f342e38291eee6b01a4a5f8df1b333b",
+ "url": "https://api.github.com/repos/onelogin/php-saml/zipball/920c2240e48c9a74aad4129720f48fbf3d5fee47",
+ "reference": "920c2240e48c9a74aad4129720f48fbf3d5fee47",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-mcrypt": "*",
- "ext-openssl": "*",
- "php": ">=5.3.2"
+ "php": ">=5.4",
+ "robrichards/xmlseclibs": "^3.0"
},
"require-dev": {
- "pdepend/pdepend": "1.1.0",
- "phploc/phploc": "*",
- "phpunit/phpunit": "4.8",
- "satooshi/php-coveralls": "1.0.1",
- "sebastian/phpcpd": "*",
- "squizlabs/php_codesniffer": "*"
+ "pdepend/pdepend": "^2.5.0",
+ "php-coveralls/php-coveralls": "^1.0.2 || ^2.0",
+ "phploc/phploc": "^2.1 || ^3.0 || ^4.0",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1",
+ "sebastian/phpcpd": "^2.0 || ^3.0 || ^4.0",
+ "squizlabs/php_codesniffer": "^3.1.1"
},
"suggest": {
+ "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs",
"ext-gettext": "Install gettext and php5-gettext libs to handle translations",
- "ext-mcrypt": "Install mcrypt and php5-mcrypt libs in order to support encryption",
- "lib-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)"
},
- "time": "2017-03-13T09:56:49+00:00",
+ "time": "2018-10-02T16:02:37+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
- "classmap": [
- "extlib/xmlseclibs",
- "lib/Saml",
- "lib/Saml2"
- ]
+ "psr-4": {
+ "OneLogin\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "OneLogin PHP SAML Toolkit",
- "homepage": "https://onelogin.zendesk.com/hc/en-us/sections/200245634-SAML-Toolkits",
+ "homepage": "https://developers.onelogin.com/saml/php",
"keywords": [
"SAML2",
"onelogin",
"saml"
]
+ },
+ {
+ "name": "robrichards/xmlseclibs",
+ "version": "3.0.2",
+ "version_normalized": "3.0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/robrichards/xmlseclibs.git",
+ "reference": "1f4de0c0d121922aafd8c62c2a9f5e528830cf38"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/1f4de0c0d121922aafd8c62c2a9f5e528830cf38",
+ "reference": "1f4de0c0d121922aafd8c62c2a9f5e528830cf38",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "php": ">= 5.4"
+ },
+ "time": "2018-09-27T13:24:13+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "RobRichards\\XMLSecLibs\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "A PHP library for XML Security",
+ "homepage": "https://github.com/robrichards/xmlseclibs",
+ "keywords": [
+ "security",
+ "signature",
+ "xml",
+ "xmldsig"
+ ]
}
]
diff --git a/3rdparty/vendor/onelogin/php-saml/.coveralls.yml b/3rdparty/vendor/onelogin/php-saml/.coveralls.yml
deleted file mode 100644
index 173ff356..00000000
--- a/3rdparty/vendor/onelogin/php-saml/.coveralls.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-service_name: travis-ci
-
-src_dir: lib
-
-coverage_clover: tests/build/logs/clover.xml
-
-json_path: tests/build/logs/coveralls-upload.json
diff --git a/3rdparty/vendor/onelogin/php-saml/.gitignore b/3rdparty/vendor/onelogin/php-saml/.gitignore
deleted file mode 100644
index 239418ab..00000000
--- a/3rdparty/vendor/onelogin/php-saml/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-*.swp
-*~
-.DS_Store
-/settings.php
-/demo1/settings.php
-/demo-old/settings.php
-/certs/sp.key
-/certs/sp.crt
-/certs/metadata.key
-/certs/metadata.crt
-/tests/build
-/vendor
-/composer.lock
-/.idea
diff --git a/3rdparty/vendor/onelogin/php-saml/.travis.yml b/3rdparty/vendor/onelogin/php-saml/.travis.yml
deleted file mode 100644
index 648e8cc0..00000000
--- a/3rdparty/vendor/onelogin/php-saml/.travis.yml
+++ /dev/null
@@ -1,36 +0,0 @@
-language: php
-
-php:
- - 5.6
- - 5.5
- - 5.4
-# - 5.3
- - 7.0
-
-env:
- - TRAVIS=true
-
-matrix:
- fast_finish: true
-
-before_install:
- - composer self-update || true
- - composer install --prefer-source --no-interaction
-
-before_script:
- - phpenv config-rm xdebug.ini
-
-script:
- - vendor/bin/phpunit --bootstrap tests/bootstrap.php --configuration tests/phpunit.xml
- - php vendor/bin/phpcpd --exclude tests --exclude vendor .
- - php vendor/bin/phploc . --exclude vendor
- - php vendor/bin/phploc lib/.
- - 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 lib/.
- - php vendor/bin/phpcs --standard=tests/ZendModStandard lib/Saml2 demo1 demo2 demo-old endpoints tests/src
-
-after_script:
- - export TRAVIS=https://travis-ci.org/onelogin/php-saml
- - echo $TRAVIS
- - echo $TRAVIS_JOB_ID
- - php vendor/bin/coveralls --config .coveralls.yml -v
diff --git a/3rdparty/vendor/onelogin/php-saml/CHANGELOG b/3rdparty/vendor/onelogin/php-saml/CHANGELOG
index bdb23be5..31fe880f 100644
--- a/3rdparty/vendor/onelogin/php-saml/CHANGELOG
+++ b/3rdparty/vendor/onelogin/php-saml/CHANGELOG
@@ -1,5 +1,35 @@
CHANGELOG
=========
+
+v.3.0.0 (pending)
+* Remove mcrypt dependency. Compatible with PHP 7.2
+* xmlseclibs now is not part of the toolkit and need to be installed from original source
+
+v.2.12.0
+* Improve Time management. Use DateTime/DateTimeZone classes.
+* Escape error messages in debug mode
+* Improve phpdoc
+* Add an extra filter to the url to be used on redirection
+
+* [#242](https://github.com/onelogin/php-saml/pull/242) Document that SHA-1 must not be used
+* [#250](https://github.com/onelogin/php-saml/pull/250) Fixed issue with IdPMetadataParser only keeping 1 certificate when multiple certificates of a single type were provided.
+* [#263](https://github.com/onelogin/php-saml/issues/263) Fix incompatibility with ADFS on SLO. When on php saml settings NameID Format is set as unspecified but the SAMLResponse has no NameID Format, no NameID Format should be specified on LogoutRequest.
+
+v.2.11.0
+* [#236](https://github.com/onelogin/php-saml/pull/236) Exclude unnecesary files from Composer production downloads
+* [#226](https://github.com/onelogin/php-saml/pull/226) Add possibility to handle nameId NameQualifier attribute in SLO Request
+* Improve logout documentation on Readme.
+* Improve multi-certificate support
+
+v.2.10.7
+* Fix IdPMetadataParser. The SingleLogoutService retrieved method was wrong
+* [#201](https://github.com/onelogin/php-saml/issues/201) Fix issues with SP entity_id, acs url and sls url that contains &
+
+v.2.10.6
+* [#206](https://github.com/onelogin/php-saml/pull/206)Be able to register future SP x509cert on the settings and publish it on SP metadata
+* [#206](https://github.com/onelogin/php-saml/pull/206) Be able to register more than 1 Identity Provider x509cert, linked with an specific use (signing or encryption)
+* [#206](https://github.com/onelogin/php-saml/pull/206) Support the ability to parse IdP XML metadata (remote url or file) and be able to inject the data obtained on the settings.
+
v.2.10.5
* Be able to get at the auth object the last processed ID
* Improve NameID Format support
diff --git a/3rdparty/vendor/onelogin/php-saml/README.md b/3rdparty/vendor/onelogin/php-saml/README.md
index 1e43b95c..15402b6c 100644
--- a/3rdparty/vendor/onelogin/php-saml/README.md
+++ b/3rdparty/vendor/onelogin/php-saml/README.md
@@ -1,22 +1,16 @@
-# OneLogin's SAML PHP Toolkit
+# OneLogin's SAML PHP Toolkit Compatible with PHP 5.X & 7.X
[![Build Status](https://api.travis-ci.org/onelogin/php-saml.png?branch=master)](http://travis-ci.org/onelogin/php-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/php-saml/badge.png)](https://coveralls.io/r/onelogin/php-saml) [![License](https://poser.pugx.org/onelogin/php-saml/license.png)](https://packagist.org/packages/onelogin/php-saml)
-Add SAML support to your PHP softwares using this library.
-Forget those complicated libraries and use that open source library provided
+Add SAML support to your PHP software using this library.
+Forget those complicated libraries and use this open source library provided
and supported by OneLogin Inc.
Warning
-------
-Update php-saml to 2.10.4, this version includes a security patch related to
-[signature validations on LogoutRequests/LogoutResponses](https://github.com/onelogin/php-saml/commit/949359f5cad5e1d085c4e5447d9aa8f49a6e82a1)
-
-Update php-saml to 2.10.0, this version includes a security patch that contains extra validations that will prevent signature wrapping attacks. [CVE-2016-1000253](https://github.com/distributedweaknessfiling/DWF-Database-Artifacts/blob/ab8ae6e845eb506fbeb10a7e4ccb379f0b4222ca/DWF/2016/1000253/CVE-2016-1000253.json)
-
-php-saml < v2.10.0 is vulnerable and allows signature wrapping!
-
+This version is compatible with PHP 7.X and does not include xmlseclibs (you will need to install it via composer, dependency described in composer.json)
Security Guidelines
-------------------
@@ -81,13 +75,10 @@ Installation
### Dependencies ###
- * `php >= 5.3.3` and some core extensions like `php-xml`, `php-date`, `php-zlib`.
+ * `php >= 5.4` and some core extensions like `php-xml`, `php-date`, `php-zlib`.
* `openssl`. Install the openssl library. It handles x509 certificates.
- * `mcrypt`. Install that library and its php driver if you gonna handle
- encrypted data (`nameID`, `assertions`).
* `gettext`. Install that library and its php driver. It handles translations.
-
-Since [PHP 5.3 is officially unsupported](http://php.net/eol.php) we recommend you to use a newer PHP version.
+ * `curl`. Install that library and its php driver if you plan to use the IdP Metadata parser.
### Code ###
@@ -95,8 +86,9 @@ Since [PHP 5.3 is officially unsupported](http://php.net/eol.php) we recommend y
The toolkit is hosted on github. You can download it from:
- * Lastest release: https://github.com/onelogin/php-saml/releases/latest
- * Master repo: https://github.com/onelogin/php-saml/tree/master
+ * https://github.com/onelogin/php-saml/releases
+
+Search for 3.X.X releases
Copy the core of the library inside the php application. (each application has its
structure so take your time to locate the PHP SAML toolkit in the best place).
@@ -111,49 +103,39 @@ In order to import the saml toolkit to your current php project, execute
composer require onelogin/php-saml
```
+Remember to select the 3.X.X branch
+
After installation has completed you will find at the `vendor/` folder a new folder named `onelogin` and inside the `php-saml`. Make sure you are including the autoloader provided by composer. It can be found at `vendor/autoload.php`.
**Important** In this option, the x509 certs must be stored at `vendor/onelogin/php-saml/certs`
and settings file stored at `vendor/onelogin/php-saml`.
-Your settings are at risk of being deleted when updating packages using `composer update` or similiar commands. So it is **highly** recommended that instead of using settings files, you pass the settings as an array directly to the constructor (explained later in this document). If you do not use this approach your settings are at risk of being deleted when updating packages using `composer update` or similiar commands.
+Your settings are at risk of being deleted when updating packages using `composer update` or similar commands. So it is **highly** recommended that instead of using settings files, you pass the settings as an array directly to the constructor (explained later in this document). If you do not use this approach your settings are at risk of being deleted when updating packages using `composer update` or similar commands.
Compatibility
-------------
-This 2.0 version has a new library. The toolkit is still compatible.
-
-The old code that you used in order to add SAML support gonna continue working
-with minor changes. You only need to load the files of the `lib/Saml` folder.
-(notice that the `compatibility.php` file do that).
-
-The old-demo folder contains code from an old app that uses the old version of
-the toolkit (v.1). Take a look.
-
-Sometimes the names of the classes of the old code could be a bit different
-and if that is your case you must change them for `OneLogin_Saml_Settings`,
-`OneLogin_Saml_Response`, `OneLogin_Saml_AuthRequest` or `OneLogin_Saml_Metadata`.
-
-We recommend that you migrate the old code to the new one to be able to use
-the new features that the new library Saml2 carries.
-
+This 3.X.X supports PHP 7.X. but can be used with PHP >=5.4 as well (5.6.24+ recommended for security reasons).
Namespaces
----------
-If you are using the library with a framework like Symfony2 that contains
+If you are using the library with a framework like Symfony that contains
namespaces, remember that calls to the class must be done by adding a backslash (`\`) to the
start, for example to use the static method getSelfURLNoQuery use:
- \OneLogin_Saml2_Utils::getSelfURLNoQuery()
+ \OneLogin\Saml2\Utils::getSelfURLNoQuery()
Security warning
----------------
-In production, the `strict` parameter **MUST** be set as `"true"`. Otherwise
-your environment is not secure and will be exposed to attacks.
+In production, the `strict` parameter **MUST** be set as `"true"` and the
+`signatureAlgorithm` and `digestAlgorithm` under `security` must be set to
+something other than SHA1 (see https://shattered.io/ ). Otherwise your
+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.
Getting started
---------------
@@ -161,43 +143,35 @@ Getting started
### Knowing the toolkit ###
The new OneLogin SAML Toolkit contains different folders (`certs`, `endpoints`,
-`extlib`, `lib`, `demo`, etc.) and some files.
+`lib`, `demo`, etc.) and some files.
Let's start describing the folders:
#### `certs/` ####
-SAML requires a x.509 cert to sign and encrypt elements like `NameID`, `Message`,
+SAML requires a x509 cert to sign and encrypt elements like `NameID`, `Message`,
`Assertion`, `Metadata`.
If our environment requires sign or encrypt support, this folder may contain
the x509 cert and the private key that the SP will use:
* `sp.crt` - The public cert of the SP
- * `sp.key` - The privake key of the SP
+ * `sp.key` - The private key of the SP
Or also we can provide those data in the setting file at the `$settings['sp']['x509cert']`
and the `$settings['sp']['privateKey']`.
Sometimes we could need a signature on the metadata published by the SP, in
-this case we could use the x.509 cert previously mentioned or use a new x.509
+this case we could use the x509 cert previously mentioned or use a new x.509
cert: `metadata.crt` and `metadata.key`.
+Use `sp_new.crt` if you are in a key rollover process and you want to
+publish that x509 certificate on Service Provider metadata.
-#### `extlib/` ####
-
-This folder contains the 3rd party libraries that the toolkit uses. At the
-moment only uses the `xmlseclibs` (autor Robert Richards, BSD Licensed) which
-handle the sign and the encryption of xml elements.
-
-
-#### `lib/` ####
+#### `src/` ####
This folder contains the heart of the toolkit, the libraries:
- * `Saml` folder contains a modified version of the toolkit v.1 and allows the
- old code to keep working. (This library is provided to maintain
- backward compatibility).
* `Saml2` folder contains the new version of the classes and methods that
are described in a later section.
@@ -236,8 +210,6 @@ and support multiple languages.
advanced_settings.php file which contains extra configuration info related to
the security, the contact person, and the organization associated to the SP.
* `_toolkit_loader.php` - This file load the toolkit libraries (The SAML2 lib).
-* `compatibility` - Import that file to make compatible your old code with the
- new toolkit (loads the SAML library).
#### Miscellaneous ####
@@ -246,8 +218,6 @@ and support multiple languages.
* `demo1/` - Contains an example of a simple PHP app with SAML support.
Read the `Readme.txt` inside for more info.
* `demo2/` - Contains another example.
-* `demo-old/` - Contains an example that uses the code of the older version of the
- the toolkit to demonstrate the backwards compatibility.
### How it works ###
@@ -272,7 +242,7 @@ file, rename and edit it.
```php
<?php
-$settings = array (
+$settings = array(
// If 'strict' is True, then the PHP Toolkit will reject unsigned
// or unencrypted messages if it expects them to be signed or encrypted.
// Also it will reject the messages if the SAML standard is not strictly
@@ -285,16 +255,16 @@ $settings = array (
// Set a BaseURL to be used instead of try to guess
// the BaseURL of the view that process the SAML Message.
// Ex http://sp.example.com/
- // http://example.com/sp/
+ // http://example.com/sp/
'baseurl' => null,
// Service Provider Data that we are deploying.
- 'sp' => array (
+ 'sp' => array(
// Identifier of the SP entity (must be a URI)
'entityId' => '',
// Specifies info about where and how the <AuthnResponse> message MUST be
// returned to the requester, in this case our SP.
- 'assertionConsumerService' => array (
+ 'assertionConsumerService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -319,8 +289,8 @@ $settings = array (
)
),
// Specifies info about where and how the <Logout Response> message MUST be
- // returned to the requester, in this case our SP.
- 'singleLogoutService' => array (
+ // returned to the requester, in this case our SP.
+ 'singleLogoutService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -337,14 +307,22 @@ $settings = array (
'x509cert' => '',
'privateKey' => '',
+ /*
+ * Key rollover
+ * If you plan to update the SP x509cert and privateKey
+ * you can define here the new x509cert and it will be
+ * published on the SP metadata so Identity Providers can
+ * read them and get ready for rollover.
+ */
+ // 'x509certNew' => '',
),
// Identity Provider Data that we want connected with our SP.
- 'idp' => array (
+ 'idp' => array(
// Identifier of the IdP entity (must be a URI)
'entityId' => '',
// SSO endpoint info of the IdP. (Authentication Request protocol)
- 'singleSignOnService' => array (
+ 'singleSignOnService' => array(
// URL Target of the IdP where the Authentication Request Message
// will be sent.
'url' => '',
@@ -354,7 +332,7 @@ $settings = array (
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
),
// SLO endpoint info of the IdP.
- 'singleLogoutService' => array (
+ 'singleLogoutService' => array(
// URL Location of the IdP where SLO Request will be sent.
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -366,7 +344,8 @@ $settings = array (
'x509cert' => '',
/*
* Instead of use the whole x509cert you can use a fingerprint in order to
- * validate a SAMLResponse.
+ * validate a SAMLResponse, but we don't recommend to use that
+ * method on production since is exploitable by a collision attack.
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
* or add for example the -sha256 , -sha384 or -sha512 parameter)
*
@@ -379,6 +358,22 @@ $settings = array (
*/
// 'certFingerprint' => '',
// 'certFingerprintAlgorithm' => 'sha1',
+
+ /* In some scenarios the IdP uses different certificates for
+ * signing/encryption, or is under key rollover phase and
+ * more than one certificate is published on IdP metadata.
+ * In order to handle that the toolkit offers that parameter.
+ * (when used, 'x509cert' and 'certFingerprint' values are
+ * ignored).
+ */
+ // 'x509certMulti' => array(
+ // 'signing' => array(
+ // 0 => '<cert1-string>',
+ // ),
+ // 'encryption' => array(
+ // 0 => '<cert2-string>',
+ // )
+ // ),
),
);
```
@@ -391,15 +386,15 @@ that you can copy and rename it as `advanced_settings.php`
```php
<?php
-$advancedSettings = array (
+$advancedSettings = array(
// Compression settings
- 'compress' => array (
+ 'compress' => array(
'requests' => true,
'responses' => true
),
// Security settings
- 'security' => array (
+ 'security' => array(
/** signatures and encryptions offered */
@@ -420,14 +415,13 @@ $advancedSettings = array (
'logoutResponseSigned' => false,
/* Sign the Metadata
- False || True (use sp certs) || array (
+ False || True (use sp certs) || array(
keyFileName => 'metadata.key',
certFileName => 'metadata.crt'
)
*/
'signMetadata' => false,
-
/** signatures and encryptions required **/
// Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest>
@@ -450,11 +444,10 @@ $advancedSettings = array (
// this SP to be encrypted.
'wantNameIdEncrypted' => false,
-
// Authentication context.
- // Set to false or don't present this parameter and no AuthContext will be sent in the AuthNRequest,
- // Set true and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
- // Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'),
+ // Set to false and no AuthContext will be sent in the AuthNRequest.
+ // Set true or don't present this parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
+ // Set an array with the possible auth context values: array('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509').
'requestedAuthnContext' => true,
// Indicates if the SP will validate all received xmls.
@@ -471,14 +464,16 @@ $advancedSettings = array (
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
- 'signatureAlgorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
+ // Notice that rsa-sha1 is a deprecated algorithm and should not be used
+ 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
// Algorithm that the toolkit will use on digest process. Options:
// 'http://www.w3.org/2000/09/xmldsig#sha1'
// 'http://www.w3.org/2001/04/xmlenc#sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#sha384'
// 'http://www.w3.org/2001/04/xmlenc#sha512'
- 'digestAlgorithm' => 'http://www.w3.org/2000/09/xmldsig#sha1',
+ // Notice that sha1 is a deprecated algorithm and should not be used
+ 'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
@@ -487,12 +482,12 @@ $advancedSettings = array (
// Contact information template, it is recommended to supply a
// technical and support contacts.
- 'contactPerson' => array (
- 'technical' => array (
+ 'contactPerson' => array(
+ 'technical' => array(
'givenName' => '',
'emailAddress' => ''
),
- 'support' => array (
+ 'support' => array(
'givenName' => '',
'emailAddress' => ''
),
@@ -500,7 +495,7 @@ $advancedSettings = array (
// Organization information template, the info in en_US lang is
// recomended, add more if required.
- 'organization' => array (
+ 'organization' => array(
'en-US' => array(
'name' => '',
'displayname' => '',
@@ -512,7 +507,7 @@ $advancedSettings = array (
The compression settings allow you to instruct whether or not the IdP can accept
data that has been compressed using [gzip](gzip) ('requests' and 'responses').
-But if we provide a $deflate boolean parameter to the getRequest or getResponse method it will have priority over the compression settings.
+But if we provide a `$deflate` boolean parameter to the `getRequest` or `getResponse` method it will have priority over the compression settings.
In the security section, you can set the way that the SP will handle the messages
and assertions. Contact the admin of the IdP and ask him what the IdP expects,
@@ -523,21 +518,21 @@ Once we know what kind of data could be configured, let's talk about the way
settings are handled within the toolkit.
The settings files described (`settings.php` and `advanced_settings.php`) are loaded
-by the toolkit if not other array with settings info is provided in the constructors of the toolkit. Let's see some examples.
+by the toolkit if no other array with settings info is provided in the constructor of the toolkit. Let's see some examples.
```php
// Initializes toolkit with settings.php & advanced_settings files.
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
//or
-$settings = new OneLogin_Saml2_Settings();
+$settings = new OneLogin\Saml2\Settings();
// Initializes toolkit with the array provided.
-$auth = new OneLogin_Saml2_Auth($settingsInfo);
+$auth = new OneLogin\Saml2\Auth($settingsInfo);
//or
-$settings = new OneLogin_Saml2_Settings($settingsInfo);
+$settings = new OneLogin\Saml2\Settings($settingsInfo);
```
-You can declare the `$settingsInfo` in the file that constains the constructor
+You can declare the `$settingsInfo` in the file that contains the constructor
execution or locate them in any file and load the file in order to get the
array available as we see in the following example:
@@ -547,15 +542,19 @@ array available as we see in the following example:
require_once 'custom_settings.php'; // The custom_settings.php contains a
// $settingsInfo array.
-$auth = new OneLogin_Saml2_Auth($settingsInfo);
+$auth = new OneLogin\Saml2\Auth($settingsInfo);
```
#### How load the library ####
-In order to use the toolkit library you need to import the `_toolkit_loader.php`
-file located on the base folder of the toolkit. You can load this file in this
-way:
+
+In order to use the toolkit library, if your project support composer you only
+need to install it with composer (See the installation section) and you are done.
+
+
+If your project doesn't use composer you need to import the `_toolkit_loader.php`
+file located on the base folder of the toolkit. You can load this file in this way:
```php
<?php
@@ -567,17 +566,9 @@ require_once(TOOLKIT_PATH . '_toolkit_loader.php');
After that line we will be able to use the classes (and their methods) of the
toolkit (because the external and the Saml2 libraries files are loaded).
-If you wrote the code of your SAML app for the version 1 of the PHP-SAML toolkit
-you will need to load the `compatibility.php`, file which loads the SAML library files,
-in addition to the the `_toolkit_loader.php`.
-
-That SAML library uses the new classes and methods of the latest version of the
-toolkits but maintain the old classes, methods, and workflow of the old process
-to accomplish the same things.
-
-We strongly recommend migrating your old code and use the new API of the
-new toolkit due there are a lot of new features that you can't handle with the
-old code.
+That toolkit depends on [xmlseclibs](https://github.com/robrichards/xmlseclibs) 3.X.X branch,
+you will need to get its code and place on your project and reuse the _toolkit_loader.php
+file to include xmlseclibs as well.
#### Initiate SSO ####
@@ -590,7 +581,7 @@ In order to send an `AuthNRequest` to the IdP:
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once(TOOLKIT_PATH . '_toolkit_loader.php'); // We load the SAML2 lib
-$auth = new OneLogin_Saml2_Auth(); // Constructor of the SP, loads settings.php
+$auth = new OneLogin\Saml2\Auth(); // Constructor of the SP, loads settings.php
// and advanced_settings.php
$auth->login(); // Method that sent the AuthNRequest
```
@@ -599,13 +590,13 @@ The `AuthNRequest` will be sent signed or unsigned based on the security info
of the `advanced_settings.php` (`'authnRequestsSigned'`).
-The IdP will then return the SAML Response to the user's client. The client is then forwarded to the Attribute Consumer Service of the SP with this information. If we do not set a 'url' param in the login method and we are using the default ACS provided by the toolkit (`endpoints/acs.php`), then the ACS endpoint will redirect the user to the file that launched the SSO request.
+The IdP will then return the SAML Response to the user's client. The client is then forwarded to the Attribute Consumer Service of the SP with this information. If we do not set a `'url'` param in the login method and we are using the default ACS provided by the toolkit (`endpoints/acs.php`), then the ACS endpoint will redirect the user to the file that launched the SSO request.
-We can set an `'returnTo'` url to change the workflow and redirect the user to the other PHP file.
+We can set a `'returnTo'` url to change the workflow and redirect the user to the other PHP file.
```php
$newTargetUrl = 'http://example.com/consume2.php';
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
$auth->login($newTargetUrl);
```
@@ -644,7 +635,7 @@ define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
try {
- $auth = new OneLogin_Saml2_Auth();
+ $auth = new OneLogin\Saml2\Auth();
$settings = $auth->getSettings();
$metadata = $settings->getSPMetadata();
$errors = $settings->validateMetadata($metadata);
@@ -652,9 +643,9 @@ try {
header('Content-Type: text/xml');
echo $metadata;
} else {
- throw new OneLogin_Saml2_Error(
+ throw new OneLogin\Saml2\Error(
'Invalid SP metadata: '.implode(', ', $errors),
- OneLogin_Saml2_Error::METADATA_SP_INVALID
+ OneLogin\Saml2\Error::METADATA_SP_INVALID
);
}
} catch (Exception $e) {
@@ -668,8 +659,9 @@ Before the XML metadata is exposed, a check takes place to ensure
that the info to be provided is valid.
Instead of use the Auth object, you can directly use
-```
-$settings = new OneLogin_Saml2_Settings($settingsInfo, true);
+
+```php
+$settings = new OneLogin\Saml2\Settings($settingsInfo, true);
```
to get the settings object and with the true parameter we will avoid the IdP Settings validation.
@@ -687,7 +679,7 @@ session_start(); // IMPORTANT: This is required in order to be able
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
@@ -696,11 +688,12 @@ if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) {
}
$auth->processResponse($requestID);
+unset($_SESSION['AuthNRequestID']);
$errors = $auth->getErrors();
if (!empty($errors)) {
- print_r('<p>'.implode(', ', $errors).'</p>');
+ echo '<p>' . implode(', ', $errors) . '</p>';
exit();
}
@@ -711,7 +704,12 @@ if (!$auth->isAuthenticated()) {
$_SESSION['samlUserdata'] = $auth->getAttributes();
$_SESSION['samlNameId'] = $auth->getNameId();
-if (isset($_POST['RelayState']) && OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
+$_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
+$_SESSION['samlNameidNameQualifier' = $auth->getNameIdNameQualifier();
+$_SESSION['samlNameidSPNameQualifier' = $auth->getNameIdSPNameQualifier();
+$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
+
+if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
$auth->redirectTo($_POST['RelayState']);
}
@@ -721,8 +719,8 @@ $nameId = $_SESSION['samlNameId'];
echo '<h1>Identified user: '. htmlentities($nameId) .'</h1>';
if (!empty($attributes)) {
- echo '<h2>'._('User attributes:').'</h2>';
- echo '<table><thead><th>'._('Name').'</th><th>'._('Values').'</th></thead><tbody>';
+ echo '<h2>' . _('User attributes:') . '</h2>';
+ echo '<table><thead><th>' . _('Name') . '</th><th>' . _('Values') . '</th></thead><tbody>';
foreach ($attributes as $attributeName => $attributeValues) {
echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
foreach ($attributeValues as $attributeValue) {
@@ -823,7 +821,7 @@ session_start(); // IMPORTANT: This is required in order to be able
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
$requestID = $_SESSION['LogoutRequestID'];
@@ -836,9 +834,9 @@ $auth->processSLO(false, $requestID);
$errors = $auth->getErrors();
if (empty($errors)) {
- print_r('Sucessfully logged out');
+ echo 'Sucessfully logged out';
} else {
- print_r(implode(', ', $errors));
+ echo implode(', ', $errors);
}
```
@@ -850,14 +848,14 @@ validated and the session could be closed
```php
// part of the processSLO method
-$logoutResponse = new OneLogin_Saml2_LogoutResponse($this->_settings, $_GET['SAMLResponse']);
+$logoutResponse = new OneLogin\Saml2\LogoutResponse($this->_settings, $_GET['SAMLResponse']);
if (!$logoutResponse->isValid($requestId)) {
$this->_errors[] = 'invalid_logout_response';
-} else if ($logoutResponse->getStatus() !== OneLogin_Saml2_Constants::STATUS_SUCCESS) {
+} else if ($logoutResponse->getStatus() !== OneLogin\Saml2\Constants::STATUS_SUCCESS) {
$this->_errors[] = 'logout_not_success';
} else {
if (!$keepLocalSession) {
- OneLogin_Saml2_Utils::deleteLocalSession();
+ OneLogin\Saml2\Utils::deleteLocalSession();
}
}
```
@@ -871,15 +869,15 @@ the IdP.
$decoded = base64_decode($_GET['SAMLRequest']);
$request = gzinflate($decoded);
-if (!OneLogin_Saml2_LogoutRequest::isValid($this->_settings, $request)) {
+if (!OneLogin\Saml2\LogoutRequest::isValid($this->_settings, $request)) {
$this->_errors[] = 'invalid_logout_request';
} else {
if (!$keepLocalSession) {
- OneLogin_Saml2_Utils::deleteLocalSession();
+ OneLogin\Saml2\Utils::deleteLocalSession();
}
$inResponseTo = $request->id;
- $responseBuilder = new OneLogin_Saml2_LogoutResponse($this->_settings);
+ $responseBuilder = new OneLogin\Saml2\LogoutResponse($this->_settings);
$responseBuilder->build($inResponseTo);
$logoutResponse = $responseBuilder->getResponse();
@@ -931,17 +929,21 @@ In order to send a Logout Request to the IdP:
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once(TOOLKIT_PATH . '_toolkit_loader.php');
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
$auth->logout(); // Method that sent the Logout Request.
```
-Also there are three optional parameters that can be set:
-
+Also there are eight optional parameters that can be set:
+* `$returnTo` - The target URL the user should be returned to after logout.
+* `$parameters` - Extra parameters to be added to the GET.
* `$name_id` - That will be used to build the LogoutRequest. If `name_id` parameter is not set and the auth object processed a
SAML Response with a `NameId`, then this `NameId` will be used.
* `$session_index` - SessionIndex that identifies the session of the user.
-* `$strict` - True if we want to stay (returns the url string) False to redirect.
+* `$stay` - True if we want to stay (returns the url string) False to redirect.
+* `$nameIdFormat` - The NameID Format will be set in the LogoutRequest.
+* `$nameIdNameQualifier` - The NameID NameQualifier will be set in the LogoutRequest.
+* `$nameIdSPNameQualifier` - The NameID SP NameQualifier will be set in the LogoutRequest.
The Logout Request will be sent signed or unsigned based on the security
info of the `advanced_settings.php` (`'logoutRequestSigned'`).
@@ -957,9 +959,37 @@ to other php file.
```php
$newTargetUrl = 'http://example.com/loggedOut.php';
-$auth = new OneLogin_Saml2_Auth();
+$auth = new OneLogin\Saml2\Auth();
$auth->logout($newTargetUrl);
```
+A more complex logout with all the parameters:
+```
+$auth = new OneLogin\Saml2\Auth();
+$returnTo = null;
+$paramters = array();
+$nameId = null;
+$sessionIndex = null;
+$nameIdFormat = null;
+$nameIdNameQualifier = null;
+$nameIdSPNameQualifier = null;
+
+if (isset($_SESSION['samlNameId'])) {
+ $nameId = $_SESSION['samlNameId'];
+}
+if (isset($_SESSION['samlSessionIndex'])) {
+ $sessionIndex = $_SESSION['samlSessionIndex'];
+}
+if (isset($_SESSION['samlNameIdFormat'])) {
+ $nameIdFormat = $_SESSION['samlNameIdFormat'];
+}
+if (isset($_SESSION['samlNameIdNameQualifier'])) {
+ $nameIdNameQualifier = $_SESSION['samlNameIdNameQualifier'];
+}
+if (isset($_SESSION['samlNameIdSPNameQualifier'])) {
+ $nameIdSPNameQualifier = $_SESSION['samlNameIdSPNameQualifier'];
+}
+$auth->logout($returnTo, $paramters, $nameId, $sessionIndex, false, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
+```
If a match on the future LogoutResponse ID and the LogoutRequest ID to be sent is required, that LogoutRequest ID must to be extracted and stored.
@@ -987,11 +1017,10 @@ session_start(); // Initialize the session, we do that because
// Note that processResponse and processSLO
// methods could manipulate/close that session
-require_once dirname(dirname(__FILE__)).'/_toolkit_loader.php'; // Load Saml2 and
- // external libs
+require_once dirname(__DIR__) . '/_toolkit_loader.php'; // Load Saml2 and xmlseclibs
require_once 'settings.php'; // Load the setting info as an Array
-$auth = new OneLogin_Saml2_Auth($settingsInfo); // Initialize the SP SAML instance
+$auth = new OneLogin\Saml2\Auth($settingsInfo); // Initialize the SP SAML instance
if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the IdP
$auth->login();
@@ -1009,25 +1038,25 @@ if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the I
// that could took place during the process
if (!empty($errors)) {
- print_r('<p>'.implode(', ', $errors).'</p>');
+ echo '<p>' . implode(', ', $errors) . '</p>';
}
// This check if the response was
if (!$auth->isAuthenticated()) { // sucessfully validated and the user
- echo "<p>Not authenticated</p>"; // data retrieved or not
+ echo '<p>Not authenticated</p>'; // data retrieved or not
exit();
}
$_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']) {
$auth->redirectTo($_POST['RelayState']); // Redirect if there is a
} // relayState set
} else if (isset($_GET['sls'])) { // Single Logout Service
$auth->processSLO(); // Process the Logout Request & Logout Response
$errors = $auth->getErrors(); // Retrieves possible validation errors
if (empty($errors)) {
- print_r('<p>Sucessfully logged out</p>');
+ echo '<p>Sucessfully logged out</p>';
} else {
- print_r('<p>'.implode(', ', $errors).'</p>');
+ echo '<p>' . implode(', ', $errors) . '</p>';
}
}
@@ -1056,8 +1085,8 @@ if (isset($_SESSION['samlUserdata'])) { // If there is user data we print it.
```
#### URL-guessing methods ####
-
-php-saml toolkit uses a bunch of methods in OneLogin_Saml2_Utils that try to guess the URL where the SAML messages are processed.
+
+php-saml toolkit uses a bunch of methods in OneLogin\Saml2\Utils that try to guess the URL where the SAML messages are processed.
* `getSelfHost` Returns the current host.
* `getSelfPort` Return the port number used for the request
@@ -1069,11 +1098,11 @@ php-saml toolkit uses a bunch of methods in OneLogin_Saml2_Utils that try to gue
getSelfURLNoQuery and getSelfRoutedURLNoQuery are used to calculate the currentURL in order to valdate SAML elements like Destination or Recipient.
-When the PHP application is behind a proxy or a load balancer we can execute setProxyVars(true) and getSelfPort and isHTTPS will take care of the $_SERVER["HTTP_X_FORWARDED_PORT"] and $_SERVER['HTTP_X_FORWARDED_PROTO'] vars (otherwise they are ignored).
+When the PHP application is behind a proxy or a load balancer we can execute `setProxyVars(true)` and `setSelfPort` and `isHTTPS` will take care of the `$_SERVER["HTTP_X_FORWARDED_PORT"]` and `$_SERVER['HTTP_X_FORWARDED_PROTO']` vars (otherwise they are ignored).
-Also a developer can use setSelfProtocol, setSelfHost, setSelfPort and getBaseURLPath to define a specific value to be returned by isHTTPS, getSelfHost, getSelfPort and getBaseURLPath. And define a setBasePath to be used on the getSelfURL and getSelfRoutedURLNoQuery to replace the data extracted from $_SERVER["REQUEST_URI"].
+Also a developer can use `setSelfProtocol`, `setSelfHost`, `setSelfPort` and `getBaseURLPath` to define a specific value to be returned by `isHTTPS`, `getSelfHost`, `getSelfPort` and `getBaseURLPath`. And define a `setBasePath` to be used on the `getSelfURL` and `getSelfRoutedURLNoQuery` to replace the data extracted from `$_SERVER["REQUEST_URI"]`.
-At the settings the developer will be able to set a 'baseurl' parameter that automatically will use setBaseURL to set values for setSelfProtocol, setSelfHost, setSelfPort and setBaseURLPath.
+At the settings the developer will be able to set a `'baseurl'` parameter that automatically will use `setBaseURL` to set values for `setSelfProtocol`, `setSelfHost`, `setSelfPort` and `setBaseURLPath`.
### Working behind load balancer ###
@@ -1085,68 +1114,46 @@ You should be able to workaround this by configuring your server so that it is a
Or by using the method described on the previous section.
-### Reply attacks ###
-
-In order to avoid reply attacks, you can store the ID of the SAML messages already processed, to avoid processing them twice. Since the Messages expires and will be invalidated due that fact, you don't need to store those IDs longer than the time frame that you currently accepting.
-
-Get the ID of the last processed message/assertion with the getLastMessageId/getLastAssertionId method of the Auth object.
-
-
-### Main classes and methods ###
-
-Described below are the main classes and methods that can be invoked.
-
-#### The Old Saml library ####
-
-Lets start describing the classes and methods of the SAML library, an evolution
-of the old v.1 toolkit that is provided to keep the backward compability.
-Most of them use classes and methods of the new SAML2 library.
+### SP Key rollover ###
-##### OneLogin_Saml_AuthRequest - `AuthRequest.php` #####
+If you plan to update the SP x509cert and privateKey you can define the new x509cert as `$settings['sp']['x509certNew']` and it will be
+published on the SP metadata so Identity Providers can read them and get ready for rollover.
-Has the protected attribute `$auth`, an `OneLogin_Saml2_Auth` object.
-* `OneLogin_Saml_AuthRequest` - Constructs `OneLogin_Saml2_Auth`,
- initializing the SP SAML instance.
-* `getRedirectUrl($returnTo)` - Obtains the SSO URL containing the AuthRequest
- message deflated.
+### IdP with multiple certificates ###
+In some scenarios the IdP uses different certificates for
+signing/encryption, or is under key rollover phase and more than one certificate is published on IdP metadata.
-##### OneLogin_Saml_Response - `Response.php` #####
+In order to handle that the toolkit offers the `$settings['idp']['x509certMulti']` parameter.
-* `OneLogin_Saml_Response` - Constructor that process the SAML Response,
- Internally initializes an SP SAML instance and an `OneLogin_Saml2_Response`.
-* `get_saml_attributes` - Retrieves an Array with the logged user data.
+When that parameter is used, `'x509cert'` and `'certFingerprint'` values will be ignored by the toolkit.
+The `x509certMulti` is an array with 2 keys:
+- `signing`. An array of certs that will be used to validate IdP signature
+- `encryption` An array with one unique cert that will be used to encrypt data to be sent to the IdP
-##### OneLogin_Saml_Settings - `Settings.php` #####
-A simple class used to build the Setting object used in the v1.0 of the toolkit.
+### Replay attacks ###
-##### OneLogin_Saml_Metadata - `Metadata.php` #####
+In order to avoid replay attacks, you can store the ID of the SAML messages already processed, to avoid processing them twice. Since the Messages expires and will be invalidated due that fact, you don't need to store those IDs longer than the time frame that you currently accepting.
-* `OneLogin_Saml_Metadata` - Constructor that build the Metadata XML info based
- on the settings of the SP
-* `getXml` - An XML with the metadata info of the SP
+Get the ID of the last processed message/assertion with the `getLastMessageId`/`getLastAssertionId` methods of the Auth object.
-##### OneLogin_Saml_XmlSec - `XmlSec.php` #####
-
-Auxiliary class that contains methods to validate the SAML Response:
-`validateNumAssertions`, `validateTimestamps`, `isValid` (which
-uses the other two previous methods and also validate the signature of
-SAML Response).
+### Main classes and methods ###
+Described below are the main classes and methods that can be invoked.
#### Saml2 library ####
Lets describe now the classes and methods of the SAML2 library.
-##### OneLogin_Saml2_Auth - Auth.php #####
+##### OneLogin\Saml2\Auth - Auth.php #####
Main class of OneLogin PHP Toolkit
- * `OneLogin_Saml2_Auth` - Initializes the SP SAML instance
+ * `Auth` - Initializes the SP SAML instance
* `login` - Initiates the SSO process.
* `logout` - Initiates the SLO process.
* `processResponse` - Process the SAML Response sent by the IdP.
@@ -1158,6 +1165,9 @@ Main class of OneLogin PHP Toolkit
* `getAttributes` - Returns the set of SAML attributes.
* `getAttribute` - Returns the requested SAML attribute
* `getNameId` - Returns the nameID
+ * `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
+ * `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
+ * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
* `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
* `getErrors` - Returns if there were any error
* `getSSOurl` - Gets the SSO url.
@@ -1172,20 +1182,20 @@ Main class of OneLogin PHP Toolkit
* `getLastResponseXML` - Returns the most recently-constructed/processed XML SAML response (SAMLResponse, LogoutResponse). If the SAMLResponse had an encrypted assertion, decrypts it.
-##### OneLogin_Saml2_AuthnRequest - `AuthnRequest.php` #####
+##### OneLogin\Saml2\AuthnRequest - `AuthnRequest.php` #####
SAML 2 Authentication Request class
- * `OneLogin_Saml2_AuthnRequest` - Constructs the `AuthnRequest` object.
+ * `AuthnRequest` - Constructs the `AuthnRequest` object.
* `getRequest` - Returns deflated, base64 encoded, unsigned `AuthnRequest`.
* `getId` - Returns the `AuthNRequest` ID.
* `getXML` - Returns the XML that will be sent as part of the request.
-##### OneLogin_Saml2_Response - `Response.php` #####
+##### OneLogin\Saml2\Response - `Response.php` #####
SAML 2 Authentication Response class
- * `OneLogin_Saml2_Response` - Constructs the SAML Response object.
+ * `Response` - Constructs the SAML Response object.
* `isValid` - Determines if the SAML Response is valid using the certificate.
* `checkStatus` - Checks if the Status is success.
* `getAudiences` - Gets the audiences.
@@ -1194,6 +1204,8 @@ SAML 2 Authentication Response class
IdP.
* `getNameId` - Gets the NameID provided by the SAML response from the IdP.
* `getNameIdFormat` - Gets the NameID Format provided by the SAML response from the IdP.
+ * `getNameIdNameQualifier` - Gets the NameID NameQualifier provided from the SAML Response String.
+ * `getNameIdNameSPQualifier` - Gets the NameID SP NameQualifier provided from the SAML Response String.
* `getSessionNotOnOrAfter` - Gets the SessionNotOnOrAfter from the
AuthnStatement
* `getSessionIndex` - Gets the SessionIndex from the AuthnStatement.
@@ -1205,11 +1217,11 @@ SAML 2 Authentication Response class
* `getError` - After executing a validation process, if it fails, this method returns the cause
* `getXMLDocument` - Returns the SAML Response document (If contains an encrypted assertion, decrypts it)
-##### OneLogin_Saml2_LogoutRequest - `LogoutRequest.php` #####
+##### OneLogin\Saml2\LogoutRequest - `LogoutRequest.php` #####
SAML 2 Logout Request class
- * `OneLogin_Saml2_LogoutRequest` - Constructs the Logout Request object.
+ * `LogoutRequest` - Constructs the Logout Request object.
* `getRequest` - Returns the Logout Request defated, base64encoded, unsigned
* `getID` - Returns the ID of the Logout Request. (If you have the object you can access to the id attribute)
* `getNameIdData` - Gets the NameID Data of the the Logout Request.
@@ -1220,11 +1232,11 @@ SAML 2 Logout Request class
* `getError` - After executing a validation process, if it fails, this method returns the cause
* `getXML` - Returns the XML that will be sent as part of the request or that was received at the SP.
-##### OneLogin_Saml2_LogoutResponse - `LogoutResponse.php` #####
+##### OneLogin\Saml2\LogoutResponse - `LogoutResponse.php` #####
SAML 2 Logout Response class
- * `OneLogin_Saml2_LogoutResponse` - Constructs a Logout Response object
+ * `LogoutResponse` - Constructs a Logout Response object
(Initialize params from settings and if provided load the Logout Response)
* `getIssuer` - Gets the Issuer of the Logout Response.
* `getStatus` - Gets the Status of the Logout Response.
@@ -1234,11 +1246,11 @@ SAML 2 Logout Response class
* `getError` - After executing a validation process, if it fails, this method returns the cause.
* `getXML` - Returns the XML that will be sent as part of the response or that was received at the SP.
-##### OneLogin_Saml2_Settings - `Settings.php` #####
+##### OneLogin\Saml2\Settings - `Settings.php` #####
Configuration of the OneLogin PHP Toolkit
- * `OneLogin_Saml2_Settings` - Initializes the settings: Sets the paths of
+ * `Settings` - Initializes the settings: Sets the paths of
the different folders and Loads settings info from settings file or
array/object provided
* `checkSettings` - Checks the settings info.
@@ -1250,6 +1262,7 @@ Configuration of the OneLogin PHP Toolkit
* `checkSPCerts` - Checks if the x509 certs of the SP exists and are valid.
* `getSPkey` - Returns the x509 private key of the SP.
* `getSPcert` - Returns the x509 public cert of the SP.
+ * `getSPcertNew` - Returns the future x509 public cert of the SP.
* `getIdPData` - Gets the IdP data.
* `getSPData`Gets the SP data.
* `getSecurityData` - Gets security data.
@@ -1259,6 +1272,7 @@ Configuration of the OneLogin PHP Toolkit
* `validateMetadata` - Validates an XML SP Metadata.
* `formatIdPCert` - Formats the IdP cert.
* `formatSPCert` - Formats the SP cert.
+ * `formatSPCertNew` - Formats the SP cert new.
* `formatSPKey` - Formats the SP private key.
* `getErrors` - Returns an array with the errors, the array is empty when
the settings is ok.
@@ -1269,7 +1283,7 @@ Configuration of the OneLogin PHP Toolkit
* `isStrict` - Returns if the 'strict' mode is active.
* `isDebugActive` - Returns if the debug is active.
-##### OneLogin_Saml2_Metadata - `Metadata.php` #####
+##### OneLogin\Saml2\Metadata - `Metadata.php` #####
A class that contains functionality related to the metadata of the SP
@@ -1278,7 +1292,7 @@ A class that contains functionality related to the metadata of the SP
* `addX509KeyDescriptors` - Adds the x509 descriptors (sign/encriptation) to
the metadata
-##### OneLogin_Saml2_Utils - `Utils.php` #####
+##### OneLogin\Saml2\Utils - `Utils.php` #####
Auxiliary class that contains several methods
@@ -1317,6 +1331,16 @@ Auxiliary class that contains several methods
(Message or Assertion).
* `validateSign` - Validates a signature (Message or Assertion).
+##### OneLogin\Saml2\IdPMetadataParser - `IdPMetadataParser.php` #####
+
+Auxiliary class that contains several methods to retrieve and process IdP metadata
+
+ * `parseRemoteXML` - Get IdP Metadata Info from URL.
+ * `parseFileXML` - Get IdP Metadata Info from File.
+ * `parseXML` - Get IdP Metadata Info from XML.
+ * `injectIntoSettings` - Inject metadata info into php-saml settings array.
+
+
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
HTML documentation about the classes and methods is provided for SAML and
@@ -1436,7 +1460,7 @@ At demo1, we saw how all the SAML Request and Responses were handler at an
unique file, the `index.php` file. This demo1 uses high-level programming.
At demo2, we have several views: `index.php`, `sso.php`, `slo.php`, `consume.php`
-and `metadata.php`. As we said, we gonna use the endpoints that are defined
+and `metadata.php`. As we said, we will use the endpoints that are defined
in the toolkit (`acs.php`, `sls.php` of the endpoints folder). This demo2 uses
low-level programming.
@@ -1469,7 +1493,7 @@ demo1, only changes the targets.
valid, close the user session of the local app. Notice that the SLO
Workflow starts and ends at the SP.
- 5.2 SLO Initiated by IdP. In this case, the action takes place on the IdP
+ 4.2 SLO Initiated by IdP. In this case, the action takes place on the IdP
side, the logout process is initiated at the idP, sends a Logout
Request to the SP (SLS endpoint `sls.php` of the endpoint folder).
The SLS endpoint of the SP process the Logout Request and if is valid,
@@ -1478,43 +1502,3 @@ demo1, only changes the targets.
Response, process it and close the session at of the IdP. Notice that the
SLO Workflow starts and ends at the IdP.
-
-## Demo Old ##
-
-### SP setup ###
-
-This demo uses the old style of the version 1 of the toolkit.
-An object of the class `OneLogin_Saml_Settings` must be provided to the
-constructor of the `AuthRequest`.
-
-You will find an `example_settings.php` file at the demo-old's folder that
-could be used as a template for your `settings.php` file.
-
-In that template, SAML settings are divided into two parts, the application
-specific (`const_assertion_consumer_service_url`, `const_issuer`,
-`const_name_identifier_format`) and the user/account specific
-`idp_sso_target_url`, `x509certificate`). You'll need to add your own code here
-to identify the user or user origin (e.g. by `subdomain`, `ip_address` etc.).
-
-
-### IdP setup ###
-
-Once the SP is configured, the metadata of the SP is published at the
-`metadata.php` file. After that, configure the IdP based on that information.
-
-
-### How it works ###
-
-At the `metadata.php` view is published the metadata of the SP.
-
-The `index.php` file acts as an initiater for the SAML conversation if it should
-should be initiated by the application. This is called Service Provider
-Initiated SAML. The service provider creates a SAML Authentication Request and
-sends it to the identity provider (IdP).
-
-The `consume.php` is the ACS endpoint. Receives the SAML assertion. After Response
-validation, the userdata and the nameID will be available, using `getNameId()` or
-`getAttributes()` we obtain them.
-
-Since the version 1 of the php toolkit does not support SLO we don't show how
-handle SLO in this demo-old.
diff --git a/3rdparty/vendor/onelogin/php-saml/_toolkit_loader.php b/3rdparty/vendor/onelogin/php-saml/_toolkit_loader.php
index 1af21e9b..c4649d76 100644
--- a/3rdparty/vendor/onelogin/php-saml/_toolkit_loader.php
+++ b/3rdparty/vendor/onelogin/php-saml/_toolkit_loader.php
@@ -1,19 +1,28 @@
<?php
-// Create an __autoload function
+// Create an __autoload function
// (can conflicts other autoloaders)
// http://php.net/manual/en/language.oop5.autoload.php
-$libDir = dirname(__FILE__) . '/lib/Saml2/';
-$extlibDir = dirname(__FILE__) . '/extlib/';
-
-// Load composer
-if (file_exists('vendor/autoload.php')) {
- require 'vendor/autoload.php';
+// Load composer vendor folder if any
+if (file_exists(__DIR__ . '/vendor/autoload.php')) {
+ require __DIR__ . '/vendor/autoload.php';
}
-// Load now external libs
-require_once $extlibDir . 'xmlseclibs/xmlseclibs.php';
+/*
+// Load xmlseclibs
+
+$xmlseclibsSrcDir = '';
+
+include_once $xmlseclibsSrcDir.'/XMLSecEnc.php';
+include_once $xmlseclibsSrcDir.'/XMLSecurityDSig.php';
+include_once $xmlseclibsSrcDir.'/XMLSecurityKey.php';
+include_once $xmlseclibsSrcDir.'/Utils/XPath.php';
+*/
+
+
+// Load php-saml
+$libDir = __DIR__ . '/src/Saml2/';
$folderInfo = scandir($libDir);
@@ -22,4 +31,4 @@ foreach ($folderInfo as $element) {
include_once $libDir.$element;
}
}
-
+
diff --git a/3rdparty/vendor/onelogin/php-saml/advanced_settings_example.php b/3rdparty/vendor/onelogin/php-saml/advanced_settings_example.php
index 3ada0293..7da4bb36 100644
--- a/3rdparty/vendor/onelogin/php-saml/advanced_settings_example.php
+++ b/3rdparty/vendor/onelogin/php-saml/advanced_settings_example.php
@@ -1,18 +1,18 @@
<?php
-$advancedSettings = array (
+$advancedSettings = array(
- // Compression settings
+ // Compression settings
// Handle if the getRequest/getResponse methods will return the Request/Response deflated.
// But if we provide a $deflate boolean parameter to the getRequest or getResponse
// method it will have priority over the compression settings.
- 'compress' => array (
+ 'compress' => array(
'requests' => true,
'responses' => true
),
// Security settings
- 'security' => array (
+ 'security' => array(
/** signatures and encryptions offered */
@@ -33,7 +33,7 @@ $advancedSettings = array (
'logoutResponseSigned' => false,
/* Sign the Metadata
- False || True (use sp certs) || array (
+ False || True (use sp certs) || array(
keyFileName => 'metadata.key',
certFileName => 'metadata.crt'
)
@@ -66,7 +66,7 @@ $advancedSettings = array (
// Authentication context.
// Set to false and no AuthContext will be sent in the AuthNRequest,
// Set true or don't present this parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
- // Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'),
+ // Set an array with the possible auth context values: array('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'),
'requestedAuthnContext' => false,
// Allows the authn comparison parameter to be set, defaults to 'exact' if
@@ -87,14 +87,16 @@ $advancedSettings = array (
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
- 'signatureAlgorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
+ // Notice that rsa-sha1 is a deprecated algorithm and should not be used
+ 'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
// Algorithm that the toolkit will use on digest process. Options:
// 'http://www.w3.org/2000/09/xmldsig#sha1'
// 'http://www.w3.org/2001/04/xmlenc#sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#sha384'
// 'http://www.w3.org/2001/04/xmlenc#sha512'
- 'digestAlgorithm' => 'http://www.w3.org/2000/09/xmldsig#sha1',
+ // Notice that sha1 is a deprecated algorithm and should not be used
+ 'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
@@ -102,19 +104,19 @@ $advancedSettings = array (
),
// Contact information template, it is recommended to suply a technical and support contacts
- 'contactPerson' => array (
- 'technical' => array (
+ 'contactPerson' => array(
+ 'technical' => array(
'givenName' => '',
'emailAddress' => ''
),
- 'support' => array (
+ 'support' => array(
'givenName' => '',
'emailAddress' => ''
),
),
// Organization information template, the info in en_US lang is recomended, add more if required
- 'organization' => array (
+ 'organization' => array(
'en-US' => array(
'name' => '',
'displayname' => '',
diff --git a/3rdparty/vendor/onelogin/php-saml/compatibility.php b/3rdparty/vendor/onelogin/php-saml/compatibility.php
deleted file mode 100644
index 02a8108c..00000000
--- a/3rdparty/vendor/onelogin/php-saml/compatibility.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-/**
- * Compability with the old PHP Toolkit
- */
-
-define('ONELOGIN_SAML_DIR', 'lib/Saml/');
-require_once ONELOGIN_SAML_DIR . 'AuthRequest.php';
-require_once ONELOGIN_SAML_DIR . 'Response.php';
-require_once ONELOGIN_SAML_DIR . 'Settings.php';
-require_once ONELOGIN_SAML_DIR . 'XmlSec.php';
-require_once ONELOGIN_SAML_DIR . 'Metadata.php';
diff --git a/3rdparty/vendor/onelogin/php-saml/composer.json b/3rdparty/vendor/onelogin/php-saml/composer.json
index 7c07916d..bab318e9 100644
--- a/3rdparty/vendor/onelogin/php-saml/composer.json
+++ b/3rdparty/vendor/onelogin/php-saml/composer.json
@@ -2,15 +2,12 @@
"name": "onelogin/php-saml",
"description": "OneLogin PHP SAML Toolkit",
"license": "MIT",
- "version": "2.10.5",
- "homepage": "https://onelogin.zendesk.com/hc/en-us/sections/200245634-SAML-Toolkits",
+ "homepage": "https://developers.onelogin.com/saml/php",
"keywords": ["saml", "saml2", "onelogin"],
"autoload": {
- "classmap": [
- "extlib/xmlseclibs",
- "lib/Saml",
- "lib/Saml2"
- ]
+ "psr-4": {
+ "OneLogin\\": "src/"
+ }
},
"support": {
"email": "sixto.garcia@onelogin.com",
@@ -18,22 +15,20 @@
"source": "https://github.com/onelogin/php-saml/"
},
"require": {
- "php": ">=5.3.2",
- "ext-openssl": "*",
- "ext-dom": "*",
- "ext-mcrypt": "*"
+ "php": ">=5.4",
+ "robrichards/xmlseclibs": "^3.0"
},
"require-dev": {
- "phpunit/phpunit": "4.8",
- "satooshi/php-coveralls": "1.0.1",
- "sebastian/phpcpd": "*",
- "phploc/phploc": "*",
- "pdepend/pdepend" : "1.1.0",
- "squizlabs/php_codesniffer": "*"
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1",
+ "php-coveralls/php-coveralls": "^1.0.2 || ^2.0",
+ "sebastian/phpcpd": "^2.0 || ^3.0 || ^4.0",
+ "phploc/phploc": "^2.1 || ^3.0 || ^4.0",
+ "pdepend/pdepend": "^2.5.0",
+ "squizlabs/php_codesniffer": "^3.1.1"
},
"suggest": {
- "lib-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)",
- "ext-mcrypt": "Install mcrypt and php5-mcrypt libs in order to support encryption",
+ "ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)",
+ "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs",
"ext-gettext": "Install gettext and php5-gettext libs to handle translations"
}
}
diff --git a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php b/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php
deleted file mode 100644
index 05be8643..00000000
--- a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/xmlseclibs.php
+++ /dev/null
@@ -1,1721 +0,0 @@
-<?php
-/**
- * xmlseclibs.php
- *
- * Copyright (c) 2007-2015, Robert Richards <rrichards@cdatazone.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * * Neither the name of Robert Richards nor the names of his
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @author Robert Richards <rrichards@cdatazone.org>
- * @copyright 2007-2015 Robert Richards <rrichards@cdatazone.org>
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version 2.0.0 modified
- */
-
-class XMLSecurityKey {
- const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
- const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
- const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
- const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
- const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
- const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
- const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
- const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
- const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
- const RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
- const RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
- const HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
-
- private $cryptParams = array();
- public $type = 0;
- public $key = null;
- public $passphrase = "";
- public $iv = null;
- public $name = null;
- public $keyChain = null;
- public $isEncrypted = false;
- public $encryptedCtx = null;
- public $guid = null;
-
- /**
- * This variable contains the certificate as a string if this key represents an X509-certificate.
- * If this key doesn't represent a certificate, this will be null.
- */
- private $x509Certificate = null;
-
- /* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
- private $X509Thumbprint = null;
-
- public function __construct($type, $params=null) {
- switch ($type) {
- case (XMLSecurityKey::TRIPLEDES_CBC):
- $this->cryptParams['library'] = 'mcrypt';
- $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
- $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
- $this->cryptParams['keysize'] = 24;
- break;
- case (XMLSecurityKey::AES128_CBC):
- $this->cryptParams['library'] = 'mcrypt';
- $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
- $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
- $this->cryptParams['keysize'] = 16;
- break;
- case (XMLSecurityKey::AES192_CBC):
- $this->cryptParams['library'] = 'mcrypt';
- $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
- $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
- $this->cryptParams['keysize'] = 24;
- break;
- case (XMLSecurityKey::AES256_CBC):
- $this->cryptParams['library'] = 'mcrypt';
- $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
- $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
- $this->cryptParams['keysize'] = 32;
- break;
- case (XMLSecurityKey::RSA_1_5):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::RSA_OAEP_MGF1P):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
- $this->cryptParams['hash'] = null;
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::RSA_SHA1):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::RSA_SHA256):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
- $this->cryptParams['digest'] = 'SHA256';
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::RSA_SHA384):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
- $this->cryptParams['digest'] = 'SHA384';
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::RSA_SHA512):
- $this->cryptParams['library'] = 'openssl';
- $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
- $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
- $this->cryptParams['digest'] = 'SHA512';
- if (is_array($params) && ! empty($params['type'])) {
- if ($params['type'] == 'public' || $params['type'] == 'private') {
- $this->cryptParams['type'] = $params['type'];
- break;
- }
- }
- throw new Exception('Certificate "type" (private/public) must be passed via parameters');
- case (XMLSecurityKey::HMAC_SHA1):
- $this->cryptParams['library'] = $type;
- $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
- break;
- default:
- throw new Exception('Invalid Key Type');
- }
- $this->type = $type;
- }
-
- /**
- * Retrieve the key size for the symmetric encryption algorithm..
- *
- * If the key size is unknown, or this isn't a symmetric encryption algorithm,
- * null is returned.
- *
- * @return int|null The number of bytes in the key.
- */
- public function getSymmetricKeySize() {
- if (! isset($this->cryptParams['keysize'])) {
- return null;
- }
- return $this->cryptParams['keysize'];
- }
-
- public function generateSessionKey() {
- if (!isset($this->cryptParams['keysize'])) {
- throw new Exception('Unknown key size for type "' . $this->type . '".');
- }
- $keysize = $this->cryptParams['keysize'];
-
- if (function_exists('openssl_random_pseudo_bytes')) {
- /* We have PHP >= 5.3 - use openssl to generate session key. */
- $key = openssl_random_pseudo_bytes($keysize);
- } else {
- /* Generating random key using iv generation routines */
- $key = mcrypt_create_iv($keysize, MCRYPT_RAND);
- }
-
- if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
- /* Make sure that the generated key has the proper parity bits set.
- * Mcrypt doesn't care about the parity bits, but others may care.
- */
- for ($i = 0; $i < strlen($key); $i++) {
- $byte = ord($key[$i]) & 0xfe;
- $parity = 1;
- for ($j = 1; $j < 8; $j++) {
- $parity ^= ($byte >> $j) & 1;
- }
- $byte |= $parity;
- $key[$i] = chr($byte);
- }
- }
-
- $this->key = $key;
- return $key;
- }
-
- public static function getRawThumbprint($cert) {
-
- $arCert = explode("\n", $cert);
- $data = '';
- $inData = false;
-
- foreach ($arCert AS $curData) {
- if (! $inData) {
- if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
- $inData = true;
- }
- } else {
- if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
- break;
- }
- $data .= trim($curData);
- }
- }
-
- if (! empty($data)) {
- return strtolower(sha1(base64_decode($data)));
- }
-
- return null;
- }
-
- public function loadKey($key, $isFile=false, $isCert = false) {
- if ($isFile) {
- $this->key = file_get_contents($key);
- } else {
- $this->key = $key;
- }
- if ($isCert) {
- $this->key = openssl_x509_read($this->key);
- openssl_x509_export($this->key, $str_cert);
- $this->x509Certificate = $str_cert;
- $this->key = $str_cert;
- } else {
- $this->x509Certificate = null;
- }
- if ($this->cryptParams['library'] == 'openssl') {
- if ($this->cryptParams['type'] == 'public') {
- if ($isCert) {
- /* Load the thumbprint if this is an X509 certificate. */
- $this->X509Thumbprint = self::getRawThumbprint($this->key);
- }
- $this->key = openssl_get_publickey($this->key);
- } else {
- $this->key = openssl_get_privatekey($this->key, $this->passphrase);
- }
- } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
- /* Check key length */
- switch ($this->type) {
- case (XMLSecurityKey::AES256_CBC):
- if (strlen($this->key) < 25) {
- throw new Exception('Key must contain at least 25 characters for this cipher');
- }
- break;
- case (XMLSecurityKey::AES192_CBC):
- if (strlen($this->key) < 17) {
- throw new Exception('Key must contain at least 17 characters for this cipher');
- }
- break;
- }
- }
- }
-
- private function encryptMcrypt($data) {
- $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
- $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
- mcrypt_generic_init($td, $this->key, $this->iv);
- if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
- $bs = mcrypt_enc_get_block_size($td);
- for ($datalen0=$datalen=strlen($data); (($datalen%$bs)!=($bs-1)); $datalen++)
- $data.=chr(mt_rand(1, 127));
- $data.=chr($datalen-$datalen0+1);
- }
- $encrypted_data = $this->iv.mcrypt_generic($td, $data);
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
- return $encrypted_data;
- }
-
- private function decryptMcrypt($data) {
- $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
- $iv_length = mcrypt_enc_get_iv_size($td);
-
- $this->iv = substr($data, 0, $iv_length);
- $data = substr($data, $iv_length);
-
- mcrypt_generic_init($td, $this->key, $this->iv);
- $decrypted_data = mdecrypt_generic($td, $data);
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
- if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
- $dataLen = strlen($decrypted_data);
- $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
- $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
- }
- return $decrypted_data;
- }
-
- private function encryptOpenSSL($data) {
- if ($this->cryptParams['type'] == 'public') {
- if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
- throw new Exception('Failure encrypting Data');
- }
- } else {
- if (! openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
- throw new Exception('Failure encrypting Data');
- }
- }
- return $encrypted_data;
- }
-
- private function decryptOpenSSL($data) {
- if ($this->cryptParams['type'] == 'public') {
- if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
- throw new Exception('Failure decrypting Data');
- }
- } else {
- if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
- throw new Exception('Failure decrypting Data');
- }
- }
- return $decrypted;
- }
-
- private function signOpenSSL($data) {
- $algo = OPENSSL_ALGO_SHA1;
- if (! empty($this->cryptParams['digest'])) {
- $algo = $this->cryptParams['digest'];
- }
- if (! openssl_sign ($data, $signature, $this->key, $algo)) {
- throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
- }
- return $signature;
- }
-
- private function verifyOpenSSL($data, $signature) {
- $algo = OPENSSL_ALGO_SHA1;
- if (! empty($this->cryptParams['digest'])) {
- $algo = $this->cryptParams['digest'];
- }
- return openssl_verify ($data, $signature, $this->key, $algo);
- }
-
- public function encryptData($data) {
- switch ($this->cryptParams['library']) {
- case 'mcrypt':
- return $this->encryptMcrypt($data);
- case 'openssl':
- return $this->encryptOpenSSL($data);
- }
- }
-
- public function decryptData($data) {
- switch ($this->cryptParams['library']) {
- case 'mcrypt':
- return $this->decryptMcrypt($data);
- case 'openssl':
- return $this->decryptOpenSSL($data);
- }
- }
-
- public function signData($data) {
- switch ($this->cryptParams['library']) {
- case 'openssl':
- return $this->signOpenSSL($data);
- case (XMLSecurityKey::HMAC_SHA1):
- return hash_hmac("sha1", $data, $this->key, true);
- }
- }
-
- public function verifySignature($data, $signature) {
- switch ($this->cryptParams['library']) {
- case 'openssl':
- return $this->verifyOpenSSL($data, $signature);
- case (XMLSecurityKey::HMAC_SHA1):
- $expectedSignature = hash_hmac("sha1", $data, $this->key, true);
- return strcmp($signature, $expectedSignature) == 0;
- }
- }
-
- public function getAlgorithm() {
- return $this->cryptParams['method'];
- }
-
- static function makeAsnSegment($type, $string) {
- switch ($type){
- case 0x02:
- if (ord($string) > 0x7f)
- $string = chr(0).$string;
- break;
- case 0x03:
- $string = chr(0).$string;
- break;
- }
-
- $length = strlen($string);
-
- if ($length < 128){
- $output = sprintf("%c%c%s", $type, $length, $string);
- } else if ($length < 0x0100){
- $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
- } else if ($length < 0x010000) {
- $output = sprintf("%c%c%c%c%s", $type, 0x82, $length/0x0100, $length%0x0100, $string);
- } else {
- $output = null;
- }
- return($output);
- }
-
- /* Modulus and Exponent must already be base64 decoded */
- static function convertRSA($modulus, $exponent) {
- /* make an ASN publicKeyInfo */
- $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
- $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
- $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
- $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
- $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
- $publicKeyInfo = XMLSecurityKey::makeAsnSegment (0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
-
- /* encode the publicKeyInfo in base64 and add PEM brackets */
- $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
- $encoding = "-----BEGIN PUBLIC KEY-----\n";
- $offset = 0;
- while ($segment=substr($publicKeyInfoBase64, $offset, 64)){
- $encoding = $encoding.$segment."\n";
- $offset += 64;
- }
- return $encoding."-----END PUBLIC KEY-----\n";
- }
-
- public function serializeKey($parent) {
-
- }
-
-
-
- /**
- * Retrieve the X509 certificate this key represents.
- *
- * Will return the X509 certificate in PEM-format if this key represents
- * an X509 certificate.
- *
- * @return The X509 certificate or null if this key doesn't represent an X509-certificate.
- */
- public function getX509Certificate() {
- return $this->x509Certificate;
- }
-
- /* Get the thumbprint of this X509 certificate.
- *
- * Returns:
- * The thumbprint as a lowercase 40-character hexadecimal number, or null
- * if this isn't a X509 certificate.
- */
- public function getX509Thumbprint() {
- return $this->X509Thumbprint;
- }
-
-
- /**
- * Create key from an EncryptedKey-element.
- *
- * @param DOMElement $element The EncryptedKey-element.
- * @return XMLSecurityKey The new key.
- */
- public static function fromEncryptedKeyElement(DOMElement $element) {
-
- $objenc = new XMLSecEnc();
- $objenc->setNode($element);
- if (! $objKey = $objenc->locateKey()) {
- throw new Exception("Unable to locate algorithm for this Encrypted Key");
- }
- $objKey->isEncrypted = true;
- $objKey->encryptedCtx = $objenc;
- XMLSecEnc::staticLocateKeyInfo($objKey, $element);
- return $objKey;
- }
-
-}
-
-
-class XMLSecurityDSig {
- const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
- const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
- const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
- const SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384';
- const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
- const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
-
- const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
- const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
- const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
- const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
-
- const template = '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
- <ds:SignedInfo>
- <ds:SignatureMethod />
- </ds:SignedInfo>
-</ds:Signature>';
-
- public $sigNode = null;
- public $idKeys = array();
- public $idNS = array();
- private $signedInfo = null;
- private $xPathCtx = null;
- private $canonicalMethod = null;
- private $prefix = 'ds';
- private $searchpfx = 'secdsig';
-
- /* This variable contains an associative array of validated nodes. */
- private $validatedNodes = null;
-
- public function __construct() {
- $sigdoc = new DOMDocument();
- $sigdoc->loadXML(XMLSecurityDSig::template);
- $this->sigNode = $sigdoc->documentElement;
- }
-
- private function resetXPathObj() {
- $this->xPathCtx = null;
- }
-
- private function getXPathObj() {
- if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
- $xpath = new DOMXPath($this->sigNode->ownerDocument);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $this->xPathCtx = $xpath;
- }
- return $this->xPathCtx;
- }
-
- static function generateGUID($prefix='pfx') {
- $uuid = md5(uniqid(mt_rand(), true));
- $guid = $prefix.substr($uuid,0,8)."-".
- substr($uuid,8,4)."-".
- substr($uuid,12,4)."-".
- substr($uuid,16,4)."-".
- substr($uuid,20,12);
- return $guid;
- }
-
- public function locateSignature($objDoc, $pos=0) {
- if ($objDoc instanceof DOMDocument) {
- $doc = $objDoc;
- } else {
- $doc = $objDoc->ownerDocument;
- }
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = ".//secdsig:Signature";
- $nodeset = $xpath->query($query, $objDoc);
- $this->sigNode = $nodeset->item($pos);
- return $this->sigNode;
- }
- return null;
- }
-
- public function createNewSignNode($name, $value=null) {
- $doc = $this->sigNode->ownerDocument;
- if (! is_null($value)) {
- $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name, $value);
- } else {
- $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $this->prefix.':'.$name);
- }
- return $node;
- }
-
- public function setCanonicalMethod($method) {
- switch ($method) {
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
- case 'http://www.w3.org/2001/10/xml-exc-c14n#':
- case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
- $this->canonicalMethod = $method;
- break;
- default:
- throw new Exception('Invalid Canonical Method');
- }
- if ($xpath = $this->getXPathObj()) {
- $query = './'.$this->searchpfx.':SignedInfo';
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($sinfo = $nodeset->item(0)) {
- $query = './'.$this->searchpfx.'CanonicalizationMethod';
- $nodeset = $xpath->query($query, $sinfo);
- if (! ($canonNode = $nodeset->item(0))) {
- $canonNode = $this->createNewSignNode('CanonicalizationMethod');
- $sinfo->insertBefore($canonNode, $sinfo->firstChild);
- }
- $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
- }
- }
- }
-
- private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefixList=null) {
- $exclusive = false;
- $withComments = false;
- switch ($canonicalmethod) {
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
- $exclusive = false;
- $withComments = false;
- break;
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
- $withComments = true;
- break;
- case 'http://www.w3.org/2001/10/xml-exc-c14n#':
- $exclusive = true;
- break;
- case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
- $exclusive = true;
- $withComments = true;
- break;
- }
-
- if (is_null($arXPath) && ($node instanceof DOMNode) && ($node->ownerDocument !== null) && $node->isSameNode($node->ownerDocument->documentElement)) {
- /* Check for any PI or comments as they would have been excluded */
- $element = $node;
- while ($refnode = $element->previousSibling) {
- if ($refnode->nodeType == XML_PI_NODE || (($refnode->nodeType == XML_COMMENT_NODE) && $withComments)) {
- break;
- }
- $element = $refnode;
- }
- if ($refnode == null) {
- $node = $node->ownerDocument;
- }
- }
-
- return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
- }
-
- public function canonicalizeSignedInfo() {
-
- $doc = $this->sigNode->ownerDocument;
- $canonicalmethod = null;
- if ($doc) {
- $xpath = $this->getXPathObj();
- $query = "./secdsig:SignedInfo";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($signInfoNode = $nodeset->item(0)) {
- $query = "./secdsig:CanonicalizationMethod";
- $nodeset = $xpath->query($query, $signInfoNode);
- if ($canonNode = $nodeset->item(0)) {
- $canonicalmethod = $canonNode->getAttribute('Algorithm');
- }
- $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
- return $this->signedInfo;
- }
- }
- return null;
- }
-
- public function calculateDigest ($digestAlgorithm, $data, $encode = true) {
- switch ($digestAlgorithm) {
- case XMLSecurityDSig::SHA1:
- $alg = 'sha1';
- break;
- case XMLSecurityDSig::SHA256:
- $alg = 'sha256';
- break;
- case XMLSecurityDSig::SHA384:
- $alg = 'sha384';
- break;
- case XMLSecurityDSig::SHA512:
- $alg = 'sha512';
- break;
- case XMLSecurityDSig::RIPEMD160:
- $alg = 'ripemd160';
- break;
- default:
- throw new Exception("Cannot validate digest: Unsupported Algorithm <$digestAlgorithm>");
- }
-
- $digest = hash($alg, $data, true);
- if ($encode) {
- $digest = base64_encode($digest);
- }
- return $digest;
- }
-
- public function validateDigest($refNode, $data) {
- $xpath = new DOMXPath($refNode->ownerDocument);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = 'string(./secdsig:DigestMethod/@Algorithm)';
- $digestAlgorithm = $xpath->evaluate($query, $refNode);
- $digValue = $this->calculateDigest($digestAlgorithm, $data, false);
- $query = 'string(./secdsig:DigestValue)';
- $digestValue = $xpath->evaluate($query, $refNode);
- return ($digValue == base64_decode($digestValue));
- }
-
- public function processTransforms($refNode, $objData, $includeCommentNodes = true) {
- $data = $objData;
- $xpath = new DOMXPath($refNode->ownerDocument);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = './secdsig:Transforms/secdsig:Transform';
- $nodelist = $xpath->query($query, $refNode);
- $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
- $arXPath = null;
- $prefixList = null;
- foreach ($nodelist AS $transform) {
- $algorithm = $transform->getAttribute("Algorithm");
- switch ($algorithm) {
- case 'http://www.w3.org/2001/10/xml-exc-c14n#':
- case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
-
- if(!$includeCommentNodes) {
- /* We remove comment nodes by forcing it to use a canonicalization
- * without comments.
- */
- $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
- } else {
- $canonicalMethod = $algorithm;
- }
-
- $node = $transform->firstChild;
- while ($node) {
- if ($node->localName == 'InclusiveNamespaces') {
- if ($pfx = $node->getAttribute('PrefixList')) {
- $arpfx = array();
- $pfxlist = explode(" ", $pfx);
- foreach ($pfxlist AS $pfx) {
- $val = trim($pfx);
- if (! empty($val)) {
- $arpfx[] = $val;
- }
- }
- if (count($arpfx) > 0) {
- $prefixList = $arpfx;
- }
- }
- break;
- }
- $node = $node->nextSibling;
- }
- break;
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
- case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
- if(!$includeCommentNodes) {
- /* We remove comment nodes by forcing it to use a canonicalization
- * without comments.
- */
- $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
- } else {
- $canonicalMethod = $algorithm;
- }
-
- break;
- case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
- $node = $transform->firstChild;
- while ($node) {
- if ($node->localName == 'XPath') {
- $arXPath = array();
- $arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
- $arXpath['namespaces'] = array();
- $nslist = $xpath->query('./namespace::*', $node);
- foreach ($nslist AS $nsnode) {
- if ($nsnode->localName != "xml") {
- $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
- }
- }
- break;
- }
- $node = $node->nextSibling;
- }
- break;
- }
- }
- if ($data instanceof DOMNode) {
- $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
- }
- return $data;
- }
-
- public function processRefNode($refNode) {
- $dataObject = null;
-
- /*
- * Depending on the URI, we may not want to include comments in the result
- * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
- */
- $includeCommentNodes = true;
-
- if ($uri = $refNode->getAttribute("URI")) {
- $arUrl = parse_url($uri);
- if (empty($arUrl['path'])) {
- if ($identifier = $arUrl['fragment']) {
-
- /* This reference identifies a node with the given id by using
- * a URI on the form "#identifier". This should not include comments.
- */
- $includeCommentNodes = false;
-
- $xPath = new DOMXPath($refNode->ownerDocument);
- if ($this->idNS && is_array($this->idNS)) {
- foreach ($this->idNS AS $nspf=>$ns) {
- $xPath->registerNamespace($nspf, $ns);
- }
- }
- $iDlist = '@Id="'.$identifier.'"';
- if (is_array($this->idKeys)) {
- foreach ($this->idKeys AS $idKey) {
- $iDlist .= " or @$idKey='$identifier'";
- }
- }
- $query = '//*['.$iDlist.']';
- $dataObject = $xPath->query($query)->item(0);
- } else {
- $dataObject = $refNode->ownerDocument;
- }
- } else {
- $dataObject = file_get_contents($arUrl);
- }
- } else {
- /* This reference identifies the root node with an empty URI. This should
- * not include comments.
- */
- $includeCommentNodes = false;
-
- $dataObject = $refNode->ownerDocument;
- }
- $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
- if (!$this->validateDigest($refNode, $data)) {
- return false;
- }
-
- if ($dataObject instanceof DOMNode) {
- /* Add this node to the list of validated nodes. */
- if(! empty($identifier)) {
- $this->validatedNodes[$identifier] = $dataObject;
- } else {
- $this->validatedNodes[] = $dataObject;
- }
- }
-
- return true;
- }
-
- public function getRefNodeID($refNode) {
- if ($uri = $refNode->getAttribute("URI")) {
- $arUrl = parse_url($uri);
- if (empty($arUrl['path'])) {
- if ($identifier = $arUrl['fragment']) {
- return $identifier;
- }
- }
- }
- return null;
- }
-
- public function getRefIDs() {
- $refids = array();
-
- $xpath = $this->getXPathObj();
- $query = "./secdsig:SignedInfo/secdsig:Reference";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($nodeset->length == 0) {
- throw new Exception("Reference nodes not found");
- }
- foreach ($nodeset AS $refNode) {
- $refids[] = $this->getRefNodeID($refNode);
- }
- return $refids;
- }
-
- public function validateReference() {
- $docElem = $this->sigNode->ownerDocument->documentElement;
- if (! $docElem->isSameNode($this->sigNode)) {
- $this->sigNode->parentNode->removeChild($this->sigNode);
- }
- $xpath = $this->getXPathObj();
- $query = "./secdsig:SignedInfo/secdsig:Reference";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($nodeset->length == 0) {
- throw new Exception("Reference nodes not found");
- }
-
- /* Initialize/reset the list of validated nodes. */
- $this->validatedNodes = array();
-
- foreach ($nodeset AS $refNode) {
- if (! $this->processRefNode($refNode)) {
- /* Clear the list of validated nodes. */
- $this->validatedNodes = null;
- throw new Exception("Reference validation failed");
- }
- }
- return true;
- }
-
- private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=null, $options=null) {
- $prefix = null;
- $prefix_ns = null;
- $id_name = 'Id';
- $overwrite_id = true;
- $force_uri = false;
-
- if (is_array($options)) {
- $prefix = empty($options['prefix'])?null:$options['prefix'];
- $prefix_ns = empty($options['prefix_ns'])?null:$options['prefix_ns'];
- $id_name = empty($options['id_name'])?'Id':$options['id_name'];
- $overwrite_id = !isset($options['overwrite'])?true:(bool)$options['overwrite'];
- $force_uri = !isset($options['force_uri'])?false:(bool)$options['force_uri'];
- }
-
- $attname = $id_name;
- if (! empty($prefix)) {
- $attname = $prefix.':'.$attname;
- }
-
- $refNode = $this->createNewSignNode('Reference');
- $sinfoNode->appendChild($refNode);
-
- if (! $node instanceof DOMDocument) {
- $uri = null;
- if (! $overwrite_id) {
- $uri = $prefix_ns ? $node->getAttributeNS($prefix_ns, $id_name) : $node->getAttribute($id_name);
- }
- if (empty($uri)) {
- $uri = XMLSecurityDSig::generateGUID();
- $node->setAttributeNS($prefix_ns, $attname, $uri);
- }
- $refNode->setAttribute("URI", '#'.$uri);
- } elseif ($force_uri) {
- $refNode->setAttribute("URI", '');
- }
-
- $transNodes = $this->createNewSignNode('Transforms');
- $refNode->appendChild($transNodes);
-
- if (is_array($arTransforms)) {
- foreach ($arTransforms AS $transform) {
- $transNode = $this->createNewSignNode('Transform');
- $transNodes->appendChild($transNode);
- if (is_array($transform) &&
- (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
- (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
- $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
- $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
- $transNode->appendChild($XPathNode);
- if (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
- foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
- $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
- }
- }
- } else {
- $transNode->setAttribute('Algorithm', $transform);
- }
- }
- } elseif (! empty($this->canonicalMethod)) {
- $transNode = $this->createNewSignNode('Transform');
- $transNodes->appendChild($transNode);
- $transNode->setAttribute('Algorithm', $this->canonicalMethod);
- }
-
- $canonicalData = $this->processTransforms($refNode, $node);
- $digValue = $this->calculateDigest($algorithm, $canonicalData);
-
- $digestMethod = $this->createNewSignNode('DigestMethod');
- $refNode->appendChild($digestMethod);
- $digestMethod->setAttribute('Algorithm', $algorithm);
-
- $digestValue = $this->createNewSignNode('DigestValue', $digValue);
- $refNode->appendChild($digestValue);
- }
-
- public function addReference($node, $algorithm, $arTransforms=null, $options=null) {
- if ($xpath = $this->getXPathObj()) {
- $query = "./secdsig:SignedInfo";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($sInfo = $nodeset->item(0)) {
- $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
- }
- }
- }
-
- public function addReferenceList($arNodes, $algorithm, $arTransforms=null, $options=null) {
- if ($xpath = $this->getXPathObj()) {
- $query = "./secdsig:SignedInfo";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($sInfo = $nodeset->item(0)) {
- foreach ($arNodes AS $node) {
- $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
- }
- }
- }
- }
-
- public function addObject($data, $mimetype=null, $encoding=null) {
- $objNode = $this->createNewSignNode('Object');
- $this->sigNode->appendChild($objNode);
- if (! empty($mimetype)) {
- $objNode->setAttribute('MimeType', $mimetype);
- }
- if (! empty($encoding)) {
- $objNode->setAttribute('Encoding', $encoding);
- }
-
- if ($data instanceof DOMElement) {
- $newData = $this->sigNode->ownerDocument->importNode($data, true);
- } else {
- $newData = $this->sigNode->ownerDocument->createTextNode($data);
- }
- $objNode->appendChild($newData);
-
- return $objNode;
- }
-
- public function locateKey($node=null) {
- if (empty($node)) {
- $node = $this->sigNode;
- }
- if (! $node instanceof DOMNode) {
- return null;
- }
- if ($doc = $node->ownerDocument) {
- $xpath = new DOMXPath($doc);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
- $algorithm = $xpath->evaluate($query, $node);
- if ($algorithm) {
- try {
- $objKey = new XMLSecurityKey($algorithm, array('type'=>'public'));
- } catch (Exception $e) {
- return null;
- }
- return $objKey;
- }
- }
- return null;
- }
-
- public function verify($objKey) {
- $doc = $this->sigNode->ownerDocument;
- $xpath = new DOMXPath($doc);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = "string(./secdsig:SignatureValue)";
- $sigValue = $xpath->evaluate($query, $this->sigNode);
- if (empty($sigValue)) {
- throw new Exception("Unable to locate SignatureValue");
- }
- return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
- }
-
- public function signData($objKey, $data) {
- return $objKey->signData($data);
- }
-
- public function sign($objKey, $appendToNode = null) {
- // If we have a parent node append it now so C14N properly works
- if ($appendToNode != null) {
- $this->resetXPathObj();
- $this->appendSignature($appendToNode);
- $this->sigNode = $appendToNode->lastChild;
- }
- if ($xpath = $this->getXPathObj()) {
- $query = "./secdsig:SignedInfo";
- $nodeset = $xpath->query($query, $this->sigNode);
- if ($sInfo = $nodeset->item(0)) {
- $query = "./secdsig:SignatureMethod";
- $nodeset = $xpath->query($query, $sInfo);
- $sMethod = $nodeset->item(0);
- $sMethod->setAttribute('Algorithm', $objKey->type);
- $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
- $sigValue = base64_encode($this->signData($objKey, $data));
- $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
- if ($infoSibling = $sInfo->nextSibling) {
- $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
- } else {
- $this->sigNode->appendChild($sigValueNode);
- }
- }
- }
- }
-
- public function appendCert() {
-
- }
-
- public function appendKey($objKey, $parent=null) {
- $objKey->serializeKey($parent);
- }
-
-
- /**
- * This function inserts the signature element.
- *
- * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
- * is specified, the signature element will be inserted as the last element before $beforeNode.
- *
- * @param $node The node the signature element should be inserted into.
- * @param $beforeNode The node the signature element should be located before.
- *
- * @return DOMNode The signature element node
- */
- public function insertSignature($node, $beforeNode = null) {
-
- $document = $node->ownerDocument;
- $signatureElement = $document->importNode($this->sigNode, true);
-
- if($beforeNode == null) {
- return $node->insertBefore($signatureElement);
- } else {
- return $node->insertBefore($signatureElement, $beforeNode);
- }
- }
-
- public function appendSignature($parentNode, $insertBefore = false) {
- $beforeNode = $insertBefore ? $parentNode->firstChild : null;
- return $this->insertSignature($parentNode, $beforeNode);
- }
-
- static function get509XCert($cert, $isPEMFormat=true) {
- $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
- if (! empty($certs)) {
- return $certs[0];
- }
- return '';
- }
-
- static function staticGet509XCerts($certs, $isPEMFormat=true) {
- if ($isPEMFormat) {
- $data = '';
- $certlist = array();
- $arCert = explode("\n", $certs);
- $inData = false;
- foreach ($arCert AS $curData) {
- if (! $inData) {
- if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
- $inData = true;
- }
- } else {
- if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
- $inData = false;
- $certlist[] = $data;
- $data = '';
- continue;
- }
- $data .= trim($curData);
- }
- }
- return $certlist;
- } else {
- return array($certs);
- }
- }
-
- static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=false, $xpath=null, $options=null) {
- if ($isURL) {
- $cert = file_get_contents($cert);
- }
- if (! $parentRef instanceof DOMElement) {
- throw new Exception('Invalid parent Node parameter');
- }
-
- list($parentRef, $keyInfo) = self::auxKeyInfo($parentRef, $xpath);
-
- // Add all certs if there are more than one
- $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
-
- $baseDoc = $parentRef->ownerDocument;
- // Attach X509 data node
- $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
- $keyInfo->appendChild($x509DataNode);
-
- $issuerSerial = false;
- $subjectName = false;
- if (is_array($options)) {
- if (! empty($options['issuerSerial'])) {
- $issuerSerial = true;
- }
- if (! empty($options['subjectName'])) {
- $subjectName = true;
- }
- }
-
- // Attach all certificate nodes and any additional data
- foreach ($certs as $X509Cert){
- if ($issuerSerial || $subjectName) {
- if ($certData = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n".chunk_split($X509Cert, 64, "\n")."-----END CERTIFICATE-----\n")) {
- if ($subjectName && ! empty($certData['subject'])) {
- if (is_array($certData['subject'])) {
- $parts = array();
- foreach ($certData['subject'] AS $key => $value) {
- if (is_array($value)) {
- foreach ($value as $valueElement) {
- array_unshift($parts, "$key=$valueElement");
- }
- } else {
- array_unshift($parts, "$key=$value");
- }
- }
- $subjectNameValue = implode(',', $parts);
- } else {
- $subjectNameValue = $certData['issuer'];
- }
- $x509SubjectNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509SubjectName', $subjectNameValue);
- $x509DataNode->appendChild($x509SubjectNode);
- }
- if ($issuerSerial && ! empty($certData['issuer']) && ! empty($certData['serialNumber'])) {
- if (is_array($certData['issuer'])) {
- $parts = array();
- foreach ($certData['issuer'] AS $key => $value) {
- array_unshift($parts, "$key=$value");
- }
- $issuerName = implode(',', $parts);
- } else {
- $issuerName = $certData['issuer'];
- }
-
- $x509IssuerNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509IssuerSerial');
- $x509DataNode->appendChild($x509IssuerNode);
-
- $x509Node = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509IssuerName', $issuerName);
- $x509IssuerNode->appendChild($x509Node);
- $x509Node = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509SerialNumber', $certData['serialNumber']);
- $x509IssuerNode->appendChild($x509Node);
- }
- }
-
- }
- $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
- $x509DataNode->appendChild($x509CertNode);
- }
- }
-
- public function add509Cert($cert, $isPEMFormat=true, $isURL=false, $options=null) {
- if ($xpath = $this->getXPathObj()) {
- self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath, $options);
- }
- }
-
- /**
- * This function appends a node to the KeyInfo.
- *
- * The KeyInfo element will be created if one does not exist in the document.
- *
- * @param DOMNode $node The node to append to the KeyInfo.
- *
- * @return DOMNode The KeyInfo element node
- */
- public function appendToKeyInfo($node) {
- $parentRef = $this->sigNode;
-
- $xpath = $this->getXPathObj();
-
- list($parentRef, $keyInfo) = self::auxKeyInfo($parentRef, $xpath);
-
- $keyInfo->appendChild($node);
-
- return $keyInfo;
- }
-
- static function auxKeyInfo($parentRef, $xpath=null)
- {
- $baseDoc = $parentRef->ownerDocument;
- if (empty($xpath)) {
- $xpath = new DOMXPath($parentRef->ownerDocument);
- $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
- }
-
- $query = "./secdsig:KeyInfo";
- $nodeset = $xpath->query($query, $parentRef);
- $keyInfo = $nodeset->item(0);
- if (! $keyInfo) {
- $inserted = false;
- $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
-
- $query = "./secdsig:Object";
- $nodeset = $xpath->query($query, $parentRef);
- if ($sObject = $nodeset->item(0)) {
- $sObject->parentNode->insertBefore($keyInfo, $sObject);
- $inserted = true;
- }
-
- if (! $inserted) {
- $parentRef->appendChild($keyInfo);
- }
- }
- return array($parentRef, $keyInfo);
- }
-
- /* This function retrieves an associative array of the validated nodes.
- *
- * The array will contain the id of the referenced node as the key and the node itself
- * as the value.
- *
- * Returns:
- * An associative array of validated nodes or null if no nodes have been validated.
- */
- public function getValidatedNodes() {
- return $this->validatedNodes;
- }
-}
-
-
-class XMLSecEnc {
- const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
- <xenc:CipherData>
- <xenc:CipherValue></xenc:CipherValue>
- </xenc:CipherData>
-</xenc:EncryptedData>";
-
- const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
- const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
- const URI = 3;
- const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
-
- private $encdoc = null;
- private $rawNode = null;
- public $type = null;
- public $encKey = null;
- private $references = array();
-
- public function __construct() {
- $this->_resetTemplate();
- }
-
- private function _resetTemplate(){
- $this->encdoc = new DOMDocument();
- $this->encdoc->loadXML(XMLSecEnc::template);
- }
-
- public function addReference($name, $node, $type) {
- if (! $node instanceOf DOMNode) {
- throw new Exception('$node is not of type DOMNode');
- }
- $curencdoc = $this->encdoc;
- $this->_resetTemplate();
- $encdoc = $this->encdoc;
- $this->encdoc = $curencdoc;
- $refuri = XMLSecurityDSig::generateGUID();
- $element = $encdoc->documentElement;
- $element->setAttribute("Id", $refuri);
- $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
- }
-
- public function setNode($node) {
- $this->rawNode = $node;
- }
-
- /**
- * Encrypt the selected node with the given key.
- *
- * @param XMLSecurityKey $objKey The encryption key and algorithm.
- * @param bool $replace Whether the encrypted node should be replaced in the original tree. Default is true.
- * @return DOMElement The <xenc:EncryptedData>-element.
- */
- public function encryptNode($objKey, $replace=true) {
- $data = '';
- if (empty($this->rawNode)) {
- throw new Exception('Node to encrypt has not been set');
- }
- if (! $objKey instanceof XMLSecurityKey) {
- throw new Exception('Invalid Key');
- }
- $doc = $this->rawNode->ownerDocument;
- $xPath = new DOMXPath($this->encdoc);
- $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
- $cipherValue = $objList->item(0);
- if ($cipherValue == null) {
- throw new Exception('Error locating CipherValue element within template');
- }
- switch ($this->type) {
- case (XMLSecEnc::Element):
- $data = $doc->saveXML($this->rawNode);
- $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
- break;
- case (XMLSecEnc::Content):
- $children = $this->rawNode->childNodes;
- foreach ($children AS $child) {
- $data .= $doc->saveXML($child);
- }
- $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
- break;
- default:
- throw new Exception('Type is currently not supported');
- }
-
- $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
- $encMethod->setAttribute('Algorithm', $objKey->getAlgorithm());
- $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
-
- $strEncrypt = base64_encode($objKey->encryptData($data));
- $value = $this->encdoc->createTextNode($strEncrypt);
- $cipherValue->appendChild($value);
-
- if ($replace) {
- switch ($this->type) {
- case (XMLSecEnc::Element):
- if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
- return $this->encdoc;
- }
- $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
- $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
- return $importEnc;
- case (XMLSecEnc::Content):
- $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
- while($this->rawNode->firstChild) {
- $this->rawNode->removeChild($this->rawNode->firstChild);
- }
- $this->rawNode->appendChild($importEnc);
- return $importEnc;
- }
- } else {
- return $this->encdoc->documentElement;
- }
- }
-
- public function encryptReferences($objKey) {
- $curRawNode = $this->rawNode;
- $curType = $this->type;
- foreach ($this->references AS $name=>$reference) {
- $this->encdoc = $reference["encnode"];
- $this->rawNode = $reference["node"];
- $this->type = $reference["type"];
- try {
- $encNode = $this->encryptNode($objKey);
- $this->references[$name]["encnode"] = $encNode;
- } catch (Exception $e) {
- $this->rawNode = $curRawNode;
- $this->type = $curType;
- throw $e;
- }
- }
- $this->rawNode = $curRawNode;
- $this->type = $curType;
- }
-
- /**
- * Retrieve the CipherValue text from this encrypted node.
- *
- * @return string|null The Ciphervalue text, or null if no CipherValue is found.
- */
- public function getCipherValue() {
- if (empty($this->rawNode)) {
- throw new Exception('Node to decrypt has not been set');
- }
-
- $doc = $this->rawNode->ownerDocument;
- $xPath = new DOMXPath($doc);
- $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
- /* Only handles embedded content right now and not a reference */
- $query = "./xmlencr:CipherData/xmlencr:CipherValue";
- $nodeset = $xPath->query($query, $this->rawNode);
- $node = $nodeset->item(0);
-
- if (!$node) {
- return null;
- }
-
- return base64_decode($node->nodeValue);
- }
-
- /**
- * Decrypt this encrypted node.
- *
- * The behaviour of this function depends on the value of $replace.
- * If $replace is false, we will return the decrypted data as a string.
- * If $replace is true, we will insert the decrypted element(s) into the
- * document, and return the decrypted element(s).
- *
- * @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
- * @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
- * @return string|DOMElement The decrypted data.
- */
- public function decryptNode($objKey, $replace=true) {
- if (! $objKey instanceof XMLSecurityKey) {
- throw new Exception('Invalid Key');
- }
-
- $encryptedData = $this->getCipherValue();
- if ($encryptedData) {
- $decrypted = $objKey->decryptData($encryptedData);
- if ($replace) {
- switch ($this->type) {
- case (XMLSecEnc::Element):
- $newdoc = new DOMDocument();
- $newdoc->loadXML($decrypted);
- if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
- return $newdoc;
- }
- $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, true);
- $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
- return $importEnc;
- case (XMLSecEnc::Content):
- if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
- $doc = $this->rawNode;
- } else {
- $doc = $this->rawNode->ownerDocument;
- }
- $newFrag = $doc->createDocumentFragment();
- $newFrag->appendXML($decrypted);
- $parent = $this->rawNode->parentNode;
- $parent->replaceChild($newFrag, $this->rawNode);
- return $parent;
- default:
- return $decrypted;
- }
- } else {
- return $decrypted;
- }
- } else {
- throw new Exception("Cannot locate encrypted data");
- }
- }
-
- public function encryptKey($srcKey, $rawKey, $append=true) {
- if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
- throw new Exception('Invalid Key');
- }
- $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
- $root = $this->encdoc->documentElement;
- $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
- if ($append) {
- $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
- $keyInfo->appendChild($encKey);
- } else {
- $this->encKey = $encKey;
- }
- $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
- $encMethod->setAttribute('Algorithm', $srcKey->getAlgorithm());
- if (! empty($srcKey->name)) {
- $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
- $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
- }
- $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
- $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
- if (is_array($this->references) && count($this->references) > 0) {
- $refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
- foreach ($this->references AS $name=>$reference) {
- $refuri = $reference["refuri"];
- $dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
- $dataRef->setAttribute("URI", '#' . $refuri);
- }
- }
- return;
- }
-
- public function decryptKey($encKey) {
- if (! $encKey->isEncrypted) {
- throw new Exception("Key is not Encrypted");
- }
- if (empty($encKey->key)) {
- throw new Exception("Key is missing data to perform the decryption");
- }
- return $this->decryptNode($encKey, false);
- }
-
- public function locateEncryptedData($element) {
- if ($element instanceof DOMDocument) {
- $doc = $element;
- } else {
- $doc = $element->ownerDocument;
- }
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $query = "//*[local-name()='EncryptedData' and namespace-uri()='".XMLSecEnc::XMLENCNS."']";
- $nodeset = $xpath->query($query);
- return $nodeset->item(0);
- }
- return null;
- }
-
- public function locateKey($node=null) {
- if (empty($node)) {
- $node = $this->rawNode;
- }
- if (! $node instanceof DOMNode) {
- return null;
- }
- if ($doc = $node->ownerDocument) {
- $xpath = new DOMXPath($doc);
- $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
- $query = ".//xmlsecenc:EncryptionMethod";
- $nodeset = $xpath->query($query, $node);
- if ($encmeth = $nodeset->item(0)) {
- $attrAlgorithm = $encmeth->getAttribute("Algorithm");
- try {
- $objKey = new XMLSecurityKey($attrAlgorithm, array('type'=>'private'));
- } catch (Exception $e) {
- return null;
- }
- return $objKey;
- }
- }
- return null;
- }
-
- static function staticLocateKeyInfo($objBaseKey=null, $node=null) {
- if (empty($node) || (! $node instanceof DOMNode)) {
- return null;
- }
- $doc = $node->ownerDocument;
- if (!$doc) {
- return null;
- }
-
- $xpath = new DOMXPath($doc);
- $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
- $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
- $query = "./xmlsecdsig:KeyInfo";
- $nodeset = $xpath->query($query, $node);
- $encmeth = $nodeset->item(0);
- if (!$encmeth) {
- /* No KeyInfo in EncryptedData / EncryptedKey. */
- return $objBaseKey;
- }
-
- foreach ($encmeth->childNodes AS $child) {
- switch ($child->localName) {
- case 'KeyName':
- if (! empty($objBaseKey)) {
- $objBaseKey->name = $child->nodeValue;
- }
- break;
- case 'KeyValue':
- foreach ($child->childNodes AS $keyval) {
- switch ($keyval->localName) {
- case 'DSAKeyValue':
- throw new Exception("DSAKeyValue currently not supported");
- case 'RSAKeyValue':
- $modulus = null;
- $exponent = null;
- if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
- $modulus = base64_decode($modulusNode->nodeValue);
- }
- if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
- $exponent = base64_decode($exponentNode->nodeValue);
- }
- if (empty($modulus) || empty($exponent)) {
- throw new Exception("Missing Modulus or Exponent");
- }
- $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
- $objBaseKey->loadKey($publicKey);
- break;
- }
- }
- break;
- case 'RetrievalMethod':
- $type = $child->getAttribute('Type');
- if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
- /* Unsupported key type. */
- break;
- }
- $uri = $child->getAttribute('URI');
- if ($uri[0] !== '#') {
- /* URI not a reference - unsupported. */
- break;
- }
- $id = substr($uri, 1);
-
- $query = "//xmlsecenc:EncryptedKey[@Id='$id']";
- $keyElement = $xpath->query($query)->item(0);
- if (!$keyElement) {
- throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
- }
-
- return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
- case 'EncryptedKey':
- return XMLSecurityKey::fromEncryptedKeyElement($child);
- case 'X509Data':
- if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
- if ($x509certNodes->length > 0) {
- $x509cert = $x509certNodes->item(0)->textContent;
- $x509cert = str_replace(array("\r", "\n", " "), "", $x509cert);
- $x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
- $objBaseKey->loadKey($x509cert, false, true);
- }
- }
- break;
- }
- }
- return $objBaseKey;
- }
-
- public function locateKeyInfo($objBaseKey=null, $node=null) {
- if (empty($node)) {
- $node = $this->rawNode;
- }
- return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml/AuthRequest.php b/3rdparty/vendor/onelogin/php-saml/lib/Saml/AuthRequest.php
deleted file mode 100644
index 4f08f5ff..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml/AuthRequest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-class OneLogin_Saml_AuthRequest
-{
-
- /**
- * @var OneLogin_Saml2_Auth object
- */
- protected $auth;
-
- /**
- * Constructs the OneLogin_Saml2_Auth, initializing
- * the SP SAML instance.
- *
- * @param array|object $settings SAML Toolkit Settings
- */
- public function __construct($settings)
- {
- $this->auth = new OneLogin_Saml2_Auth($settings);
- }
-
- /**
- * Obtains the SSO URL containing the AuthRequest
- * message deflated.
- *
- * @param string|null $returnTo
- *
- * @return string
- *
- * @throws OneLogin_Saml2_Error
- */
- public function getRedirectUrl($returnTo = null)
- {
- $settings = $this->auth->getSettings();
- $authnRequest = new OneLogin_Saml2_AuthnRequest($settings);
- $parameters = array('SAMLRequest' => $authnRequest->getRequest());
- if (!empty($returnTo)) {
- $parameters['RelayState'] = $returnTo;
- } else {
- $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
- }
- $url = OneLogin_Saml2_Utils::redirect($this->auth->getSSOurl(), $parameters, true);
- return $url;
- }
-
- /**
- * @return string
- */
- protected function _generateUniqueID()
- {
- return OneLogin_Saml2_Utils::generateUniqueID();
- }
-
- /**
- * @return string
- */
- protected function _getTimestamp()
- {
- $defaultTimezone = date_default_timezone_get();
- date_default_timezone_set('UTC');
- $timestamp = strftime("%Y-%m-%dT%H:%M:%SZ");
- date_default_timezone_set($defaultTimezone);
- return $timestamp;
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Metadata.php b/3rdparty/vendor/onelogin/php-saml/lib/Saml/Metadata.php
deleted file mode 100644
index 1073a90c..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Metadata.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-class OneLogin_Saml_Metadata
-{
- const VALIDITY_SECONDS = 604800; // 1 week
-
- protected $_settings;
-
- /**
- * @param array|object|null $settings Setting data
- */
- public function __construct($settings = null)
- {
- $auth = new OneLogin_Saml2_Auth($settings);
- $this->_settings = $auth->getSettings();
- }
-
- /**
- * @return string
- *
- * @throws OneLogin_Saml2_Error
- */
- public function getXml()
- {
- return $this->_settings->getSPMetadata();
- }
-
- /**
- * @return string
- */
- protected function _getMetadataValidTimestamp()
- {
- $timeZone = date_default_timezone_get();
- date_default_timezone_set('UTC');
- $time = strftime("%Y-%m-%dT%H:%M:%SZ", time() + self::VALIDITY_SECONDS);
- date_default_timezone_set($timeZone);
- return $time;
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Response.php b/3rdparty/vendor/onelogin/php-saml/lib/Saml/Response.php
deleted file mode 100644
index d9332a71..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Response.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-class OneLogin_Saml_Response extends OneLogin_Saml2_Response
-{
- /**
- * Constructor that process the SAML Response,
- * Internally initializes an SP SAML instance
- * and an OneLogin_Saml2_Response.
- *
- * @param array|object $oldSettings Settings
- * @param string $assertion SAML Response
- */
- public function __construct($oldSettings, $assertion)
- {
- $auth = new OneLogin_Saml2_Auth($oldSettings);
- $settings = $auth->getSettings();
- parent::__construct($settings, $assertion);
- }
-
- /**
- * Retrieves an Array with the logged user data.
- *
- * @return array
- */
- public function get_saml_attributes()
- {
- return $this->getAttributes();
- }
-
- /**
- * Retrieves the nameId
- *
- * @return string
- */
- public function get_nameid()
- {
- return $this->getNameId();
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Settings.php b/3rdparty/vendor/onelogin/php-saml/lib/Saml/Settings.php
deleted file mode 100644
index e9dbedc8..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml/Settings.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-/**
- * Holds SAML settings for the SamlResponse and SamlAuthRequest classes.
- *
- * These settings need to be filled in by the user prior to being used.
- */
-class OneLogin_Saml_Settings
-{
- const NAMEID_EMAIL_ADDRESS = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress';
- const NAMEID_X509_SUBJECT_NAME = 'urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName';
- const NAMEID_WINDOWS_DOMAIN_QUALIFIED_NAME = 'urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName';
- const NAMEID_KERBEROS = 'urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos';
- const NAMEID_ENTITY = 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity';
- const NAMEID_TRANSIENT = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient';
- const NAMEID_PERSISTENT = 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent';
-
- /**
- * The URL to submit SAML authentication requests to.
- * @var string
- */
- public $idpSingleSignOnUrl = '';
-
- /**
- * The URL to submit SAML Logout Request to.
- * @var string
- */
- public $idpSingleLogOutUrl = '';
-
- /**
- * The x509 certificate used to authenticate the request.
- * @var string
- */
- public $idpPublicCertificate = '';
-
- /**
- * The URL where to the SAML Response/SAML Assertion will be posted.
- * @var string
- */
- public $spReturnUrl = '';
-
- /**
- * The name of the application.
- * @var string
- */
- public $spIssuer = 'php-saml';
-
- /**
- * Specifies what format to return the authentication token, i.e, the email address.
- * @var string
- */
- public $requestedNameIdFormat = self::NAMEID_EMAIL_ADDRESS;
-
- /**
- * @return array<string,array> Values (compatibility with the new version)
- */
- public function getValues()
- {
- $values = array();
-
- $values['sp'] = array();
- $values['sp']['entityId'] = $this->spIssuer;
- $values['sp']['assertionConsumerService'] = array(
- 'url' => $this->spReturnUrl,
- );
- $values['sp']['NameIDFormat'] = $this->requestedNameIdFormat;
-
- $values['idp'] = array();
- $values['idp']['entityId'] = $this->idpSingleSignOnUrl;
- $values['idp']['singleSignOnService'] = array(
- 'url' => $this->idpSingleSignOnUrl,
- );
- $values['idp']['singleLogoutService'] = array(
- 'url' => $this->idpSingleLogOutUrl,
- );
- $values['idp']['x509cert'] = $this->idpPublicCertificate;
-
- return $values;
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml/XmlSec.php b/3rdparty/vendor/onelogin/php-saml/lib/Saml/XmlSec.php
deleted file mode 100644
index 919a62ef..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml/XmlSec.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-
-/**
- * Determine if the SAML response is valid using a provided x509 certificate.
- */
-class OneLogin_Saml_XmlSec
-{
- /**
- * A SamlResponse class provided to the constructor.
- * @var OneLogin_Saml_Settings
- */
- protected $_settings;
-
- /**
- * The document to be tested.
- * @var DomDocument
- */
- protected $_document;
-
- /**
- * Construct the SamlXmlSec object.
- *
- * @param OneLogin_Saml_Settings $settings A SamlResponse settings object containing the necessary
- * x509 certicate to test the document.
- * @param OneLogin_Saml_Response $response The document to test.
- */
- public function __construct(OneLogin_Saml_Settings $settings, OneLogin_Saml_Response $response)
- {
- $this->_settings = $settings;
- $this->_document = clone $response->document;
- }
-
- /**
- * Verify that the document only contains a single Assertion
- *
- * @return bool TRUE if the document passes.
- */
- public function validateNumAssertions()
- {
- $rootNode = $this->_document;
- $assertionNodes = $rootNode->getElementsByTagName('Assertion');
- return ($assertionNodes->length == 1);
- }
-
- /**
- * Verify that the document is still valid according
- *
- * @return bool
- */
- public function validateTimestamps()
- {
- $rootNode = $this->_document;
- $timestampNodes = $rootNode->getElementsByTagName('Conditions');
- for ($i = 0; $i < $timestampNodes->length; $i++) {
- $nbAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotBefore");
- $naAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotOnOrAfter");
- if ($nbAttribute && strtotime($nbAttribute->textContent) > time()) {
- return false;
- }
- if ($naAttribute && strtotime($naAttribute->textContent) <= time()) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return bool
- *
- * @throws Exception
- */
- public function isValid()
- {
- $singleAssertion = $this->validateNumAssertions();
- if (!$singleAssertion) {
- throw new Exception('Multiple assertions are not supported');
- }
-
- $validTimestamps = $this->validateTimestamps();
- if (!$validTimestamps) {
- throw new Exception('Timing issues (please check your clock settings)');
- }
-
- $objXMLSecDSig = new XMLSecurityDSig();
-
- $objDSig = $objXMLSecDSig->locateSignature($this->_document);
- if (!$objDSig) {
- throw new Exception('Cannot locate Signature Node');
- }
- $objXMLSecDSig->canonicalizeSignedInfo();
- $objXMLSecDSig->idKeys = array('ID');
-
- $objKey = $objXMLSecDSig->locateKey();
- if (!$objKey) {
- throw new Exception('We have no idea about the key');
- }
-
- try {
- $objXMLSecDSig->validateReference();
- } catch (Exception $e) {
- throw new Exception('Reference Validation Failed');
- }
-
- XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig);
-
- $objKey->loadKey($this->_settings->idpPublicCertificate, false, true);
-
- return ($objXMLSecDSig->verify($objKey) === 1);
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/version.json b/3rdparty/vendor/onelogin/php-saml/lib/Saml2/version.json
deleted file mode 100644
index 5ca57d3a..00000000
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/version.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "php-saml": {
- "version": "2.10.5",
- "released": "13/03/2017"
- }
-}
diff --git a/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.mo b/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.mo
deleted file mode 100644
index 4898ddb5..00000000
--- a/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.mo
+++ /dev/null
Binary files differ
diff --git a/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.po b/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.po
deleted file mode 100644
index c8e9ef97..00000000
--- a/3rdparty/vendor/onelogin/php-saml/locale/en_US/LC_MESSAGES/phptoolkit.po
+++ /dev/null
@@ -1,26 +0,0 @@
-msgid ""
-msgstr ""
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "test"
-msgstr "test"
-
-msgid "test2: %s"
-msgstr "test2: %s"
-
-#: index.php:15 endpoints/acs.php:35
-msgid "User attributes:"
-msgstr ""
-
-#: index.php:16 endpoints/acs.php:36
-msgid "Name"
-msgstr ""
-
-#: index.php:16 endpoints/acs.php:36
-msgid "Values"
-msgstr ""
-
-#: index.php:26 endpoints/acs.php:46
-msgid "Attributes not found"
-msgstr ""
diff --git a/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.mo b/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.mo
deleted file mode 100644
index 9f277740..00000000
--- a/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.mo
+++ /dev/null
Binary files differ
diff --git a/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.po b/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.po
deleted file mode 100644
index a989377d..00000000
--- a/3rdparty/vendor/onelogin/php-saml/locale/es_ES/LC_MESSAGES/phptoolkit.po
+++ /dev/null
@@ -1,27 +0,0 @@
-msgid ""
-msgstr ""
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-msgid "test"
-msgstr "prueba"
-
-msgid "test2: %s"
-msgstr "prueba2: %s"
-
-#: index.php:15 endpoints/acs.php:35
-msgid "User attributes:"
-msgstr "Atributos del usuario:"
-
-#: index.php:16 endpoints/acs.php:36
-msgid "Name"
-msgstr "Nombre"
-
-#: index.php:16 endpoints/acs.php:36
-msgid "Values"
-msgstr "Valores"
-
-#: index.php:26 endpoints/acs.php:46
-msgid "Attributes not found"
-msgstr "Atributos no encontrados"
-
diff --git a/3rdparty/vendor/onelogin/php-saml/phpdoc.xml b/3rdparty/vendor/onelogin/php-saml/phpdoc.xml
deleted file mode 100644
index e9f38d82..00000000
--- a/3rdparty/vendor/onelogin/php-saml/phpdoc.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<phpdoc>
- <title>OneLogin's SAML PHP Toolkit</title>
- <parser>
- <default-package-name>OneLogin_SAML_Toolkit</default-package-name>
- <target>docs/Saml3</target>
- </parser>
- <extensions>
- <extension>php</extension>
- </extensions>
- <transformer>
- <target>docs/Saml3</target>
- </transformer>
- <transformations>
- <template name="onelogin" />
-<!-- <template name="clean" /> -->
- </transformations>
- <files>
- <directory>lib/Saml2/*</directory>
- <ignore>lib/Saml/*</ignore>
- <ignore>tests/*</ignore>
- <ignore>demo1/*</ignore>
- <ignore>demo2/*</ignore>
- <ignore>demo-old/*</ignore>
- <ignore>endpoints/*</ignore>
- <ignore>extlib/*</ignore>
- <ignore>locale/*</ignore>
- <ignore>docs/*</ignore>
- <ignore>vendor/*</ignore>
- <ignore>compatibility.php</ignore>
- <ignore>_toolkit_loader.php</ignore>
- <ignore>settings.php</ignore>
- <ignore>settings_example.php</ignore>
- <ignore>advanced_settings.php</ignore>
- <ignore>advanced_settings_example</ignore>
- </files>
-</phpdoc>
diff --git a/3rdparty/vendor/onelogin/php-saml/settings_example.php b/3rdparty/vendor/onelogin/php-saml/settings_example.php
index ff665e97..c9f41088 100644
--- a/3rdparty/vendor/onelogin/php-saml/settings_example.php
+++ b/3rdparty/vendor/onelogin/php-saml/settings_example.php
@@ -1,6 +1,6 @@
<?php
-$settings = array (
+$settings = array(
// If 'strict' is True, then the PHP Toolkit will reject unsigned
// or unencrypted messages if it expects them signed or encrypted
// Also will reject the messages if not strictly follow the SAML
@@ -10,19 +10,19 @@ $settings = array (
// Enable debug mode (to print errors)
'debug' => false,
- // Set a BaseURL to be used instead of try to guess
+ // Set a BaseURL to be used instead of try to guess
// the BaseURL of the view that process the SAML Message.
// Ex. http://sp.example.com/
- // http://example.com/sp/
+ // http://example.com/sp/
'baseurl' => null,
// Service Provider Data that we are deploying
- 'sp' => array (
+ 'sp' => array(
// Identifier of the SP entity (must be a URI)
'entityId' => '',
// Specifies info about where and how the <AuthnResponse> message MUST be
// returned to the requester, in this case our SP.
- 'assertionConsumerService' => array (
+ 'assertionConsumerService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -32,7 +32,7 @@ $settings = array (
),
// If you need to specify requested attributes, set a
// attributeConsumingService. nameFormat, attributeValue and
- // friendlyName can be omitted. Otherwise remove this section.
+ // friendlyName can be omitted. Otherwise remove this section.
"attributeConsumingService"=> array(
"ServiceName" => "SP test",
"serviceDescription" => "Test Service",
@@ -48,7 +48,7 @@ $settings = array (
),
// Specifies info about where and how the <Logout Response> message MUST be
// returned to the requester, in this case our SP.
- 'singleLogoutService' => array (
+ 'singleLogoutService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -65,14 +65,23 @@ $settings = array (
// the certs folder. But we can also provide them with the following parameters
'x509cert' => '',
'privateKey' => '',
+
+ /*
+ * Key rollover
+ * If you plan to update the SP x509cert and privateKey
+ * you can define here the new x509cert and it will be
+ * published on the SP metadata so Identity Providers can
+ * read them and get ready for rollover.
+ */
+ // 'x509certNew' => '',
),
// Identity Provider Data that we want connect with our SP
- 'idp' => array (
+ 'idp' => array(
// Identifier of the IdP entity (must be a URI)
'entityId' => '',
// SSO endpoint info of the IdP. (Authentication Request protocol)
- 'singleSignOnService' => array (
+ 'singleSignOnService' => array(
// URL Target of the IdP where the SP will send the Authentication Request Message
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -81,7 +90,7 @@ $settings = array (
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
),
// SLO endpoint info of the IdP.
- 'singleLogoutService' => array (
+ 'singleLogoutService' => array(
// URL Location of the IdP where the SP will send the SLO Request
'url' => '',
// SAML protocol binding to be used when returning the <Response>
@@ -92,7 +101,10 @@ $settings = array (
// Public x509 certificate of the IdP
'x509cert' => '',
/*
- * Instead of use the whole x509cert you can use a fingerprint
+ * Instead of use the whole x509cert you can use a fingerprint in
+ * order to validate the SAMLResponse, but we don't recommend to use
+ * that method on production since is exploitable by a collision
+ * attack.
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
* or add for example the -sha256 , -sha384 or -sha512 parameter)
*
@@ -102,5 +114,21 @@ $settings = array (
*/
// 'certFingerprint' => '',
// 'certFingerprintAlgorithm' => 'sha1',
+
+ /* In some scenarios the IdP uses different certificates for
+ * signing/encryption, or is under key rollover phase and more
+ * than one certificate is published on IdP metadata.
+ * In order to handle that the toolkit offers that parameter.
+ * (when used, 'x509cert' and 'certFingerprint' values are
+ * ignored).
+ */
+ // 'x509certMulti' => array(
+ // 'signing' => array(
+ // 0 => '<cert1-string>',
+ // ),
+ // 'encryption' => array(
+ // 0 => '<cert2-string>',
+ // )
+ // ),
),
);
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Auth.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Auth.php
index ff501321..636c0342 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Auth.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Auth.php
@@ -1,15 +1,33 @@
<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+
+use Exception;
/**
* Main class of OneLogin's PHP Toolkit
- *
*/
-class OneLogin_Saml2_Auth
+class Auth
{
/**
* Settings data.
*
- * @var OneLogin_Saml2_Settings
+ * @var Settings
*/
private $_settings;
@@ -21,6 +39,13 @@ class OneLogin_Saml2_Auth
private $_attributes = array();
/**
+ * User attributes data with FriendlyName index.
+ *
+ * @var array
+ */
+ private $_attributesWithFriendlyName = array();
+
+ /**
* NameID
*
* @var string
@@ -35,6 +60,20 @@ class OneLogin_Saml2_Auth
private $_nameidFormat;
/**
+ * NameID NameQualifier
+ *
+ * @var string
+ */
+ private $_nameidNameQualifier;
+
+ /**
+ * NameID SP NameQualifier
+ *
+ * @var string
+ */
+ private $_nameidSPNameQualifier;
+
+ /**
* If user is authenticated.
*
* @var bool
@@ -54,7 +93,7 @@ class OneLogin_Saml2_Auth
* SessionNotOnOrAfter. When the user is logged, this stored it
* from the AuthnStatement of the SAML Response
*
- * @var DateTime
+ * @var int|null
*/
private $_sessionExpiration;
@@ -76,7 +115,7 @@ class OneLogin_Saml2_Auth
* The NotOnOrAfter value of the valid SubjectConfirmationData
* node (if any) of the last assertion processed
*
- * @var DateTime
+ * @var int
*/
private $_lastAssertionNotOnOrAfter;
@@ -88,11 +127,18 @@ class OneLogin_Saml2_Auth
private $_errors = array();
/**
- * Reason of the last error.
+ * Last error object.
*
- * @var string
+ * @var Error|null
+ */
+ private $_lastErrorException;
+
+ /**
+ * Last error.
+ *
+ * @var string|null
*/
- private $_errorReason;
+ private $_lastError;
/**
* Last AuthNRequest ID or LogoutRequest ID generated by this Service Provider
@@ -114,24 +160,27 @@ class OneLogin_Saml2_Auth
* (SAMLResponse, LogoutResponse). If the SAMLResponse was
* encrypted, by default tries to return the decrypted XML
*
- * @var string
+ * @var string|\DomDocument|null
*/
private $_lastResponse;
/**
* Initializes the SP SAML instance.
*
- * @param array|object|null $oldSettings Setting data (You can provide a OneLogin_Saml_Settings, the settings object of the Saml folder implementation)
+ * @param array|null $settings Setting data
+ *
+ * @throws Exception
+ * @throws Error
*/
- public function __construct($oldSettings = null)
+ public function __construct(array $settings = null)
{
- $this->_settings = new OneLogin_Saml2_Settings($oldSettings);
+ $this->_settings = new Settings($settings);
}
/**
* Returns the settings info
*
- * @return OneLogin_Saml2_Settings The settings data.
+ * @return Settings The settings data.
*/
public function getSettings()
{
@@ -143,14 +192,14 @@ class OneLogin_Saml2_Auth
*
* @param bool $value Strict parameter
*
- * @return array The settings data.
+ * @throws Error
*/
public function setStrict($value)
{
- if (! (is_bool($value))) {
- throw new OneLogin_Saml2_Error(
+ if (!is_bool($value)) {
+ throw new Error(
'Invalid value passed to setStrict()',
- OneLogin_Saml2_Error::SETTINGS_INVALID_SYNTAX
+ Error::SETTINGS_INVALID_SYNTAX
);
}
@@ -162,21 +211,25 @@ class OneLogin_Saml2_Auth
*
* @param string|null $requestId The ID of the AuthNRequest sent by this SP to the IdP
*
- * @throws OneLogin_Saml2_Error
+ * @throws Error
+ * @throws ValidationError
*/
public function processResponse($requestId = null)
{
$this->_errors = array();
- $this->_errorReason = null;
- if (isset($_POST) && isset($_POST['SAMLResponse'])) {
+ $this->_lastError = $this->_lastErrorException = null;
+ if (isset($_POST['SAMLResponse'])) {
// AuthnResponse -- HTTP_POST Binding
- $response = new OneLogin_Saml2_Response($this->_settings, $_POST['SAMLResponse']);
+ $response = new Response($this->_settings, $_POST['SAMLResponse']);
$this->_lastResponse = $response->getXMLDocument();
if ($response->isValid($requestId)) {
$this->_attributes = $response->getAttributes();
+ $this->_attributesWithFriendlyName = $response->getAttributesWithFriendlyName();
$this->_nameid = $response->getNameId();
$this->_nameidFormat = $response->getNameIdFormat();
+ $this->_nameidNameQualifier = $response->getNameIdNameQualifier();
+ $this->_nameidSPNameQualifier = $response->getNameIdSPNameQualifier();
$this->_authenticated = true;
$this->_sessionIndex = $response->getSessionIndex();
$this->_sessionExpiration = $response->getSessionNotOnOrAfter();
@@ -185,13 +238,14 @@ class OneLogin_Saml2_Auth
$this->_lastAssertionNotOnOrAfter = $response->getAssertionNotOnOrAfter();
} else {
$this->_errors[] = 'invalid_response';
- $this->_errorReason = $response->getError();
+ $this->_lastErrorException = $response->getErrorException();
+ $this->_lastError = $response->getError();
}
} else {
$this->_errors[] = 'invalid_binding';
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SAML Response not found, Only supported HTTP_POST Binding',
- OneLogin_Saml2_Error::SAML_RESPONSE_NOT_FOUND
+ Error::SAML_RESPONSE_NOT_FOUND
);
}
}
@@ -199,55 +253,58 @@ class OneLogin_Saml2_Auth
/**
* Process the SAML Logout Response / Logout Request sent by the IdP.
*
- * @param bool $keepLocalSession When false will destroy the local session, otherwise will keep it
- * @param string|null $requestId The ID of the LogoutRequest sent by this SP to the IdP
- * @param bool $retrieveParametersFromServer
- * @param callable $cbDeleteSession
- * @param bool $stay True if we want to stay (returns the url string) False to redirect
+ * @param bool $keepLocalSession When false will destroy the local session, otherwise will keep it
+ * @param string|null $requestId The ID of the LogoutRequest sent by this SP to the IdP
+ * @param bool $retrieveParametersFromServer True if we want to use parameters from $_SERVER to validate the signature
+ * @param callable $cbDeleteSession Callback to be executed to delete session
+ * @param bool $stay True if we want to stay (returns the url string) False to redirect
*
- * @return string|void
+ * @return string|null
*
- * @throws OneLogin_Saml2_Error
+ * @throws Error
*/
public function processSLO($keepLocalSession = false, $requestId = null, $retrieveParametersFromServer = false, $cbDeleteSession = null, $stay = false)
{
$this->_errors = array();
- $this->_errorReason = null;
- if (isset($_GET) && isset($_GET['SAMLResponse'])) {
- $logoutResponse = new OneLogin_Saml2_LogoutResponse($this->_settings, $_GET['SAMLResponse']);
+ $this->_lastError = $this->_lastErrorException = null;
+ if (isset($_GET['SAMLResponse'])) {
+ $logoutResponse = new LogoutResponse($this->_settings, $_GET['SAMLResponse']);
$this->_lastResponse = $logoutResponse->getXML();
if (!$logoutResponse->isValid($requestId, $retrieveParametersFromServer)) {
$this->_errors[] = 'invalid_logout_response';
- $this->_errorReason = $logoutResponse->getError();
- } else if ($logoutResponse->getStatus() !== OneLogin_Saml2_Constants::STATUS_SUCCESS) {
+ $this->_lastErrorException = $logoutResponse->getErrorException();
+ $this->_lastError = $logoutResponse->getError();
+
+ } else if ($logoutResponse->getStatus() !== Constants::STATUS_SUCCESS) {
$this->_errors[] = 'logout_not_success';
} else {
$this->_lastMessageId = $logoutResponse->id;
if (!$keepLocalSession) {
if ($cbDeleteSession === null) {
- OneLogin_Saml2_Utils::deleteLocalSession();
+ Utils::deleteLocalSession();
} else {
call_user_func($cbDeleteSession);
}
}
}
- } else if (isset($_GET) && isset($_GET['SAMLRequest'])) {
- $logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, $_GET['SAMLRequest']);
+ } else if (isset($_GET['SAMLRequest'])) {
+ $logoutRequest = new LogoutRequest($this->_settings, $_GET['SAMLRequest']);
$this->_lastRequest = $logoutRequest->getXML();
if (!$logoutRequest->isValid($retrieveParametersFromServer)) {
$this->_errors[] = 'invalid_logout_request';
- $this->_errorReason = $logoutRequest->getError();
+ $this->_lastErrorException = $logoutRequest->getErrorException();
+ $this->_lastError = $logoutRequest->getError();
} else {
if (!$keepLocalSession) {
if ($cbDeleteSession === null) {
- OneLogin_Saml2_Utils::deleteLocalSession();
+ Utils::deleteLocalSession();
} else {
call_user_func($cbDeleteSession);
}
}
$inResponseTo = $logoutRequest->id;
$this->_lastMessageId = $logoutRequest->id;
- $responseBuilder = new OneLogin_Saml2_LogoutResponse($this->_settings);
+ $responseBuilder = new LogoutResponse($this->_settings);
$responseBuilder->build($inResponseTo);
$this->_lastResponse = $responseBuilder->getXML();
@@ -269,9 +326,9 @@ class OneLogin_Saml2_Auth
}
} else {
$this->_errors[] = 'invalid_binding';
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SAML LogoutRequest/LogoutResponse not found. Only supported HTTP_REDIRECT Binding',
- OneLogin_Saml2_Error::SAML_LOGOUTMESSAGE_NOT_FOUND
+ Error::SAML_LOGOUTMESSAGE_NOT_FOUND
);
}
}
@@ -283,17 +340,18 @@ class OneLogin_Saml2_Auth
* @param string $url The target URL to redirect the user.
* @param array $parameters Extra parameters to be passed as part of the url
* @param bool $stay True if we want to stay (returns the url string) False to redirect
+ *
+ * @return string|null
*/
- public function redirectTo($url = '', $parameters = array(), $stay = false)
+ public function redirectTo($url = '', array $parameters = array(), $stay = false)
{
- assert('is_string($url)');
- assert('is_array($parameters)');
+ assert(is_string($url));
if (empty($url) && isset($_REQUEST['RelayState'])) {
$url = $_REQUEST['RelayState'];
}
- return OneLogin_Saml2_Utils::redirect($url, $parameters, $stay);
+ return Utils::redirect($url, $parameters, $stay);
}
/**
@@ -316,6 +374,17 @@ class OneLogin_Saml2_Auth
return $this->_attributes;
}
+
+ /**
+ * Returns the set of SAML attributes indexed by FriendlyName
+ *
+ * @return array Attributes of the user.
+ */
+ public function getAttributesWithFriendlyName()
+ {
+ return $this->_attributesWithFriendlyName;
+ }
+
/**
* Returns the nameID
*
@@ -337,6 +406,26 @@ class OneLogin_Saml2_Auth
}
/**
+ * Returns the nameID NameQualifier
+ *
+ * @return string The nameID NameQualifier of the assertion
+ */
+ public function getNameIdNameQualifier()
+ {
+ return $this->_nameidNameQualifier;
+ }
+
+ /**
+ * Returns the nameID SP NameQualifier
+ *
+ * @return string The nameID SP NameQualifier of the assertion
+ */
+ public function getNameIdSPNameQualifier()
+ {
+ return $this->_nameidSPNameQualifier;
+ }
+
+ /**
* Returns the SessionIndex
*
* @return string|null The SessionIndex of the assertion
@@ -349,7 +438,7 @@ class OneLogin_Saml2_Auth
/**
* Returns the SessionNotOnOrAfter
*
- * @return DateTime|null The SessionNotOnOrAfter of the assertion
+ * @return int|null The SessionNotOnOrAfter of the assertion
*/
public function getSessionExpiration()
{
@@ -369,11 +458,22 @@ class OneLogin_Saml2_Auth
/**
* Returns the reason for the last error
*
- * @return string Error reason
+ * @return string|null Error reason
*/
public function getLastErrorReason()
{
- return $this->_errorReason;
+ return $this->_lastError;
+ }
+
+
+ /**
+ * Returns the last error
+ *
+ * @return Exception|null Error
+ */
+ public function getLastErrorException()
+ {
+ return $this->_lastErrorException;
}
/**
@@ -385,7 +485,7 @@ class OneLogin_Saml2_Auth
*/
public function getAttribute($name)
{
- assert('is_string($name)');
+ assert(is_string($name));
$value = null;
if (isset($this->_attributes[$name])) {
@@ -395,22 +495,39 @@ class OneLogin_Saml2_Auth
}
/**
+ * Returns the requested SAML attribute indexed by FriendlyName
+ *
+ * @param string $friendlyName The requested attribute of the user.
+ *
+ * @return array|null Requested SAML attribute ($friendlyName).
+ */
+ public function getAttributeWithFriendlyName($friendlyName)
+ {
+ assert(is_string($friendlyName));
+ $value = null;
+ if (isset($this->_attributesWithFriendlyName[$friendlyName])) {
+ return $this->_attributesWithFriendlyName[$friendlyName];
+ }
+ return $value;
+ }
+
+ /**
* Initiates the SSO process.
*
* @param string|null $returnTo The target URL the user should be returned to after login.
* @param array $parameters Extra parameters to be added to the GET
- * @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true'
- * @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true'
+ * @param bool $forceAuthn When true the AuthNRequest will set the ForceAuthn='true'
+ * @param bool $isPassive When true the AuthNRequest will set the Ispassive='true'
* @param bool $stay True if we want to stay (returns the url string) False to redirect
- * @param bool $setNameIdPolicy When true the AuthNReuqest will set a nameIdPolicy element
+ * @param bool $setNameIdPolicy When true the AuthNRequest will set a nameIdPolicy element
*
- * @return If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
+ * @return string|null If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
+ *
+ * @throws Error
*/
- public function login($returnTo = null, $parameters = array(), $forceAuthn = false, $isPassive = false, $stay = false, $setNameIdPolicy = true)
+ public function login($returnTo = null, array $parameters = array(), $forceAuthn = false, $isPassive = false, $stay = false, $setNameIdPolicy = true)
{
- assert('is_array($parameters)');
-
- $authnRequest = new OneLogin_Saml2_AuthnRequest($this->_settings, $forceAuthn, $isPassive, $setNameIdPolicy);
+ $authnRequest = new AuthnRequest($this->_settings, $forceAuthn, $isPassive, $setNameIdPolicy);
$this->_lastRequest = $authnRequest->getXML();
$this->_lastRequestID = $authnRequest->getId();
@@ -421,7 +538,7 @@ class OneLogin_Saml2_Auth
if (!empty($returnTo)) {
$parameters['RelayState'] = $returnTo;
} else {
- $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
+ $parameters['RelayState'] = Utils::getSelfRoutedURLNoQuery();
}
$security = $this->_settings->getSecurityData();
@@ -436,26 +553,25 @@ class OneLogin_Saml2_Auth
/**
* Initiates the SLO process.
*
- * @param string|null $returnTo The target URL the user should be returned to after logout.
- * @param array $parameters Extra parameters to be added to the GET
- * @param string|null $nameId The NameID that will be set in the LogoutRequest.
- * @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
- * @param bool $stay True if we want to stay (returns the url string) False to redirect
- * @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
+ * @param string|null $returnTo The target URL the user should be returned to after logout.
+ * @param array $parameters Extra parameters to be added to the GET
+ * @param string|null $nameId The NameID that will be set in the LogoutRequest.
+ * @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
+ * @param bool $stay True if we want to stay (returns the url string) False to redirect
+ * @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
+ * @param string|null $nameIdNameQualifier The NameID NameQualifier will be set in the LogoutRequest.
*
- * @return If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
+ * @return string|null If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
*
- * @throws OneLogin_Saml2_Error
+ * @throws Error
*/
- public function logout($returnTo = null, $parameters = array(), $nameId = null, $sessionIndex = null, $stay = false, $nameIdFormat = null)
+ public function logout($returnTo = null, array $parameters = array(), $nameId = null, $sessionIndex = null, $stay = false, $nameIdFormat = null, $nameIdNameQualifier = null, $nameIdSPNameQualifier = null)
{
- assert('is_array($parameters)');
-
$sloUrl = $this->getSLOurl();
if (empty($sloUrl)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'The IdP does not support Single Log Out',
- OneLogin_Saml2_Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED
+ Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED
);
}
@@ -466,7 +582,7 @@ class OneLogin_Saml2_Auth
$nameIdFormat = $this->_nameidFormat;
}
- $logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, null, $nameId, $sessionIndex, $nameIdFormat);
+ $logoutRequest = new LogoutRequest($this->_settings, null, $nameId, $sessionIndex, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
$this->_lastRequest = $logoutRequest->getXML();
$this->_lastRequestID = $logoutRequest->id;
@@ -477,7 +593,7 @@ class OneLogin_Saml2_Auth
if (!empty($returnTo)) {
$parameters['RelayState'] = $returnTo;
} else {
- $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
+ $parameters['RelayState'] = Utils::getSelfRoutedURLNoQuery();
}
$security = $this->_settings->getSecurityData();
@@ -504,7 +620,7 @@ class OneLogin_Saml2_Auth
/**
* Gets the SLO url.
*
- * @return string The url of the Single Logout Service
+ * @return string|null The url of the Single Logout Service
*/
public function getSLOurl()
{
@@ -529,46 +645,18 @@ class OneLogin_Saml2_Auth
/**
* Generates the Signature for a SAML Request
*
- * @param string $samlRequest The SAML Request
- * @param string $relayState The RelayState
+ * @param string $samlRequest The SAML Request
+ * @param string $relayState The RelayState
* @param string $signAlgorithm Signature algorithm method
*
* @return string A base64 encoded signature
*
* @throws Exception
- * @throws OneLogin_Saml2_Error
+ * @throws Error
*/
- public function buildRequestSignature($samlRequest, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA1)
+ public function buildRequestSignature($samlRequest, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA256)
{
- $key = $this->_settings->getSPkey();
- if (empty($key)) {
- throw new OneLogin_Saml2_Error(
- "Trying to sign the SAML Request but can't load the SP private key",
- OneLogin_Saml2_Error::PRIVATE_KEY_NOT_FOUND
- );
- }
-
- $key = $this->_settings->getSPkey();
-
- $objKey = new XMLSecurityKey($signAlgorithm, array('type' => 'private'));
- $objKey->loadKey($key, false);
-
- $security = $this->_settings->getSecurityData();
- if ($security['lowercaseUrlencoding']) {
- $msg = 'SAMLRequest='.rawurlencode($samlRequest);
- if (isset($relayState)) {
- $msg .= '&RelayState='.rawurlencode($relayState);
- }
- $msg .= '&SigAlg=' . rawurlencode($signAlgorithm);
- } else {
- $msg = 'SAMLRequest='.urlencode($samlRequest);
- if (isset($relayState)) {
- $msg .= '&RelayState='.urlencode($relayState);
- }
- $msg .= '&SigAlg=' . urlencode($signAlgorithm);
- }
- $signature = $objKey->signData($msg);
- return base64_encode($signature);
+ return $this->buildMessageSignature($samlRequest, $relayState, $signAlgorithm, "SAMLRequest");
}
/**
@@ -581,16 +669,37 @@ class OneLogin_Saml2_Auth
* @return string A base64 encoded signature
*
* @throws Exception
- * @throws OneLogin_Saml2_Error
+ * @throws Error
+ */
+ public function buildResponseSignature($samlResponse, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA256)
+ {
+ return $this->buildMessageSignature($samlResponse, $relayState, $signAlgorithm, "SAMLResponse");
+ }
+
+ /**
+ * Generates the Signature for a SAML Message
+ *
+ * @param string $samlMessage The SAML Message
+ * @param string $relayState The RelayState
+ * @param string $signAlgorithm Signature algorithm method
+ * @param string $type "SAMLRequest" or "SAMLResponse"
+ *
+ * @return string A base64 encoded signature
+ *
+ * @throws Exception
+ * @throws Error
*/
- public function buildResponseSignature($samlResponse, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA1)
+ private function buildMessageSignature($samlMessage, $relayState, $signAlgorithm = XMLSecurityKey::RSA_SHA256, $type="SAMLRequest")
{
$key = $this->_settings->getSPkey();
if (empty($key)) {
- throw new OneLogin_Saml2_Error(
- "Trying to sign the SAML Response but can't load the SP private key",
- OneLogin_Saml2_Error::PRIVATE_KEY_NOT_FOUND
- );
+ if ($type == "SAMLRequest") {
+ $errorMsg = "Trying to sign the SAML Request but can't load the SP private key";
+ } else {
+ $errorMsg = "Trying to sign the SAML Response but can't load the SP private key";
+ }
+
+ throw new Error($errorMsg, Error::PRIVATE_KEY_NOT_FOUND);
}
$objKey = new XMLSecurityKey($signAlgorithm, array('type' => 'private'));
@@ -598,13 +707,13 @@ class OneLogin_Saml2_Auth
$security = $this->_settings->getSecurityData();
if ($security['lowercaseUrlencoding']) {
- $msg = 'SAMLResponse='.rawurlencode($samlResponse);
+ $msg = $type.'='.rawurlencode($samlMessage);
if (isset($relayState)) {
$msg .= '&RelayState='.rawurlencode($relayState);
}
$msg .= '&SigAlg=' . rawurlencode($signAlgorithm);
} else {
- $msg = 'SAMLResponse='.urlencode($samlResponse);
+ $msg = $type.'='.urlencode($samlMessage);
if (isset($relayState)) {
$msg .= '&RelayState='.urlencode($relayState);
}
@@ -631,7 +740,7 @@ class OneLogin_Saml2_Auth
}
/**
- * @return The NotOnOrAfter value of the valid
+ * @return int The NotOnOrAfter value of the valid
* SubjectConfirmationData node (if any)
* of the last assertion processed
*/
@@ -644,7 +753,7 @@ class OneLogin_Saml2_Auth
* Returns the most recently-constructed/processed
* XML SAML request (AuthNRequest, LogoutRequest)
*
- * @return string The Request XML
+ * @return string|null The Request XML
*/
public function getLastRequestXML()
{
@@ -657,7 +766,7 @@ class OneLogin_Saml2_Auth
* If the SAMLResponse was encrypted, by default tries
* to return the decrypted XML.
*
- * @return string The Response XML
+ * @return string|null The Response XML
*/
public function getLastResponseXML()
{
@@ -669,7 +778,7 @@ class OneLogin_Saml2_Auth
$response = $this->_lastResponse->saveXML();
}
}
-
+
return $response;
}
}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php
index e6e49a2f..2dd6bd20 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/AuthnRequest.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/AuthnRequest.php
@@ -1,26 +1,42 @@
<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
/**
* SAML 2 Authentication Request
- *
*/
-class OneLogin_Saml2_AuthnRequest
+class AuthnRequest
{
-
/**
* Object that represents the setting info
- * @var OneLogin_Saml2_Settings
+ *
+ * @var Settings
*/
protected $_settings;
/**
* SAML AuthNRequest string
+ *
* @var string
*/
private $_authnRequest;
/**
* SAML AuthNRequest ID.
+ *
* @var string
*/
private $_id;
@@ -28,12 +44,12 @@ class OneLogin_Saml2_AuthnRequest
/**
* Constructs the AuthnRequest object.
*
- * @param OneLogin_Saml2_Settings $settings Settings
- * @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true'
- * @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true'
- * @param bool $setNameIdPolicy When true the AuthNReuqest will set a nameIdPolicy
+ * @param Settings $settings SAML Toolkit Settings
+ * @param bool $forceAuthn When true the AuthNReuqest will set the ForceAuthn='true'
+ * @param bool $isPassive When true the AuthNReuqest will set the Ispassive='true'
+ * @param bool $setNameIdPolicy When true the AuthNReuqest will set a nameIdPolicy
*/
- public function __construct(OneLogin_Saml2_Settings $settings, $forceAuthn = false, $isPassive = false, $setNameIdPolicy = true)
+ public function __construct(\OneLogin\Saml2\Settings $settings, $forceAuthn = false, $isPassive = false, $setNameIdPolicy = true)
{
$this->_settings = $settings;
@@ -41,14 +57,14 @@ class OneLogin_Saml2_AuthnRequest
$idpData = $this->_settings->getIdPData();
$security = $this->_settings->getSecurityData();
- $id = OneLogin_Saml2_Utils::generateUniqueID();
- $issueInstant = OneLogin_Saml2_Utils::parseTime2SAML(time());
+ $id = Utils::generateUniqueID();
+ $issueInstant = Utils::parseTime2SAML(time());
$nameIdPolicyStr = '';
if ($setNameIdPolicy) {
$nameIDPolicyFormat = $spData['NameIDFormat'];
if (isset($security['wantNameIdEncrypted']) && $security['wantNameIdEncrypted']) {
- $nameIDPolicyFormat = OneLogin_Saml2_Constants::NAMEID_ENCRYPTED;
+ $nameIDPolicyFormat = Constants::NAMEID_ENCRYPTED;
}
$nameIdPolicyStr = <<<NAMEIDPOLICY
@@ -93,7 +109,6 @@ ISPASSIVE;
$requestedAuthnStr = '';
if (isset($security['requestedAuthnContext']) && $security['requestedAuthnContext'] !== false) {
-
$authnComparison = 'exact';
if (isset($security['requestedAuthnContextComparison'])) {
$authnComparison = $security['requestedAuthnContextComparison'];
@@ -114,6 +129,8 @@ REQUESTEDAUTHN;
}
}
+ $spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
+ $acsUrl = htmlspecialchars($spData['assertionConsumerService']['url'], ENT_QUOTES);
$request = <<<AUTHNREQUEST
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
@@ -124,8 +141,8 @@ REQUESTEDAUTHN;
IssueInstant="$issueInstant"
Destination="{$idpData['singleSignOnService']['url']}"
ProtocolBinding="{$spData['assertionConsumerService']['binding']}"
- AssertionConsumerServiceURL="{$spData['assertionConsumerService']['url']}">
- <saml:Issuer>{$spData['entityId']}</saml:Issuer>
+ AssertionConsumerServiceURL="{$acsUrl}">
+ <saml:Issuer>{$spEntityId}</saml:Issuer>
{$nameIdPolicyStr}
{$requestedAuthnStr}
</samlp:AuthnRequest>
@@ -139,6 +156,8 @@ AUTHNREQUEST;
* Returns deflated, base64 encoded, unsigned AuthnRequest.
*
* @param bool|null $deflate Whether or not we should 'gzdeflate' the request body before we return it.
+ *
+ * @return string
*/
public function getRequest($deflate = null)
{
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Constants.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Constants.php
index dd702fa3..21261fb2 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Constants.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Constants.php
@@ -1,11 +1,26 @@
<?php
-
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
/**
* Constants of OneLogin PHP Toolkit
*
* Defines all required constants
*/
-class OneLogin_Saml2_Constants
+class Constants
{
// Value added to the current time in time condition validations
const ALLOWED_CLOCK_DRIFT = 180; // 3 min in seconds
diff --git a/3rdparty/vendor/onelogin/php-saml/src/Saml2/Error.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Error.php
new file mode 100644
index 00000000..211acf48
--- /dev/null
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Error.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use Exception;
+
+/**
+ * Error class of OneLogin PHP Toolkit
+ *
+ * Defines the Error class
+ */
+class Error extends Exception
+{
+ // Errors
+ const SETTINGS_FILE_NOT_FOUND = 0;
+ const SETTINGS_INVALID_SYNTAX = 1;
+ const SETTINGS_INVALID = 2;
+ const METADATA_SP_INVALID = 3;
+ const SP_CERTS_NOT_FOUND = 4;
+ // SP_CERTS_NOT_FOUND is deprecated, use CERT_NOT_FOUND instead
+ const CERT_NOT_FOUND = 4;
+ const REDIRECT_INVALID_URL = 5;
+ const PUBLIC_CERT_FILE_NOT_FOUND = 6;
+ const PRIVATE_KEY_FILE_NOT_FOUND = 7;
+ const SAML_RESPONSE_NOT_FOUND = 8;
+ const SAML_LOGOUTMESSAGE_NOT_FOUND = 9;
+ const SAML_LOGOUTREQUEST_INVALID = 10;
+ const SAML_LOGOUTRESPONSE_INVALID = 11;
+ const SAML_SINGLE_LOGOUT_NOT_SUPPORTED = 12;
+ const PRIVATE_KEY_NOT_FOUND = 13;
+ const UNSUPPORTED_SETTINGS_OBJECT = 14;
+
+ /**
+ * Constructor
+ *
+ * @param string $msg Describes the error.
+ * @param int $code The code error (defined in the error class).
+ * @param array|null $args Arguments used in the message that describes the error.
+ */
+ public function __construct($msg, $code = 0, $args = array())
+ {
+ assert(is_string($msg));
+ assert(is_int($code));
+
+ if (!isset($args)) {
+ $args = array();
+ }
+ $params = array_merge(array($msg), $args);
+ $message = call_user_func_array('sprintf', $params);
+
+ parent::__construct($message, $code);
+ }
+}
diff --git a/3rdparty/vendor/onelogin/php-saml/src/Saml2/IdPMetadataParser.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/IdPMetadataParser.php
new file mode 100644
index 00000000..e305125b
--- /dev/null
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/IdPMetadataParser.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use DOMDocument;
+use Exception;
+
+/**
+ * IdP Metadata Parser of OneLogin PHP Toolkit
+ */
+class IdPMetadataParser
+{
+ /**
+ * Get IdP Metadata Info from URL
+ *
+ * @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
+ * metadata contains more than one
+ * IDPSSODescriptor, the first is returned
+ * @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
+ * @param string $desiredSSOBinding Parse specific binding SSO endpoint
+ * @param string $desiredSLOBinding Parse specific binding SLO endpoint
+ *
+ * @return array metadata info in php-saml settings format
+ */
+ public static function parseRemoteXML($url, $entityId = null, $desiredNameIdFormat = null, $desiredSSOBinding = Constants::BINDING_HTTP_REDIRECT, $desiredSLOBinding = Constants::BINDING_HTTP_REDIRECT)
+ {
+ $metadataInfo = array();
+
+ try {
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($ch, CURLOPT_FAILONERROR, 1);
+
+ $xml = curl_exec($ch);
+ if ($xml !== false) {
+ $metadataInfo = self::parseXML($xml, $entityId, $desiredNameIdFormat, $desiredSSOBinding, $desiredSLOBinding);
+ } else {
+ throw new Exception(curl_error($ch), curl_errno($ch));
+ }
+ } catch (Exception $e) {
+ }
+ return $metadataInfo;
+ }
+
+ /**
+ * Get IdP Metadata Info from File
+ *
+ * @param string $filepath File path
+ * @param string $entityId Entity Id of the desired IdP, if no
+ * entity Id is provided and the XML
+ * metadata contains more than one
+ * IDPSSODescriptor, the first is returned
+ * @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
+ * @param string $desiredSSOBinding Parse specific binding SSO endpoint
+ * @param string $desiredSLOBinding Parse specific binding SLO endpoint
+ *
+ * @return array metadata info in php-saml settings format
+ */
+ public static function parseFileXML($filepath, $entityId = null, $desiredNameIdFormat = null, $desiredSSOBinding = Constants::BINDING_HTTP_REDIRECT, $desiredSLOBinding = Constants::BINDING_HTTP_REDIRECT)
+ {
+ $metadataInfo = array();
+
+ try {
+ if (file_exists($filepath)) {
+ $data = file_get_contents($filepath);
+ $metadataInfo = self::parseXML($data, $entityId, $desiredNameIdFormat, $desiredSSOBinding, $desiredSLOBinding);
+ }
+ } catch (Exception $e) {
+ }
+ return $metadataInfo;
+ }
+
+ /**
+ * Get IdP Metadata Info from URL
+ *
+ * @param string $xml XML that contains IdP metadata
+ * @param string $entityId Entity Id of the desired IdP, if no
+ * entity Id is provided and the XML
+ * metadata contains more than one
+ * IDPSSODescriptor, the first is returned
+ * @param string $desiredNameIdFormat If available on IdP metadata, use that nameIdFormat
+ * @param string $desiredSSOBinding Parse specific binding SSO endpoint
+ * @param string $desiredSLOBinding Parse specific binding SLO endpoint
+ *
+ * @return array metadata info in php-saml settings format
+ *
+ * @throws Exception
+ */
+ public static function parseXML($xml, $entityId = null, $desiredNameIdFormat = null, $desiredSSOBinding = Constants::BINDING_HTTP_REDIRECT, $desiredSLOBinding = Constants::BINDING_HTTP_REDIRECT)
+ {
+ $metadataInfo = array();
+
+ $dom = new DOMDocument();
+ $dom->preserveWhiteSpace = false;
+ $dom->formatOutput = true;
+ try {
+ $dom = Utils::loadXML($dom, $xml);
+ if (!$dom) {
+ throw new Exception('Error parsing metadata');
+ }
+
+ $customIdPStr = '';
+ if (!empty($entityId)) {
+ $customIdPStr = '[@entityID="' . $entityId . '"]';
+ }
+ $idpDescryptorXPath = '//md:EntityDescriptor' . $customIdPStr . '/md:IDPSSODescriptor';
+
+ $idpDescriptorNodes = Utils::query($dom, $idpDescryptorXPath);
+
+ if (isset($idpDescriptorNodes) && $idpDescriptorNodes->length > 0) {
+ $metadataInfo['idp'] = array();
+
+ $idpDescriptor = $idpDescriptorNodes->item(0);
+
+ if (empty($entityId) && $idpDescriptor->parentNode->hasAttribute('entityID')) {
+ $entityId = $idpDescriptor->parentNode->getAttribute('entityID');
+ }
+
+ if (!empty($entityId)) {
+ $metadataInfo['idp']['entityId'] = $entityId;
+ }
+
+ $ssoNodes = Utils::query($dom, './md:SingleSignOnService[@Binding="'.$desiredSSOBinding.'"]', $idpDescriptor);
+ if ($ssoNodes->length < 1) {
+ $ssoNodes = Utils::query($dom, './md:SingleSignOnService', $idpDescriptor);
+ }
+ if ($ssoNodes->length > 0) {
+ $metadataInfo['idp']['singleSignOnService'] = array(
+ 'url' => $ssoNodes->item(0)->getAttribute('Location'),
+ 'binding' => $ssoNodes->item(0)->getAttribute('Binding')
+ );
+ }
+
+ $sloNodes = Utils::query($dom, './md:SingleLogoutService[@Binding="'.$desiredSLOBinding.'"]', $idpDescriptor);
+ if ($sloNodes->length < 1) {
+ $sloNodes = Utils::query($dom, './md:SingleLogoutService', $idpDescriptor);
+ }
+ if ($sloNodes->length > 0) {
+ $metadataInfo['idp']['singleLogoutService'] = array(
+ 'url' => $sloNodes->item(0)->getAttribute('Location'),
+ 'binding' => $sloNodes->item(0)->getAttribute('Binding')
+ );
+ }
+
+ $keyDescriptorCertSigningNodes = Utils::query($dom, './md:KeyDescriptor[not(contains(@use, "encryption"))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate', $idpDescriptor);
+
+ $keyDescriptorCertEncryptionNodes = Utils::query($dom, './md:KeyDescriptor[not(contains(@use, "signing"))]/ds:KeyInfo/ds:X509Data/ds:X509Certificate', $idpDescriptor);
+
+ if (!empty($keyDescriptorCertSigningNodes) || !empty($keyDescriptorCertEncryptionNodes)) {
+ $metadataInfo['idp']['x509certMulti'] = array();
+ if (!empty($keyDescriptorCertSigningNodes)) {
+ $idpInfo['x509certMulti']['signing'] = array();
+ foreach ($keyDescriptorCertSigningNodes as $keyDescriptorCertSigningNode) {
+ $metadataInfo['idp']['x509certMulti']['signing'][] = Utils::formatCert($keyDescriptorCertSigningNode->nodeValue, false);
+ }
+ }
+ if (!empty($keyDescriptorCertEncryptionNodes)) {
+ $idpInfo['x509certMulti']['encryption'] = array();
+ foreach ($keyDescriptorCertEncryptionNodes as $keyDescriptorCertEncryptionNode) {
+ $metadataInfo['idp']['x509certMulti']['encryption'][] = Utils::formatCert($keyDescriptorCertEncryptionNode->nodeValue, false);
+ }
+ }
+
+ $idpCertdata = $metadataInfo['idp']['x509certMulti'];
+ if ((count($idpCertdata) == 1 and
+ ((isset($idpCertdata['signing']) and count($idpCertdata['signing']) == 1) or (isset($idpCertdata['encryption']) and count($idpCertdata['encryption']) == 1))) or
+ ((isset($idpCertdata['signing']) && count($idpCertdata['signing']) == 1) && isset($idpCertdata['encryption']) && count($idpCertdata['encryption']) == 1 && strcmp($idpCertdata['signing'][0], $idpCertdata['encryption'][0]) == 0)) {
+ if (isset($metadataInfo['idp']['x509certMulti']['signing'][0])) {
+ $metadataInfo['idp']['x509cert'] = $metadataInfo['idp']['x509certMulti']['signing'][0];
+ } else {
+ $metadataInfo['idp']['x509cert'] = $metadataInfo['idp']['x509certMulti']['encryption'][0];
+ }
+ unset($metadataInfo['idp']['x509certMulti']);
+ }
+ }
+
+ $nameIdFormatNodes = Utils::query($dom, './md:NameIDFormat', $idpDescriptor);
+ if ($nameIdFormatNodes->length > 0) {
+ $metadataInfo['sp']['NameIDFormat'] = $nameIdFormatNodes->item(0)->nodeValue;
+ if (!empty($desiredNameIdFormat)) {
+ foreach ($nameIdFormatNodes as $nameIdFormatNode) {
+ if (strcmp($nameIdFormatNode->nodeValue, $desiredNameIdFormat) == 0) {
+ $metadataInfo['sp']['NameIDFormat'] = $nameIdFormatNode->nodeValue;
+ break;
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception $e) {
+ throw new Exception('Error parsing metadata. '.$e->getMessage());
+ }
+
+ return $metadataInfo;
+ }
+
+ /**
+ * Inject metadata info into php-saml settings array
+ *
+ * @param array $settings php-saml settings array
+ * @param array $metadataInfo array metadata info
+ *
+ * @return array settings
+ */
+ public static function injectIntoSettings($settings, $metadataInfo)
+ {
+ if (isset($metadataInfo['idp']) && isset($settings['idp'])) {
+ if (isset($metadataInfo['idp']['x509certMulti']) && !empty($metadataInfo['idp']['x509certMulti']) && isset($settings['idp']['x509cert'])) {
+ unset($settings['idp']['x509cert']);
+ }
+
+ if (isset($metadataInfo['idp']['x509cert']) && !empty($metadataInfo['idp']['x509cert']) && isset($settings['idp']['x509certMulti'])) {
+ unset($settings['idp']['x509certMulti']);
+ }
+ }
+
+ return array_replace_recursive($settings, $metadataInfo);
+ }
+}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutRequest.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php
index 79c04ded..2e9258c8 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutRequest.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutRequest.php
@@ -1,51 +1,76 @@
<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+
+use DOMDocument;
+use Exception;
/**
* SAML 2 Logout Request
- *
*/
-class OneLogin_Saml2_LogoutRequest
+class LogoutRequest
{
/**
- * Contains the ID of the Logout Request
- * @var string
- */
+ * Contains the ID of the Logout Request
+ *
+ * @var string
+ */
public $id;
/**
* Object that represents the setting info
- * @var OneLogin_Saml2_Settings
+ *
+ * @var Settings
*/
protected $_settings;
/**
* SAML Logout Request
+ *
* @var string
*/
protected $_logoutRequest;
/**
- * After execute a validation process, this var contains the cause
- * @var string
- */
+ * After execute a validation process, this var contains the cause
+ *
+ * @var Exception
+ */
private $_error;
/**
* Constructs the Logout Request object.
*
- * @param OneLogin_Saml2_Settings $settings Settings
- * @param string|null $request A UUEncoded Logout Request.
- * @param string|null $nameId The NameID that will be set in the LogoutRequest.
- * @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
- * @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
+ * @param Settings $settings Settings
+ * @param string|null $request A UUEncoded Logout Request.
+ * @param string|null $nameId The NameID that will be set in the LogoutRequest.
+ * @param string|null $sessionIndex The SessionIndex (taken from the SAML Response in the SSO process).
+ * @param string|null $nameIdFormat The NameID Format will be set in the LogoutRequest.
+ * @param string|null $nameIdNameQualifier The NameID NameQualifier will be set in the LogoutRequest.
+ * @param string|null $nameIdSPNameQualifier The NameID SP NameQualifier will be set in the LogoutRequest.
*/
- public function __construct(OneLogin_Saml2_Settings $settings, $request = null, $nameId = null, $sessionIndex = null, $nameIdFormat = null)
+ public function __construct(\OneLogin\Saml2\Settings $settings, $request = null, $nameId = null, $sessionIndex = null, $nameIdFormat = null, $nameIdNameQualifier = null, $nameIdSPNameQualifier = null)
{
$this->_settings = $settings;
$baseURL = $this->_settings->getBaseURL();
if (!empty($baseURL)) {
- OneLogin_Saml2_Utils::setBaseURL($baseURL);
+ Utils::setBaseURL($baseURL);
}
if (!isset($request) || empty($request)) {
@@ -53,37 +78,56 @@ class OneLogin_Saml2_LogoutRequest
$idpData = $this->_settings->getIdPData();
$security = $this->_settings->getSecurityData();
- $id = OneLogin_Saml2_Utils::generateUniqueID();
+ $id = Utils::generateUniqueID();
$this->id = $id;
- $nameIdValue = OneLogin_Saml2_Utils::generateUniqueID();
- $issueInstant = OneLogin_Saml2_Utils::parseTime2SAML(time());
+ $issueInstant = Utils::parseTime2SAML(time());
$cert = null;
if (isset($security['nameIdEncrypted']) && $security['nameIdEncrypted']) {
- $cert = $idpData['x509cert'];
+ $existsMultiX509Enc = isset($idpData['x509certMulti']) && isset($idpData['x509certMulti']['encryption']) && !empty($idpData['x509certMulti']['encryption']);
+
+ if ($existsMultiX509Enc) {
+ $cert = $idpData['x509certMulti']['encryption'][0];
+ } else {
+ $cert = $idpData['x509cert'];
+ }
}
if (!empty($nameId)) {
- if (empty($nameIdFormat)) {
+ if (empty($nameIdFormat)
+ && $spData['NameIDFormat'] != Constants::NAMEID_UNSPECIFIED) {
$nameIdFormat = $spData['NameIDFormat'];
}
- $spNameQualifier = null;
} else {
$nameId = $idpData['entityId'];
- $nameIdFormat = OneLogin_Saml2_Constants::NAMEID_ENTITY;
- $spNameQualifier = $spData['entityId'];
+ $nameIdFormat = Constants::NAMEID_ENTITY;
+ }
+
+ /* From saml-core-2.0-os 8.3.6, when the entity Format is used:
+ "The NameQualifier, SPNameQualifier, and SPProvidedID attributes MUST be omitted.
+ */
+ if (!empty($nameIdFormat) && $nameIdFormat == Constants::NAMEID_ENTITY) {
+ $nameIdNameQualifier = null;
+ $nameIdSPNameQualifier = null;
+ }
+
+ // NameID Format UNSPECIFIED omitted
+ if (!empty($nameIdFormat) && $nameIdFormat == Constants::NAMEID_UNSPECIFIED) {
+ $nameIdFormat = null;
}
- $nameIdObj = OneLogin_Saml2_Utils::generateNameId(
+ $nameIdObj = Utils::generateNameId(
$nameId,
- $spNameQualifier,
+ $nameIdSPNameQualifier,
$nameIdFormat,
- $cert
+ $cert,
+ $nameIdNameQualifier
);
$sessionIndexStr = isset($sessionIndex) ? "<samlp:SessionIndex>{$sessionIndex}</samlp:SessionIndex>" : "";
+ $spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
$logoutRequest = <<<LOGOUTREQUEST
<samlp:LogoutRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
@@ -92,7 +136,7 @@ class OneLogin_Saml2_LogoutRequest
Version="2.0"
IssueInstant="{$issueInstant}"
Destination="{$idpData['singleLogoutService']['url']}">
- <saml:Issuer>{$spData['entityId']}</saml:Issuer>
+ <saml:Issuer>{$spEntityId}</saml:Issuer>
{$nameIdObj}
{$sessionIndexStr}
</samlp:LogoutRequest>
@@ -106,12 +150,11 @@ LOGOUTREQUEST;
} else {
$logoutRequest = $decoded;
}
- $this->id = self::getID($logoutRequest);
+ $this->id = static::getID($logoutRequest);
}
$this->_logoutRequest = $logoutRequest;
}
-
/**
* Returns the Logout Request defated, base64encoded, unsigned
*
@@ -140,6 +183,8 @@ LOGOUTREQUEST;
* @param string|DOMDocument $request Logout Request Message
*
* @return string ID
+ *
+ * @throws OneLogin_Saml2_Error
*/
public static function getID($request)
{
@@ -147,7 +192,15 @@ LOGOUTREQUEST;
$dom = $request;
} else {
$dom = new DOMDocument();
- $dom = OneLogin_Saml2_Utils::loadXML($dom, $request);
+ $dom = Utils::loadXML($dom, $request);
+ }
+
+
+ if (false === $dom) {
+ throw new Error(
+ "LogoutRequest could not be processed",
+ Error::SAML_LOGOUTREQUEST_INVALID
+ );
}
$id = $dom->documentElement->getAttribute('ID');
@@ -162,7 +215,9 @@ LOGOUTREQUEST;
*
* @return array Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
*
+ * @throws Error
* @throws Exception
+ * @throws ValidationError
*/
public static function getNameIdData($request, $key = null)
{
@@ -170,38 +225,38 @@ LOGOUTREQUEST;
$dom = $request;
} else {
$dom = new DOMDocument();
- $dom = OneLogin_Saml2_Utils::loadXML($dom, $request);
+ $dom = Utils::loadXML($dom, $request);
}
- $encryptedEntries = OneLogin_Saml2_Utils::query($dom, '/samlp:LogoutRequest/saml:EncryptedID');
+ $encryptedEntries = Utils::query($dom, '/samlp:LogoutRequest/saml:EncryptedID');
if ($encryptedEntries->length == 1) {
$encryptedDataNodes = $encryptedEntries->item(0)->getElementsByTagName('EncryptedData');
$encryptedData = $encryptedDataNodes->item(0);
if (empty($key)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
"Private Key is required in order to decrypt the NameID, check settings",
- OneLogin_Saml2_Error::PRIVATE_KEY_NOT_FOUND
+ Error::PRIVATE_KEY_NOT_FOUND
);
}
$seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type'=>'private'));
$seckey->loadKey($key);
- $nameId = OneLogin_Saml2_Utils::decryptElement($encryptedData, $seckey);
+ $nameId = Utils::decryptElement($encryptedData, $seckey);
} else {
- $entries = OneLogin_Saml2_Utils::query($dom, '/samlp:LogoutRequest/saml:NameID');
+ $entries = Utils::query($dom, '/samlp:LogoutRequest/saml:NameID');
if ($entries->length == 1) {
$nameId = $entries->item(0);
}
}
if (!isset($nameId)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"NameID not found in the Logout Request",
- OneLogin_Saml2_ValidationError::NO_NAMEID
+ ValidationError::NO_NAMEID
);
}
@@ -223,6 +278,10 @@ LOGOUTREQUEST;
* @param string|null $key The SP key
*
* @return string Name ID Value
+ *
+ * @throws Error
+ * @throws Exception
+ * @throws ValidationError
*/
public static function getNameId($request, $key = null)
{
@@ -236,6 +295,8 @@ LOGOUTREQUEST;
* @param string|DOMDocument $request Logout Request Message
*
* @return string|null $issuer The Issuer
+ *
+ * @throws Exception
*/
public static function getIssuer($request)
{
@@ -243,11 +304,11 @@ LOGOUTREQUEST;
$dom = $request;
} else {
$dom = new DOMDocument();
- $dom = OneLogin_Saml2_Utils::loadXML($dom, $request);
+ $dom = Utils::loadXML($dom, $request);
}
$issuer = null;
- $issuerNodes = OneLogin_Saml2_Utils::query($dom, '/samlp:LogoutRequest/saml:Issuer');
+ $issuerNodes = Utils::query($dom, '/samlp:LogoutRequest/saml:Issuer');
if ($issuerNodes->length == 1) {
$issuer = $issuerNodes->item(0)->textContent;
}
@@ -263,6 +324,8 @@ LOGOUTREQUEST;
* @param string|DOMDocument $request Logout Request Message
*
* @return array The SessionIndex value
+ *
+ * @throws Exception
*/
public static function getSessionIndexes($request)
{
@@ -270,11 +333,11 @@ LOGOUTREQUEST;
$dom = $request;
} else {
$dom = new DOMDocument();
- $dom = OneLogin_Saml2_Utils::loadXML($dom, $request);
+ $dom = Utils::loadXML($dom, $request);
}
$sessionIndexes = array();
- $sessionIndexNodes = OneLogin_Saml2_Utils::query($dom, '/samlp:LogoutRequest/samlp:SessionIndex');
+ $sessionIndexNodes = Utils::query($dom, '/samlp:LogoutRequest/samlp:SessionIndex');
foreach ($sessionIndexNodes as $sessionIndexNode) {
$sessionIndexes[] = $sessionIndexNode->textContent;
}
@@ -284,14 +347,19 @@ LOGOUTREQUEST;
/**
* Checks if the Logout Request recieved is valid.
*
+ * @param bool $retrieveParametersFromServer True if we want to use parameters from $_SERVER to validate the signature
+ *
* @return bool If the Logout Request is or not valid
+ *
+ * @throws Exception
+ * @throws ValidationError
*/
public function isValid($retrieveParametersFromServer = false)
{
$this->_error = null;
try {
$dom = new DOMDocument();
- $dom = OneLogin_Saml2_Utils::loadXML($dom, $this->_logoutRequest);
+ $dom = Utils::loadXML($dom, $this->_logoutRequest);
$idpData = $this->_settings->getIdPData();
$idPEntityId = $idpData['entityId'];
@@ -300,24 +368,24 @@ LOGOUTREQUEST;
$security = $this->_settings->getSecurityData();
if ($security['wantXMLValidation']) {
- $res = OneLogin_Saml2_Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
+ $res = Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
if (!$res instanceof DOMDocument) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd",
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
}
- $currentURL = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
+ $currentURL = Utils::getSelfRoutedURLNoQuery();
// Check NotOnOrAfter
if ($dom->documentElement->hasAttribute('NotOnOrAfter')) {
- $na = OneLogin_Saml2_Utils::parseSAML2Time($dom->documentElement->getAttribute('NotOnOrAfter'));
+ $na = Utils::parseSAML2Time($dom->documentElement->getAttribute('NotOnOrAfter'));
if ($na <= time()) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Could not validate timestamp: expired. Check system clock.",
- OneLogin_Saml2_ValidationError::RESPONSE_EXPIRED
+ ValidationError::RESPONSE_EXPIRED
);
}
}
@@ -325,109 +393,79 @@ LOGOUTREQUEST;
// Check destination
if ($dom->documentElement->hasAttribute('Destination')) {
$destination = $dom->documentElement->getAttribute('Destination');
- if (!empty($destination)) {
- if (strpos($destination, $currentURL) === false) {
- throw new OneLogin_Saml2_ValidationError(
- "The LogoutRequest was received at $currentURL instead of $destination",
- OneLogin_Saml2_ValidationError::WRONG_DESTINATION
- );
- }
+ if (!empty($destination) && strpos($destination, $currentURL) === false) {
+ throw new ValidationError(
+ "The LogoutRequest was received at $currentURL instead of $destination",
+ ValidationError::WRONG_DESTINATION
+ );
}
}
- $nameId = $this->getNameId($dom, $this->_settings->getSPkey());
+ $nameId = static::getNameId($dom, $this->_settings->getSPkey());
// Check issuer
- $issuer = $this->getIssuer($dom);
+ $issuer = static::getIssuer($dom);
if (!empty($issuer) && $issuer != $idPEntityId) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid issuer in the Logout Request",
- OneLogin_Saml2_ValidationError::WRONG_ISSUER
+ ValidationError::WRONG_ISSUER
);
}
- if ($security['wantMessagesSigned']) {
- if (!isset($_GET['Signature'])) {
- throw new OneLogin_Saml2_ValidationError(
- "The Message of the Logout Request is not signed and the SP require it",
- OneLogin_Saml2_ValidationError::NO_SIGNED_MESSAGE
- );
- }
+ if ($security['wantMessagesSigned'] && !isset($_GET['Signature'])) {
+ throw new ValidationError(
+ "The Message of the Logout Request is not signed and the SP require it",
+ ValidationError::NO_SIGNED_MESSAGE
+ );
}
}
if (isset($_GET['Signature'])) {
- if (!isset($_GET['SigAlg'])) {
- $signAlg = XMLSecurityKey::RSA_SHA1;
- } else {
- $signAlg = $_GET['SigAlg'];
- }
-
- if ($retrieveParametersFromServer) {
- $signedQuery = 'SAMLRequest='.OneLogin_Saml2_Utils::extractOriginalQueryParam('SAMLRequest');
- if (isset($_GET['RelayState'])) {
- $signedQuery .= '&RelayState='.OneLogin_Saml2_Utils::extractOriginalQueryParam('RelayState');
- }
- $signedQuery .= '&SigAlg='.OneLogin_Saml2_Utils::extractOriginalQueryParam('SigAlg');
- } else {
- $signedQuery = 'SAMLRequest='.urlencode($_GET['SAMLRequest']);
- if (isset($_GET['RelayState'])) {
- $signedQuery .= '&RelayState='.urlencode($_GET['RelayState']);
- }
- $signedQuery .= '&SigAlg='.urlencode($signAlg);
- }
-
- if (!isset($idpData['x509cert']) || empty($idpData['x509cert'])) {
- throw new OneLogin_Saml2_Error(
- "In order to validate the sign on the Logout Request, the x509cert of the IdP is required",
- OneLogin_Saml2_Error::CERT_NOT_FOUND
- );
- }
- $cert = $idpData['x509cert'];
-
- $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
- $objKey->loadKey($cert, false, true);
-
- if ($signAlg != XMLSecurityKey::RSA_SHA1) {
- try {
- $objKey = OneLogin_Saml2_Utils::castKey($objKey, $signAlg, 'public');
- } catch (Exception $e) {
- throw new OneLogin_Saml2_ValidationError(
- "Invalid signAlg in the recieved Logout Request",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
- );
- }
- }
-
- if ($objKey->verifySignature($signedQuery, base64_decode($_GET['Signature'])) !== 1) {
- throw new OneLogin_Saml2_ValidationError(
+ $signatureValid = Utils::validateBinarySign("SAMLRequest", $_GET, $idpData, $retrieveParametersFromServer);
+ if (!$signatureValid) {
+ throw new ValidationError(
"Signature validation failed. Logout Request rejected",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
+ ValidationError::INVALID_SIGNATURE
);
}
}
return true;
} catch (Exception $e) {
- $this->_error = $e->getMessage();
+ $this->_error = $e;
$debug = $this->_settings->isDebugActive();
if ($debug) {
- echo $this->_error;
+ echo htmlentities($this->_error->getMessage());
}
return false;
}
}
- /* After execute a validation process, if fails this method returns the cause
+ /**
+ * After execute a validation process, if fails this method returns the Exception of the cause
*
- * @return string Cause
+ * @return Exception Cause
*/
- public function getError()
+ public function getErrorException()
{
return $this->_error;
}
/**
+ * After execute a validation process, if fails this method returns the cause
+ *
+ * @return null|string Error reason
+ */
+ public function getError()
+ {
+ $errorMsg = null;
+ if (isset($this->_error)) {
+ $errorMsg = htmlentities($this->_error->getMessage());
+ }
+ return $errorMsg;
+ }
+
+ /**
* Returns the XML that will be sent as part of the request
* or that was received at the SP
*
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutResponse.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutResponse.php
index 366f8367..2f376bb5 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/LogoutResponse.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/LogoutResponse.php
@@ -1,55 +1,82 @@
<?php
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use DOMDocument;
+use DOMNodeList;
+use Exception;
/**
* SAML 2 Logout Response
- *
*/
-class OneLogin_Saml2_LogoutResponse
+class LogoutResponse
{
/**
- * Contains the ID of the Logout Response
- * @var string
- */
+ * Contains the ID of the Logout Response
+ *
+ * @var string
+ */
public $id;
/**
* Object that represents the setting info
- * @var OneLogin_Saml2_Settings
+ *
+ * @var Settings
*/
protected $_settings;
/**
* The decoded, unprocessed XML response provided to the constructor.
- * @var string
+ *
+ * @var string|null
*/
protected $_logoutResponse;
/**
* A DOMDocument class loaded from the SAML LogoutResponse.
- * @var DomDocument
+ *
+ * @var DOMDocument
*/
public $document;
/**
- * After execute a validation process, if it fails, this var contains the cause
- * @var string
- */
+ * After execute a validation process, if it fails, this var contains the cause
+ *
+ * @var Exception|null
+ */
private $_error;
/**
* Constructs a Logout Response object (Initialize params from settings and if provided
* load the Logout Response.
*
- * @param OneLogin_Saml2_Settings $settings Settings.
+ * @param Settings $settings Settings.
* @param string|null $response An UUEncoded SAML Logout response from the IdP.
+ *
+ * @throws Error
+ * @throws Exception
+ *
*/
- public function __construct(OneLogin_Saml2_Settings $settings, $response = null)
+ public function __construct(\OneLogin\Saml2\Settings $settings, $response = null)
{
$this->_settings = $settings;
$baseURL = $this->_settings->getBaseURL();
if (!empty($baseURL)) {
- OneLogin_Saml2_Utils::setBaseURL($baseURL);
+ Utils::setBaseURL($baseURL);
}
if ($response) {
@@ -61,7 +88,14 @@ class OneLogin_Saml2_LogoutResponse
$this->_logoutResponse = $decoded;
}
$this->document = new DOMDocument();
- $this->document = OneLogin_Saml2_Utils::loadXML($this->document, $this->_logoutResponse);
+ $this->document = Utils::loadXML($this->document, $this->_logoutResponse);
+
+ if (false === $this->document) {
+ throw new Error(
+ "LogoutResponse could not be processed",
+ Error::SAML_LOGOUTRESPONSE_INVALID
+ );
+ }
if ($this->document->documentElement->hasAttribute('ID')) {
$this->id = $this->document->documentElement->getAttribute('ID');
@@ -87,7 +121,7 @@ class OneLogin_Saml2_LogoutResponse
/**
* Gets the Status of the Logout Response.
*
- * @return string The Status
+ * @return string|null The Status
*/
public function getStatus()
{
@@ -102,12 +136,12 @@ class OneLogin_Saml2_LogoutResponse
/**
* Determines if the SAML LogoutResponse is valid
*
- * @param string|null $requestId The ID of the LogoutRequest sent by this SP to the IdP
- * @param bool $retrieveParametersFromServer
+ * @param string|null $requestId The ID of the LogoutRequest sent by this SP to the IdP
+ * @param bool $retrieveParametersFromServer True if we want to use parameters from $_SERVER to validate the signature
*
* @return bool Returns if the SAML LogoutResponse is or not valid
- *
- * @throws Exception
+ *
+ * @throws ValidationError
*/
public function isValid($requestId = null, $retrieveParametersFromServer = false)
{
@@ -120,11 +154,11 @@ class OneLogin_Saml2_LogoutResponse
$security = $this->_settings->getSecurityData();
if ($security['wantXMLValidation']) {
- $res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
+ $res = Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
if (!$res instanceof DOMDocument) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd",
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
}
@@ -133,9 +167,9 @@ class OneLogin_Saml2_LogoutResponse
if (isset($requestId) && $this->document->documentElement->hasAttribute('InResponseTo')) {
$inResponseTo = $this->document->documentElement->getAttribute('InResponseTo');
if ($requestId != $inResponseTo) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The InResponseTo of the Logout Response: $inResponseTo, does not match the ID of the Logout request sent by the SP: $requestId",
- OneLogin_Saml2_ValidationError::WRONG_INRESPONSETO
+ ValidationError::WRONG_INRESPONSETO
);
}
}
@@ -143,93 +177,48 @@ class OneLogin_Saml2_LogoutResponse
// Check issuer
$issuer = $this->getIssuer();
if (!empty($issuer) && $issuer != $idPEntityId) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid issuer in the Logout Response",
- OneLogin_Saml2_ValidationError::WRONG_ISSUER
+ ValidationError::WRONG_ISSUER
);
}
- $currentURL = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
+ $currentURL = Utils::getSelfRoutedURLNoQuery();
// Check destination
if ($this->document->documentElement->hasAttribute('Destination')) {
$destination = $this->document->documentElement->getAttribute('Destination');
- if (!empty($destination)) {
- if (strpos($destination, $currentURL) === false) {
- throw new OneLogin_Saml2_ValidationError(
- "The LogoutResponse was received at $currentURL instead of $destination",
- OneLogin_Saml2_ValidationError::WRONG_DESTINATION
- );
- }
- }
- }
-
- if ($security['wantMessagesSigned']) {
- if (!isset($_GET['Signature'])) {
- throw new OneLogin_Saml2_ValidationError(
- "The Message of the Logout Response is not signed and the SP requires it",
- OneLogin_Saml2_ValidationError::NO_SIGNED_MESSAGE
+ if (!empty($destination) && strpos($destination, $currentURL) === false) {
+ throw new ValidationError(
+ "The LogoutResponse was received at $currentURL instead of $destination",
+ ValidationError::WRONG_DESTINATION
);
}
}
- }
-
- if (isset($_GET['Signature'])) {
- if (!isset($_GET['SigAlg'])) {
- $signAlg = XMLSecurityKey::RSA_SHA1;
- } else {
- $signAlg = $_GET['SigAlg'];
- }
- if ($retrieveParametersFromServer) {
- $signedQuery = 'SAMLResponse='.OneLogin_Saml2_Utils::extractOriginalQueryParam('SAMLResponse');
- if (isset($_GET['RelayState'])) {
- $signedQuery .= '&RelayState='.OneLogin_Saml2_Utils::extractOriginalQueryParam('RelayState');
- }
- $signedQuery .= '&SigAlg='.OneLogin_Saml2_Utils::extractOriginalQueryParam('SigAlg');
- } else {
- $signedQuery = 'SAMLResponse='.urlencode($_GET['SAMLResponse']);
- if (isset($_GET['RelayState'])) {
- $signedQuery .= '&RelayState='.urlencode($_GET['RelayState']);
- }
- $signedQuery .= '&SigAlg='.urlencode($signAlg);
- }
-
- if (!isset($idpData['x509cert']) || empty($idpData['x509cert'])) {
- throw new OneLogin_Saml2_Error(
- "In order to validate the sign on the Logout Response, the x509cert of the IdP is required",
- OneLogin_Saml2_Error::CERT_NOT_FOUND
+ if ($security['wantMessagesSigned'] && !isset($_GET['Signature'])) {
+ throw new ValidationError(
+ "The Message of the Logout Response is not signed and the SP requires it",
+ ValidationError::NO_SIGNED_MESSAGE
);
}
- $cert = $idpData['x509cert'];
-
- $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
- $objKey->loadKey($cert, false, true);
-
- if ($signAlg != XMLSecurityKey::RSA_SHA1) {
- try {
- $objKey = OneLogin_Saml2_Utils::castKey($objKey, $signAlg, 'public');
- } catch (Exception $e) {
- throw new OneLogin_Saml2_ValidationError(
- "Invalid signAlg in the recieved Logout Response",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
- );
- }
- }
+ }
- if ($objKey->verifySignature($signedQuery, base64_decode($_GET['Signature'])) !== 1) {
- throw new OneLogin_Saml2_ValidationError(
+ if (isset($_GET['Signature'])) {
+ $signatureValid = Utils::validateBinarySign("SAMLResponse", $_GET, $idpData, $retrieveParametersFromServer);
+ if (!$signatureValid) {
+ throw new ValidationError(
"Signature validation failed. Logout Response rejected",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
+ ValidationError::INVALID_SIGNATURE
);
}
}
return true;
} catch (Exception $e) {
- $this->_error = $e->getMessage();
+ $this->_error = $e;
$debug = $this->_settings->isDebugActive();
if ($debug) {
- echo $this->_error;
+ echo htmlentities($this->_error->getMessage());
}
return false;
}
@@ -238,13 +227,13 @@ class OneLogin_Saml2_LogoutResponse
/**
* Extracts a node from the DOMDocument (Logout Response Menssage)
*
- * @param string $query Xpath Expresion
+ * @param string $query Xpath Expression
*
* @return DOMNodeList The queried node
*/
private function _query($query)
{
- return OneLogin_Saml2_Utils::query($this->document, $query);
+ return Utils::query($this->document, $query);
}
@@ -259,9 +248,10 @@ class OneLogin_Saml2_LogoutResponse
$spData = $this->_settings->getSPData();
$idpData = $this->_settings->getIdPData();
- $this->id = OneLogin_Saml2_Utils::generateUniqueID();
- $issueInstant = OneLogin_Saml2_Utils::parseTime2SAML(time());
+ $this->id = Utils::generateUniqueID();
+ $issueInstant = Utils::parseTime2SAML(time());
+ $spEntityId = htmlspecialchars($spData['entityId'], ENT_QUOTES);
$logoutResponse = <<<LOGOUTRESPONSE
<samlp:LogoutResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
@@ -271,7 +261,7 @@ class OneLogin_Saml2_LogoutResponse
Destination="{$idpData['singleLogoutService']['url']}"
InResponseTo="{$inResponseTo}"
>
- <saml:Issuer>{$spData['entityId']}</saml:Issuer>
+ <saml:Issuer>{$spEntityId}</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
@@ -289,30 +279,45 @@ LOGOUTRESPONSE;
*/
public function getResponse($deflate = null)
{
- $subject = $this->_logoutResponse;
+ $logoutResponse = $this->_logoutResponse;
if (is_null($deflate)) {
$deflate = $this->_settings->shouldCompressResponses();
}
if ($deflate) {
- $subject = gzdeflate($this->_logoutResponse);
+ $logoutResponse = gzdeflate($this->_logoutResponse);
}
- return base64_encode($subject);
+ return base64_encode($logoutResponse);
}
- /* After execute a validation process, if fails this method returns the cause.
+ /**
+ * After execute a validation process, if fails this method returns the cause.
*
- * @return string Cause
+ * @return Exception|null Cause
*/
- public function getError()
+ public function getErrorException()
{
return $this->_error;
}
- /**
- * @return the ID of the Response
- */
+ /**
+ * After execute a validation process, if fails this method returns the cause
+ *
+ * @return null|string Error reason
+ */
+ public function getError()
+ {
+ $errorMsg = null;
+ if (isset($this->_error)) {
+ $errorMsg = htmlentities($this->_error->getMessage());
+ }
+ return $errorMsg;
+ }
+
+ /**
+ * @return string the ID of the Response
+ */
public function getId()
{
return $this->id;
@@ -322,7 +327,7 @@ LOGOUTRESPONSE;
* Returns the XML that will be sent as part of the response
* or that was received at the SP
*
- * @return string
+ * @return string|null
*/
public function getXML()
{
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Metadata.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Metadata.php
index 56626248..2efd1136 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Metadata.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Metadata.php
@@ -1,11 +1,30 @@
<?php
-
/**
- * Metadata lib of OneLogin PHP Toolkit
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
*
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
*/
-class OneLogin_Saml2_Metadata
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+use RobRichards\XMLSecLibs\XMLSecurityDSig;
+
+use DOMDocument;
+use Exception;
+
+/**
+ * Metadata lib of OneLogin PHP Toolkit
+ */
+class Metadata
{
const TIME_VALID = 172800; // 2 days
const TIME_CACHED = 604800; // 1 week
@@ -16,11 +35,12 @@ class OneLogin_Saml2_Metadata
* @param array $sp The SP data
* @param bool|string $authnsign authnRequestsSigned attribute
* @param bool|string $wsign wantAssertionsSigned attribute
- * @param DateTime|null $validUntil Metadata's valid time
+ * @param int|null $validUntil Metadata's valid time
* @param int|null $cacheDuration Duration of the cache in seconds
* @param array $contacts Contacts info
* @param array $organization Organization ingo
* @param array $attributes
+ *
* @return string SAML Metadata XML
*/
public static function builder($sp, $authnsign = false, $wsign = false, $validUntil = null, $cacheDuration = null, $contacts = array(), $organization = array(), $attributes = array())
@@ -29,7 +49,7 @@ class OneLogin_Saml2_Metadata
if (!isset($validUntil)) {
$validUntil = time() + self::TIME_VALID;
}
- $validUntilTime = gmdate('Y-m-d\TH:i:s\Z', $validUntil);
+ $validUntilTime = Utils::parseTime2SAML($validUntil);
if (!isset($cacheDuration)) {
$cacheDuration = self::TIME_CACHED;
@@ -38,9 +58,10 @@ class OneLogin_Saml2_Metadata
$sls = '';
if (isset($sp['singleLogoutService'])) {
+ $slsUrl = htmlspecialchars($sp['singleLogoutService']['url'], ENT_QUOTES);
$sls = <<<SLS_TEMPLATE
<md:SingleLogoutService Binding="{$sp['singleLogoutService']['binding']}"
- Location="{$sp['singleLogoutService']['url']}" />
+ Location="{$slsUrl}" />
SLS_TEMPLATE;
}
@@ -127,7 +148,7 @@ CONTACT;
$reqAttrAuxStr = '>';
if (is_string($attribute['attributeValue'])) {
$attribute['attributeValue'] = array($attribute['attributeValue']);
- }
+ }
foreach ($attribute['attributeValue'] as $attrValue) {
$reqAttrAuxStr .=<<<ATTRIBUTEVALUE
@@ -149,16 +170,18 @@ ATTRIBUTEVALUE;
METADATA_TEMPLATE;
}
+ $spEntityId = htmlspecialchars($sp['entityId'], ENT_QUOTES);
+ $acsUrl = htmlspecialchars($sp['assertionConsumerService']['url'], ENT_QUOTES);
$metadata = <<<METADATA_TEMPLATE
<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
validUntil="{$validUntilTime}"
cacheDuration="PT{$cacheDuration}S"
- entityID="{$sp['entityId']}">
+ entityID="{$spEntityId}">
<md:SPSSODescriptor AuthnRequestsSigned="{$strAuthnsign}" WantAssertionsSigned="{$strWsign}" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
{$sls} <md:NameIDFormat>{$sp['NameIDFormat']}</md:NameIDFormat>
<md:AssertionConsumerService Binding="{$sp['assertionConsumerService']['binding']}"
- Location="{$sp['assertionConsumerService']['url']}"
+ Location="{$acsUrl}"
index="1" />
{$strAttributeConsumingService}
</md:SPSSODescriptor>{$strOrganization}{$strContacts}
@@ -170,21 +193,23 @@ METADATA_TEMPLATE;
/**
* Signs the metadata with the key/cert provided
*
- * @param string $metadata SAML Metadata XML
- * @param string $key x509 key
- * @param string $cert x509 cert
- * @param string $signAlgorithm Signature algorithm method
- * @param string $digestAlgorithm Digest algorithm method
+ * @param string $metadata SAML Metadata XML
+ * @param string $key x509 key
+ * @param string $cert x509 cert
+ * @param string $signAlgorithm Signature algorithm method
+ * @param string $digestAlgorithm Digest algorithm method
*
* @return string Signed Metadata
+ *
+ * @throws Exception
*/
- public static function signMetadata($metadata, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA1, $digestAlgorithm = XMLSecurityDSig::SHA1)
+ public static function signMetadata($metadata, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA256, $digestAlgorithm = XMLSecurityDSig::SHA256)
{
- return OneLogin_Saml2_Utils::addSign($metadata, $key, $cert, $signAlgorithm, $digestAlgorithm);
+ return Utils::addSign($metadata, $key, $cert, $signAlgorithm, $digestAlgorithm);
}
/**
- * Adds the x509 descriptors (sign/encriptation) to the metadata
+ * Adds the x509 descriptors (sign/encryption) to the metadata
* The same cert will be used for sign/encrypt
*
* @param string $metadata SAML Metadata XML
@@ -192,6 +217,8 @@ METADATA_TEMPLATE;
* @param bool $wantsEncrypted Whether to include the KeyDescriptor for encryption
*
* @return string Metadata with KeyDescriptors
+ *
+ * @throws Exception
*/
public static function addX509KeyDescriptors($metadata, $cert, $wantsEncrypted = true)
{
@@ -199,7 +226,7 @@ METADATA_TEMPLATE;
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
try {
- $xml = OneLogin_Saml2_Utils::loadXML($xml, $metadata);
+ $xml = Utils::loadXML($xml, $metadata);
if (!$xml) {
throw new Exception('Error parsing metadata');
}
@@ -207,16 +234,16 @@ METADATA_TEMPLATE;
throw new Exception('Error parsing metadata. '.$e->getMessage());
}
- $formatedCert = OneLogin_Saml2_Utils::formatCert($cert, false);
- $x509Certificate = $xml->createElementNS(OneLogin_Saml2_Constants::NS_DS, 'X509Certificate', $formatedCert);
+ $formatedCert = Utils::formatCert($cert, false);
+ $x509Certificate = $xml->createElementNS(Constants::NS_DS, 'X509Certificate', $formatedCert);
- $keyData = $xml->createElementNS(OneLogin_Saml2_Constants::NS_DS, 'ds:X509Data');
+ $keyData = $xml->createElementNS(Constants::NS_DS, 'ds:X509Data');
$keyData->appendChild($x509Certificate);
- $keyInfo = $xml->createElementNS(OneLogin_Saml2_Constants::NS_DS, 'ds:KeyInfo');
+ $keyInfo = $xml->createElementNS(Constants::NS_DS, 'ds:KeyInfo');
$keyInfo->appendChild($keyData);
- $keyDescriptor = $xml->createElementNS(OneLogin_Saml2_Constants::NS_MD, "md:KeyDescriptor");
+ $keyDescriptor = $xml->createElementNS(Constants::NS_MD, "md:KeyDescriptor");
$SPSSODescriptor = $xml->getElementsByTagName('SPSSODescriptor')->item(0);
$SPSSODescriptor->insertBefore($keyDescriptor->cloneNode(), $SPSSODescriptor->firstChild);
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Response.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Response.php
index 6c43068e..7ad31b0f 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Response.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Response.php
@@ -1,81 +1,108 @@
<?php
-
/**
- * SAML 2 Authentication Response
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
*
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
*/
-class OneLogin_Saml2_Response
-{
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+use RobRichards\XMLSecLibs\XMLSecEnc;
+
+use DOMDocument;
+use DOMNodeList;
+use DOMXPath;
+use Exception;
+/**
+ * SAML 2 Authentication Response
+ */
+class Response
+{
/**
* Settings
- * @var OneLogin_Saml2_Settings
+ *
+ * @var Settings
*/
protected $_settings;
/**
* The decoded, unprocessed XML response provided to the constructor.
+ *
* @var string
*/
public $response;
/**
* A DOMDocument class loaded from the SAML Response.
- * @var DomDocument
+ *
+ * @var DOMDocument
*/
public $document;
/**
* A DOMDocument class loaded from the SAML Response (Decrypted).
- * @var DomDocument
+ *
+ * @var DOMDocument
*/
public $decryptedDocument;
/**
* The response contains an encrypted assertion.
+ *
* @var bool
*/
public $encrypted = false;
/**
* After validation, if it fail this var has the cause of the problem
- * @var string
+ *
+ * @var Exception|null
*/
private $_error;
/**
* NotOnOrAfter value of a valid SubjectConfirmationData node
*
- * @var DateTime
+ * @var int
*/
private $_validSCDNotOnOrAfter;
/**
* Constructs the SAML Response object.
*
- * @param OneLogin_Saml2_Settings $settings Settings.
- * @param string $response A UUEncoded SAML response from the IdP.
+ * @param Settings $settings Settings.
+ * @param string $response A UUEncoded SAML response from the IdP.
*
* @throws Exception
+ * @throws ValidationError
*/
- public function __construct(OneLogin_Saml2_Settings $settings, $response)
+ public function __construct(\OneLogin\Saml2\Settings $settings, $response)
{
$this->_settings = $settings;
$baseURL = $this->_settings->getBaseURL();
if (!empty($baseURL)) {
- OneLogin_Saml2_Utils::setBaseURL($baseURL);
+ Utils::setBaseURL($baseURL);
}
$this->response = base64_decode($response);
$this->document = new DOMDocument();
- $this->document = OneLogin_Saml2_Utils::loadXML($this->document, $this->response);
+ $this->document = Utils::loadXML($this->document, $this->response);
if (!$this->document) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"SAML Response could not be processed",
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
@@ -84,7 +111,7 @@ class OneLogin_Saml2_Response
if ($encryptedAssertionNodes->length !== 0) {
$this->decryptedDocument = clone $this->document;
$this->encrypted = true;
- $this->decryptedDocument = $this->_decryptAssertion($this->decryptedDocument);
+ $this->decryptedDocument = $this->decryptAssertion($this->decryptedDocument);
}
}
@@ -96,6 +123,7 @@ class OneLogin_Saml2_Response
* @return bool Validate the document
*
* @throws Exception
+ * @throws ValidationError
*/
public function isValid($requestId = null)
{
@@ -103,16 +131,16 @@ class OneLogin_Saml2_Response
try {
// Check SAML version
if ($this->document->documentElement->getAttribute('Version') != '2.0') {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Unsupported SAML version",
- OneLogin_Saml2_ValidationError::UNSUPPORTED_SAML_VERSION
+ ValidationError::UNSUPPORTED_SAML_VERSION
);
}
if (!$this->document->documentElement->hasAttribute('ID')) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Missing ID attribute on SAML Response",
- OneLogin_Saml2_ValidationError::MISSING_ID
+ ValidationError::MISSING_ID
);
}
@@ -120,9 +148,9 @@ class OneLogin_Saml2_Response
$singleAssertion = $this->validateNumAssertions();
if (!$singleAssertion) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"SAML Response must contain 1 assertion",
- OneLogin_Saml2_ValidationError::WRONG_NUMBER_OF_ASSERTIONS
+ ValidationError::WRONG_NUMBER_OF_ASSERTIONS
);
}
@@ -133,8 +161,8 @@ class OneLogin_Saml2_Response
$signedElements = $this->processSignedElements();
- $responseTag = '{'.OneLogin_Saml2_Constants::NS_SAMLP.'}Response';
- $assertionTag = '{'.OneLogin_Saml2_Constants::NS_SAML.'}Assertion';
+ $responseTag = '{'.Constants::NS_SAMLP.'}Response';
+ $assertionTag = '{'.Constants::NS_SAML.'}Assertion';
$hasSignedResponse = in_array($responseTag, $signedElements);
$hasSignedAssertion = in_array($assertionTag, $signedElements);
@@ -144,65 +172,63 @@ class OneLogin_Saml2_Response
if ($security['wantXMLValidation']) {
$errorXmlMsg = "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd";
- $res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
+ $res = Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
if (!$res instanceof DOMDocument) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
$errorXmlMsg,
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
- # If encrypted, check also the decrypted document
+ // If encrypted, check also the decrypted document
if ($this->encrypted) {
- $res = OneLogin_Saml2_Utils::validateXML($this->decryptedDocument, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
+ $res = Utils::validateXML($this->decryptedDocument, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
if (!$res instanceof DOMDocument) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
$errorXmlMsg,
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
}
}
- $currentURL = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
-
+ $currentURL = Utils::getSelfRoutedURLNoQuery();
+
if ($this->document->documentElement->hasAttribute('InResponseTo')) {
$responseInResponseTo = $this->document->documentElement->getAttribute('InResponseTo');
}
// Check if the InResponseTo of the Response matchs the ID of the AuthNRequest (requestId) if provided
- if (isset($requestId) && isset($responseInResponseTo)) {
- if ($requestId != $responseInResponseTo) {
- throw new OneLogin_Saml2_ValidationError(
- "The InResponseTo of the Response: $responseInResponseTo, does not match the ID of the AuthNRequest sent by the SP: $requestId",
- OneLogin_Saml2_ValidationError::WRONG_INRESPONSETO
- );
- }
+ if (isset($requestId) && isset($responseInResponseTo) && $requestId != $responseInResponseTo) {
+ throw new ValidationError(
+ "The InResponseTo of the Response: $responseInResponseTo, does not match the ID of the AuthNRequest sent by the SP: $requestId",
+ ValidationError::WRONG_INRESPONSETO
+ );
}
if (!$this->encrypted && $security['wantAssertionsEncrypted']) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The assertion of the Response is not encrypted and the SP requires it",
- OneLogin_Saml2_ValidationError::NO_ENCRYPTED_ASSERTION
+ ValidationError::NO_ENCRYPTED_ASSERTION
);
}
if ($security['wantNameIdEncrypted']) {
$encryptedIdNodes = $this->_queryAssertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData');
if ($encryptedIdNodes->length != 1) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The NameID of the Response is not encrypted and the SP requires it",
- OneLogin_Saml2_ValidationError::NO_ENCRYPTED_NAMEID
+ ValidationError::NO_ENCRYPTED_NAMEID
);
}
}
// Validate Conditions element exists
if (!$this->checkOneCondition()) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The Assertion must include a Conditions element",
- OneLogin_Saml2_ValidationError::MISSING_CONDITIONS
+ ValidationError::MISSING_CONDITIONS
);
}
@@ -211,18 +237,18 @@ class OneLogin_Saml2_Response
// Validate AuthnStatement element exists and is unique
if (!$this->checkOneAuthnStatement()) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The Assertion must include an AuthnStatement element",
- OneLogin_Saml2_ValidationError::WRONG_NUMBER_OF_AUTHSTATEMENTS
+ ValidationError::WRONG_NUMBER_OF_AUTHSTATEMENTS
);
}
// EncryptedAttributes are not supported
$encryptedAttributeNodes = $this->_queryAssertion('/saml:AttributeStatement/saml:EncryptedAttribute');
if ($encryptedAttributeNodes->length > 0) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"There is an EncryptedAttribute in the Response and this SP not support them",
- OneLogin_Saml2_ValidationError::ENCRYPTED_ATTRIBUTES
+ ValidationError::ENCRYPTED_ATTRIBUTES
);
}
@@ -231,19 +257,19 @@ class OneLogin_Saml2_Response
$destination = trim($this->document->documentElement->getAttribute('Destination'));
if (empty($destination)) {
if (!$security['relaxDestinationValidation']) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The response has an empty Destination value",
- OneLogin_Saml2_ValidationError::EMPTY_DESTINATION
+ ValidationError::EMPTY_DESTINATION
);
}
} else {
if (strpos($destination, $currentURL) !== 0) {
- $currentURLNoRouted = OneLogin_Saml2_Utils::getSelfURLNoQuery();
+ $currentURLNoRouted = Utils::getSelfURLNoQuery();
if (strpos($destination, $currentURLNoRouted) !== 0) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The response was received at $currentURL instead of $destination",
- OneLogin_Saml2_ValidationError::WRONG_DESTINATION
+ ValidationError::WRONG_DESTINATION
);
}
}
@@ -253,13 +279,13 @@ class OneLogin_Saml2_Response
// Check audience
$validAudiences = $this->getAudiences();
if (!empty($validAudiences) && !in_array($spEntityId, $validAudiences, true)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
sprintf(
"Invalid audience for this Response (expected '%s', got '%s')",
$spEntityId,
implode(',', $validAudiences)
),
- OneLogin_Saml2_ValidationError::WRONG_AUDIENCE
+ ValidationError::WRONG_AUDIENCE
);
}
@@ -268,19 +294,19 @@ class OneLogin_Saml2_Response
foreach ($issuers as $issuer) {
$trimmedIssuer = trim($issuer);
if (empty($trimmedIssuer) || $trimmedIssuer !== $idPEntityId) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid issuer in the Assertion/Response (expected '$idPEntityId', got '$trimmedIssuer')",
- OneLogin_Saml2_ValidationError::WRONG_ISSUER
+ ValidationError::WRONG_ISSUER
);
}
}
// Check the session Expiration
$sessionExpiration = $this->getSessionNotOnOrAfter();
- if (!empty($sessionExpiration) && $sessionExpiration + OneLogin_Saml2_Constants::ALLOWED_CLOCK_DRIFT <= time()) {
- throw new OneLogin_Saml2_ValidationError(
+ if (!empty($sessionExpiration) && $sessionExpiration + Constants::ALLOWED_CLOCK_DRIFT <= time()) {
+ throw new ValidationError(
"The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response",
- OneLogin_Saml2_ValidationError::SESSION_EXPIRED
+ ValidationError::SESSION_EXPIRED
);
}
@@ -288,7 +314,7 @@ class OneLogin_Saml2_Response
$anySubjectConfirmation = false;
$subjectConfirmationNodes = $this->_queryAssertion('/saml:Subject/saml:SubjectConfirmation');
foreach ($subjectConfirmationNodes as $scn) {
- if ($scn->hasAttribute('Method') && $scn->getAttribute('Method') != OneLogin_Saml2_Constants::CM_BEARER) {
+ if ($scn->hasAttribute('Method') && $scn->getAttribute('Method') != Constants::CM_BEARER) {
continue;
}
$subjectConfirmationDataNodes = $scn->getElementsByTagName('SubjectConfirmationData');
@@ -309,14 +335,14 @@ class OneLogin_Saml2_Response
}
}
if ($scnData->hasAttribute('NotOnOrAfter')) {
- $noa = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotOnOrAfter'));
- if ($noa + OneLogin_Saml2_Constants::ALLOWED_CLOCK_DRIFT <= time()) {
+ $noa = Utils::parseSAML2Time($scnData->getAttribute('NotOnOrAfter'));
+ if ($noa + Constants::ALLOWED_CLOCK_DRIFT <= time()) {
continue;
}
}
if ($scnData->hasAttribute('NotBefore')) {
- $nb = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotBefore'));
- if ($nb > time() + OneLogin_Saml2_Constants::ALLOWED_CLOCK_DRIFT) {
+ $nb = Utils::parseSAML2Time($scnData->getAttribute('NotBefore'));
+ if ($nb > time() + Constants::ALLOWED_CLOCK_DRIFT) {
continue;
}
}
@@ -331,78 +357,85 @@ class OneLogin_Saml2_Response
}
if (!$anySubjectConfirmation) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"A valid SubjectConfirmation was not found on this Response",
- OneLogin_Saml2_ValidationError::WRONG_SUBJECTCONFIRMATION
+ ValidationError::WRONG_SUBJECTCONFIRMATION
);
}
if ($security['wantAssertionsSigned'] && !$hasSignedAssertion) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The Assertion of the Response is not signed and the SP requires it",
- OneLogin_Saml2_ValidationError::NO_SIGNED_ASSERTION
+ ValidationError::NO_SIGNED_ASSERTION
);
}
-
+
if ($security['wantMessagesSigned'] && !$hasSignedResponse) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The Message of the Response is not signed and the SP requires it",
- OneLogin_Saml2_ValidationError::NO_SIGNED_MESSAGE
+ ValidationError::NO_SIGNED_MESSAGE
);
}
}
// Detect case not supported
if ($this->encrypted) {
- $encryptedIDNodes = OneLogin_Saml2_Utils::query($this->decryptedDocument, '/samlp:Response/saml:Assertion/saml:Subject/saml:EncryptedID');
+ $encryptedIDNodes = Utils::query($this->decryptedDocument, '/samlp:Response/saml:Assertion/saml:Subject/saml:EncryptedID');
if ($encryptedIDNodes->length > 0) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Unsigned SAML Response that contains a signed and encrypted Assertion with encrypted nameId is not supported.',
- OneLogin_Saml2_ValidationError::NOT_SUPPORTED
+ ValidationError::NOT_SUPPORTED
);
}
}
if (empty($signedElements) || (!$hasSignedResponse && !$hasSignedAssertion)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'No Signature found. SAML Response rejected',
- OneLogin_Saml2_ValidationError::NO_SIGNATURE_FOUND
+ ValidationError::NO_SIGNATURE_FOUND
);
} else {
$cert = $idpData['x509cert'];
$fingerprint = $idpData['certFingerprint'];
$fingerprintalg = $idpData['certFingerprintAlgorithm'];
- # If find a Signature on the Response, validates it checking the original response
- if ($hasSignedResponse && !OneLogin_Saml2_Utils::validateSign($this->document, $cert, $fingerprint, $fingerprintalg, OneLogin_Saml2_Utils::RESPONSE_SIGNATURE_XPATH)) {
- throw new OneLogin_Saml2_ValidationError(
+ $multiCerts = null;
+ $existsMultiX509Sign = isset($idpData['x509certMulti']) && isset($idpData['x509certMulti']['signing']) && !empty($idpData['x509certMulti']['signing']);
+
+ if ($existsMultiX509Sign) {
+ $multiCerts = $idpData['x509certMulti']['signing'];
+ }
+
+ // If find a Signature on the Response, validates it checking the original response
+ if ($hasSignedResponse && !Utils::validateSign($this->document, $cert, $fingerprint, $fingerprintalg, Utils::RESPONSE_SIGNATURE_XPATH, $multiCerts)) {
+ throw new ValidationError(
"Signature validation failed. SAML Response rejected",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
+ ValidationError::INVALID_SIGNATURE
);
}
- # If find a Signature on the Assertion (decrypted assertion if was encrypted)
+ // If find a Signature on the Assertion (decrypted assertion if was encrypted)
$documentToCheckAssertion = $this->encrypted ? $this->decryptedDocument : $this->document;
- if ($hasSignedAssertion && !OneLogin_Saml2_Utils::validateSign($documentToCheckAssertion, $cert, $fingerprint, $fingerprintalg, OneLogin_Saml2_Utils::ASSERTION_SIGNATURE_XPATH)) {
- throw new OneLogin_Saml2_ValidationError(
+ if ($hasSignedAssertion && !Utils::validateSign($documentToCheckAssertion, $cert, $fingerprint, $fingerprintalg, Utils::ASSERTION_SIGNATURE_XPATH, $multiCerts)) {
+ throw new ValidationError(
"Signature validation failed. SAML Response rejected",
- OneLogin_Saml2_ValidationError::INVALID_SIGNATURE
+ ValidationError::INVALID_SIGNATURE
);
}
}
return true;
} catch (Exception $e) {
- $this->_error = $e->getMessage();
+ $this->_error = $e;
$debug = $this->_settings->isDebugActive();
if ($debug) {
- echo $this->_error;
+ echo htmlentities($e->getMessage());
}
return false;
}
}
/**
- * @return the ID of the Response
+ * @return string|null the ID of the Response
*/
public function getId()
{
@@ -414,25 +447,26 @@ class OneLogin_Saml2_Response
}
/**
- * @return the ID of the assertion in the Response
+ * @return string|null the ID of the assertion in the Response
+ *
+ * @throws ValidationError
*/
public function getAssertionId()
{
if (!$this->validateNumAssertions()) {
- throw new IllegalArgumentException("SAML Response must contain 1 Assertion.");
+ throw new ValidationError("SAML Response must contain 1 Assertion.", ValidationError::WRONG_NUMBER_OF_ASSERTIONS);
}
$assertionNodes = $this->_queryAssertion("");
$id = null;
- if ($assertionNodes->length == 1) {
- if ($assertionNodes->item(0)->hasAttribute('ID')) {
- $id = $assertionNodes->item(0)->getAttribute('ID');
- }
+ if ($assertionNodes->length == 1 && $assertionNodes->item(0)->hasAttribute('ID')) {
+ $id = $assertionNodes->item(0)->getAttribute('ID');
}
return $id;
}
/**
- * @return the NotOnOrAfter value of the valid SubjectConfirmationData * node if any
+ * @return int the NotOnOrAfter value of the valid SubjectConfirmationData
+ * node if any
*/
public function getAssertionNotOnOrAfter()
{
@@ -442,13 +476,13 @@ class OneLogin_Saml2_Response
/**
* Checks if the Status is success
*
- * @throws $statusExceptionMsg If status is not success
+ * @throws ValidationError If status is not success
*/
public function checkStatus()
{
- $status = OneLogin_Saml2_Utils::getStatus($this->document);
+ $status = Utils::getStatus($this->document);
- if (isset($status['code']) && $status['code'] !== OneLogin_Saml2_Constants::STATUS_SUCCESS) {
+ if (isset($status['code']) && $status['code'] !== Constants::STATUS_SUCCESS) {
$explodedCode = explode(':', $status['code']);
$printableCode = array_pop($explodedCode);
@@ -456,18 +490,18 @@ class OneLogin_Saml2_Response
if (!empty($status['msg'])) {
$statusExceptionMsg .= ' -> '.$status['msg'];
}
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
$statusExceptionMsg,
- OneLogin_Saml2_ValidationError::STATUS_CODE_IS_NOT_SUCCESS
+ ValidationError::STATUS_CODE_IS_NOT_SUCCESS
);
}
}
- /**
- * Checks that the samlp:Response/saml:Assertion/saml:Conditions element exists and is unique.
- *
- * @return boolean true if the Conditions element exists and is unique
- */
+ /**
+ * Checks that the samlp:Response/saml:Assertion/saml:Conditions element exists and is unique.
+ *
+ * @return boolean true if the Conditions element exists and is unique
+ */
public function checkOneCondition()
{
$entries = $this->_queryAssertion("/saml:Conditions");
@@ -478,11 +512,11 @@ class OneLogin_Saml2_Response
}
}
- /**
- * Checks that the samlp:Response/saml:Assertion/saml:AuthnStatement element exists and is unique.
- *
- * @return boolean true if the AuthnStatement element exists and is unique
- */
+ /**
+ * Checks that the samlp:Response/saml:Assertion/saml:AuthnStatement element exists and is unique.
+ *
+ * @return boolean true if the AuthnStatement element exists and is unique
+ */
public function checkOneAuthnStatement()
{
$entries = $this->_queryAssertion("/saml:AuthnStatement");
@@ -517,19 +551,21 @@ class OneLogin_Saml2_Response
* Gets the Issuers (from Response and Assertion).
*
* @return array @issuers The issuers of the assertion/response
+ *
+ * @throws ValidationError
*/
public function getIssuers()
{
$issuers = array();
- $responseIssuer = OneLogin_Saml2_Utils::query($this->document, '/samlp:Response/saml:Issuer');
+ $responseIssuer = Utils::query($this->document, '/samlp:Response/saml:Issuer');
if ($responseIssuer->length > 0) {
if ($responseIssuer->length == 1) {
$issuers[] = $responseIssuer->item(0)->textContent;
} else {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Issuer of the Response is multiple.",
- OneLogin_Saml2_ValidationError::ISSUER_MULTIPLE_IN_RESPONSE
+ ValidationError::ISSUER_MULTIPLE_IN_RESPONSE
);
}
}
@@ -538,9 +574,9 @@ class OneLogin_Saml2_Response
if ($assertionIssuer->length == 1) {
$issuers[] = $assertionIssuer->item(0)->textContent;
} else {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Issuer of the Assertion not found or multiple.",
- OneLogin_Saml2_ValidationError::ISSUER_NOT_FOUND_IN_ASSERTION
+ ValidationError::ISSUER_NOT_FOUND_IN_ASSERTION
);
}
@@ -551,6 +587,8 @@ class OneLogin_Saml2_Response
* Gets the NameID Data provided by the SAML response from the IdP.
*
* @return array Name ID Data (Value, Format, NameQualifier, SPNameQualifier)
+ *
+ * @throws ValidationError
*/
public function getNameIdData()
{
@@ -563,7 +601,7 @@ class OneLogin_Saml2_Response
$seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type'=>'private'));
$seckey->loadKey($key);
- $nameId = OneLogin_Saml2_Utils::decryptElement($encryptedData, $seckey);
+ $nameId = Utils::decryptElement($encryptedData, $seckey);
} else {
$entries = $this->_queryAssertion('/saml:Subject/saml:NameID');
@@ -577,16 +615,16 @@ class OneLogin_Saml2_Response
if (!isset($nameId)) {
$security = $this->_settings->getSecurityData();
if ($security['wantNameId']) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"NameID not found in the assertion of the Response",
- OneLogin_Saml2_ValidationError::NO_NAMEID
+ ValidationError::NO_NAMEID
);
}
} else {
if ($this->_settings->isStrict() && empty($nameId->nodeValue)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"An empty NameID value found",
- OneLogin_Saml2_ValidationError::EMPTY_NAMEID
+ ValidationError::EMPTY_NAMEID
);
}
$nameIdData['Value'] = $nameId->nodeValue;
@@ -597,9 +635,9 @@ class OneLogin_Saml2_Response
$spData = $this->_settings->getSPData();
$spEntityId = $spData['entityId'];
if ($spEntityId != $nameId->getAttribute($attr)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"The SPNameQualifier value mistmatch the SP entityID value.",
- OneLogin_Saml2_ValidationError::SP_NAME_QUALIFIER_NAME_MISMATCH
+ ValidationError::SP_NAME_QUALIFIER_NAME_MISMATCH
);
}
}
@@ -614,7 +652,9 @@ class OneLogin_Saml2_Response
/**
* Gets the NameID provided by the SAML response from the IdP.
*
- * @return string Name ID Value
+ * @return string|null Name ID Value
+ *
+ * @throws ValidationError
*/
public function getNameId()
{
@@ -629,7 +669,9 @@ class OneLogin_Saml2_Response
/**
* Gets the NameID Format provided by the SAML response from the IdP.
*
- * @return string Name ID Format
+ * @return string|null Name ID Format
+ *
+ * @throws ValidationError
*/
public function getNameIdFormat()
{
@@ -642,17 +684,53 @@ class OneLogin_Saml2_Response
}
/**
+ * Gets the NameID NameQualifier provided by the SAML response from the IdP.
+ *
+ * @return string|null Name ID NameQualifier
+ *
+ * @throws ValidationError
+ */
+ public function getNameIdNameQualifier()
+ {
+ $nameIdNameQualifier = null;
+ $nameIdData = $this->getNameIdData();
+ if (!empty($nameIdData) && isset($nameIdData['NameQualifier'])) {
+ $nameIdNameQualifier = $nameIdData['NameQualifier'];
+ }
+ return $nameIdNameQualifier;
+ }
+
+ /**
+ * Gets the NameID SP NameQualifier provided by the SAML response from the IdP.
+ *
+ * @return string|null NameID SP NameQualifier
+ *
+ * @throws ValidationError
+ */
+ public function getNameIdSPNameQualifier()
+ {
+ $nameIdSPNameQualifier = null;
+ $nameIdData = $this->getNameIdData();
+ if (!empty($nameIdData) && isset($nameIdData['SPNameQualifier'])) {
+ $nameIdSPNameQualifier = $nameIdData['SPNameQualifier'];
+ }
+ return $nameIdSPNameQualifier;
+ }
+
+ /**
* Gets the SessionNotOnOrAfter from the AuthnStatement.
* Could be used to set the local session expiration
*
* @return int|null The SessionNotOnOrAfter value
+ *
+ * @throws Exception
*/
public function getSessionNotOnOrAfter()
{
$notOnOrAfter = null;
$entries = $this->_queryAssertion('/saml:AuthnStatement[@SessionNotOnOrAfter]');
if ($entries->length !== 0) {
- $notOnOrAfter = OneLogin_Saml2_Utils::parseSAML2Time($entries->item(0)->getAttribute('SessionNotOnOrAfter'));
+ $notOnOrAfter = Utils::parseSAML2Time($entries->item(0)->getAttribute('SessionNotOnOrAfter'));
}
return $notOnOrAfter;
}
@@ -665,7 +743,6 @@ class OneLogin_Saml2_Response
*
* @return string|null The SessionIndex value
*/
-
public function getSessionIndex()
{
$sessionIndex = null;
@@ -680,38 +757,50 @@ class OneLogin_Saml2_Response
* Gets the Attributes from the AttributeStatement element.
*
* @return array The attributes of the SAML Assertion
+ *
+ * @throws ValidationError
*/
public function getAttributes()
{
- $attributes = array();
-
- /* EncryptedAttributes not supported
-
- $encriptedAttributes = $this->_queryAssertion('/saml:AttributeStatement/saml:EncryptedAttribute');
+ return $this->_getAttributesByKeyName('Name');
+ }
- if ($encriptedAttributes->length > 0) {
- foreach ($encriptedAttributes as $encriptedAttribute) {
- $key = $this->_settings->getSPkey();
- $seckey = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, array('type'=>'private'));
- $seckey->loadKey($key);
- $attribute = OneLogin_Saml2_Utils::decryptElement($encriptedAttribute->firstChild(), $seckey);
- }
- }
- */
+ /**
+ * Gets the Attributes from the AttributeStatement element using their FriendlyName.
+ *
+ * @return array The attributes of the SAML Assertion
+ *
+ * @throws ValidationError
+ */
+ public function getAttributesWithFriendlyName()
+ {
+ return $this->_getAttributesByKeyName('FriendlyName');
+ }
+ /**
+ * @param string $keyName
+ *
+ * @return array
+ *
+ * @throws ValidationError
+ */
+ private function _getAttributesByKeyName($keyName = "Name")
+ {
+ $attributes = array();
$entries = $this->_queryAssertion('/saml:AttributeStatement/saml:Attribute');
-
/** @var $entry DOMNode */
foreach ($entries as $entry) {
- $attributeName = $entry->attributes->getNamedItem('Name')->nodeValue;
-
- if (in_array($attributeName, array_keys($attributes))) {
- throw new OneLogin_Saml2_ValidationError(
- "Found an Attribute element with duplicated Name",
- OneLogin_Saml2_ValidationError::DUPLICATED_ATTRIBUTE_NAME_FOUND
+ $attributeKeyNode = $entry->attributes->getNamedItem($keyName);
+ if ($attributeKeyNode === null) {
+ continue;
+ }
+ $attributeKeyName = $attributeKeyNode->nodeValue;
+ if (in_array($attributeKeyName, array_keys($attributes))) {
+ throw new ValidationError(
+ "Found an Attribute element with duplicated ".$keyName,
+ ValidationError::DUPLICATED_ATTRIBUTE_NAME_FOUND
);
}
-
$attributeValues = array();
foreach ($entry->childNodes as $childNode) {
$tagName = ($childNode->prefix ? $childNode->prefix.':' : '') . 'AttributeValue';
@@ -719,8 +808,7 @@ class OneLogin_Saml2_Response
$attributeValues[] = $childNode->nodeValue;
}
}
-
- $attributes[$attributeName] = $attributeValues;
+ $attributes[$attributeKeyName] = $attributeValues;
}
return $attributes;
}
@@ -751,6 +839,8 @@ class OneLogin_Saml2_Response
* - Check that IDs and reference URI are unique and consistent.
*
* @return array Signed element tags
+ *
+ * @throws ValidationError
*/
public function processSignedElements()
{
@@ -764,31 +854,31 @@ class OneLogin_Saml2_Response
$signNodes = $this->document->getElementsByTagName('Signature');
}
foreach ($signNodes as $signNode) {
- $responseTag = '{'.OneLogin_Saml2_Constants::NS_SAMLP.'}Response';
- $assertionTag = '{'.OneLogin_Saml2_Constants::NS_SAML.'}Assertion';
+ $responseTag = '{'.Constants::NS_SAMLP.'}Response';
+ $assertionTag = '{'.Constants::NS_SAML.'}Assertion';
$signedElement = '{'.$signNode->parentNode->namespaceURI.'}'.$signNode->parentNode->localName;
if ($signedElement != $responseTag && $signedElement != $assertionTag) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Invalid Signature Element $signedElement SAML Response rejected",
- OneLogin_Saml2_ValidationError::WRONG_SIGNED_ELEMENT
+ ValidationError::WRONG_SIGNED_ELEMENT
);
}
- # Check that reference URI matches the parent ID and no duplicate References or IDs
+ // Check that reference URI matches the parent ID and no duplicate References or IDs
$idValue = $signNode->parentNode->getAttribute('ID');
if (empty($idValue)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Signed Element must contain an ID. SAML Response rejected',
- OneLogin_Saml2_ValidationError::ID_NOT_FOUND_IN_SIGNED_ELEMENT
+ ValidationError::ID_NOT_FOUND_IN_SIGNED_ELEMENT
);
}
if (in_array($idValue, $verifiedIds)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Duplicated ID. SAML Response rejected',
- OneLogin_Saml2_ValidationError::DUPLICATED_ID_IN_SIGNED_ELEMENTS
+ ValidationError::DUPLICATED_ID_IN_SIGNED_ELEMENTS
);
}
$verifiedIds[] = $idValue;
@@ -801,37 +891,35 @@ class OneLogin_Saml2_Response
$sei = substr($sei, 1);
if ($sei != $idValue) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Found an invalid Signed Element. SAML Response rejected',
- OneLogin_Saml2_ValidationError::INVALID_SIGNED_ELEMENT
+ ValidationError::INVALID_SIGNED_ELEMENT
);
}
if (in_array($sei, $verifiedSeis)) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Duplicated Reference URI. SAML Response rejected',
- OneLogin_Saml2_ValidationError::DUPLICATED_REFERENCE_IN_SIGNED_ELEMENTS
+ ValidationError::DUPLICATED_REFERENCE_IN_SIGNED_ELEMENTS
);
}
$verifiedSeis[] = $sei;
}
} else {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Unexpected number of Reference nodes found for signature. SAML Response rejected.',
- OneLogin_Saml2_ValidationError::UNEXPECTED_REFERENCE
+ ValidationError::UNEXPECTED_REFERENCE
);
}
$signedElements[] = $signedElement;
}
- if (!empty($signedElements)) {
- // Check SignedElements
- if (!$this->validateSignedElements($signedElements)) {
- throw new OneLogin_Saml2_ValidationError(
- 'Found an unexpected Signature Element. SAML Response rejected',
- OneLogin_Saml2_ValidationError::UNEXPECTED_SIGNED_ELEMENTS
- );
- }
+ // Check SignedElements
+ if (!empty($signedElements) && !$this->validateSignedElements($signedElements)) {
+ throw new ValidationError(
+ 'Found an unexpected Signature Element. SAML Response rejected',
+ ValidationError::UNEXPECTED_SIGNED_ELEMENTS
+ );
}
return $signedElements;
}
@@ -840,6 +928,9 @@ class OneLogin_Saml2_Response
* Verifies that the document is still valid according Conditions Element.
*
* @return bool
+ *
+ * @throws Exception
+ * @throws ValidationError
*/
public function validateTimestamps()
{
@@ -853,16 +944,16 @@ class OneLogin_Saml2_Response
for ($i = 0; $i < $timestampNodes->length; $i++) {
$nbAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotBefore");
$naAttribute = $timestampNodes->item($i)->attributes->getNamedItem("NotOnOrAfter");
- if ($nbAttribute && OneLogin_SAML2_Utils::parseSAML2Time($nbAttribute->textContent) > time() + OneLogin_Saml2_Constants::ALLOWED_CLOCK_DRIFT) {
- throw new OneLogin_Saml2_ValidationError(
+ if ($nbAttribute && Utils::parseSAML2Time($nbAttribute->textContent) > time() + Constants::ALLOWED_CLOCK_DRIFT) {
+ throw new ValidationError(
'Could not validate timestamp: not yet valid. Check system clock.',
- OneLogin_Saml2_ValidationError::ASSERTION_TOO_EARLY
+ ValidationError::ASSERTION_TOO_EARLY
);
}
- if ($naAttribute && OneLogin_SAML2_Utils::parseSAML2Time($naAttribute->textContent) + OneLogin_Saml2_Constants::ALLOWED_CLOCK_DRIFT <= time()) {
- throw new OneLogin_Saml2_ValidationError(
+ if ($naAttribute && Utils::parseSAML2Time($naAttribute->textContent) + Constants::ALLOWED_CLOCK_DRIFT <= time()) {
+ throw new ValidationError(
'Could not validate timestamp: expired. Check system clock.',
- OneLogin_Saml2_ValidationError::ASSERTION_EXPIRED
+ ValidationError::ASSERTION_EXPIRED
);
}
}
@@ -872,7 +963,11 @@ class OneLogin_Saml2_Response
/**
* Verifies that the document has the expected signed nodes.
*
+ * @param array $signedElements Signed elements
+ *
* @return bool
+ *
+ * @throws ValidationError
*/
public function validateSignedElements($signedElements)
{
@@ -880,35 +975,35 @@ class OneLogin_Saml2_Response
return false;
}
- $responseTag = '{'.OneLogin_Saml2_Constants::NS_SAMLP.'}Response';
- $assertionTag = '{'.OneLogin_Saml2_Constants::NS_SAML.'}Assertion';
+ $responseTag = '{'.Constants::NS_SAMLP.'}Response';
+ $assertionTag = '{'.Constants::NS_SAML.'}Assertion';
$ocurrence = array_count_values($signedElements);
- if ((in_array($responseTag, $signedElements) && $ocurrence[$responseTag] > 1) ||
- (in_array($assertionTag, $signedElements) && $ocurrence[$assertionTag] > 1) ||
- !in_array($responseTag, $signedElements) && !in_array($assertionTag, $signedElements)
+ if ((in_array($responseTag, $signedElements) && $ocurrence[$responseTag] > 1)
+ || (in_array($assertionTag, $signedElements) && $ocurrence[$assertionTag] > 1)
+ || !in_array($responseTag, $signedElements) && !in_array($assertionTag, $signedElements)
) {
return false;
}
// Check that the signed elements found here, are the ones that will be verified
- // by OneLogin_Saml2_Utils->validateSign()
+ // by Utils->validateSign()
if (in_array($responseTag, $signedElements)) {
- $expectedSignatureNodes = OneLogin_Saml2_Utils::query($this->document, OneLogin_Saml2_Utils::RESPONSE_SIGNATURE_XPATH);
+ $expectedSignatureNodes = Utils::query($this->document, Utils::RESPONSE_SIGNATURE_XPATH);
if ($expectedSignatureNodes->length != 1) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Unexpected number of Response signatures found. SAML Response rejected.",
- OneLogin_Saml2_ValidationError::WRONG_NUMBER_OF_SIGNATURES_IN_RESPONSE
+ ValidationError::WRONG_NUMBER_OF_SIGNATURES_IN_RESPONSE
);
}
}
if (in_array($assertionTag, $signedElements)) {
- $expectedSignatureNodes = $this->_query(OneLogin_Saml2_Utils::ASSERTION_SIGNATURE_XPATH);
+ $expectedSignatureNodes = $this->_query(Utils::ASSERTION_SIGNATURE_XPATH);
if ($expectedSignatureNodes->length != 1) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Unexpected number of Assertion signatures found. SAML Response rejected.",
- OneLogin_Saml2_ValidationError::WRONG_NUMBER_OF_SIGNATURES_IN_ASSERTION
+ ValidationError::WRONG_NUMBER_OF_SIGNATURES_IN_ASSERTION
);
}
}
@@ -919,11 +1014,9 @@ class OneLogin_Saml2_Response
/**
* Extracts a node from the DOMDocument (Assertion).
*
- * @param string $assertionXpath Xpath Expresion
+ * @param string $assertionXpath Xpath Expression
*
* @return DOMNodeList The queried node
- *
- * @throws Exception
*/
protected function _queryAssertion($assertionXpath)
{
@@ -933,10 +1026,10 @@ class OneLogin_Saml2_Response
$xpath = new DOMXPath($this->document);
}
- $xpath->registerNamespace('samlp', OneLogin_Saml2_Constants::NS_SAMLP);
- $xpath->registerNamespace('saml', OneLogin_Saml2_Constants::NS_SAML);
- $xpath->registerNamespace('ds', OneLogin_Saml2_Constants::NS_DS);
- $xpath->registerNamespace('xenc', OneLogin_Saml2_Constants::NS_XENC);
+ $xpath->registerNamespace('samlp', Constants::NS_SAMLP);
+ $xpath->registerNamespace('saml', Constants::NS_SAML);
+ $xpath->registerNamespace('ds', Constants::NS_DS);
+ $xpath->registerNamespace('xenc', Constants::NS_XENC);
$assertionNode = '/samlp:Response/saml:Assertion';
$signatureQuery = $assertionNode . '/ds:Signature/ds:SignedInfo/ds:Reference';
@@ -972,54 +1065,55 @@ class OneLogin_Saml2_Response
/**
* Extracts nodes that match the query from the DOMDocument (Response Menssage)
*
- * @param string $query Xpath Expresion
+ * @param string $query Xpath Expression
*
* @return DOMNodeList The queried nodes
*/
private function _query($query)
{
if ($this->encrypted) {
- return OneLogin_Saml2_Utils::query($this->decryptedDocument, $query);
+ return Utils::query($this->decryptedDocument, $query);
} else {
- return OneLogin_Saml2_Utils::query($this->document, $query);
+ return Utils::query($this->document, $query);
}
}
/**
* Decrypts the Assertion (DOMDocument)
*
- * @param DomNode $dom DomDocument
+ * @param \DomNode $dom DomDocument
*
* @return DOMDocument Decrypted Assertion
*
* @throws Exception
+ * @throws ValidationError
*/
- protected function _decryptAssertion($dom)
+ protected function decryptAssertion(\DomNode $dom)
{
$pem = $this->_settings->getSPkey();
if (empty($pem)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
"No private key available, check settings",
- OneLogin_Saml2_Error::PRIVATE_KEY_NOT_FOUND
+ Error::PRIVATE_KEY_NOT_FOUND
);
}
-
+
$objenc = new XMLSecEnc();
$encData = $objenc->locateEncryptedData($dom);
if (!$encData) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Cannot locate encrypted assertion",
- OneLogin_Saml2_ValidationError::MISSING_ENCRYPTED_ELEMENT
+ ValidationError::MISSING_ENCRYPTED_ELEMENT
);
}
-
+
$objenc->setNode($encData);
$objenc->type = $encData->getAttribute("Type");
if (!$objKey = $objenc->locateKey()) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Unknown algorithm",
- OneLogin_Saml2_ValidationError::KEY_ALGORITHM_ERROR
+ ValidationError::KEY_ALGORITHM_ERROR
);
}
@@ -1034,26 +1128,31 @@ class OneLogin_Saml2_Response
$objKeyInfo->loadKey($pem, false, false);
}
}
-
+
if (empty($objKey->key)) {
$objKey->loadKey($key);
}
- $decrypted = $objenc->decryptNode($objKey, true);
-
- if ($decrypted instanceof DOMDocument) {
+ $decryptedXML = $objenc->decryptNode($objKey, false);
+ $decrypted = new DOMDocument();
+ $check = Utils::loadXML($decrypted, $decryptedXML);
+ if ($check === false) {
+ throw new Exception('Error: string from decrypted assertion could not be loaded into a XML document');
+ }
+ if ($encData->parentNode instanceof DOMDocument) {
return $decrypted;
} else {
- $encryptedAssertion = $decrypted->parentNode;
+ $decrypted = $decrypted->documentElement;
+ $encryptedAssertion = $encData->parentNode;
$container = $encryptedAssertion->parentNode;
- # Fix possible issue with saml namespace
- if (!$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml') &&
- !$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml2') &&
- !$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns') &&
- !$container->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml') &&
- !$container->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml2')
- ) {
+ // Fix possible issue with saml namespace
+ if (!$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml')
+ && !$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml2')
+ && !$decrypted->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns')
+ && !$container->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml')
+ && !$container->hasAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:saml2')
+ ) {
if (strpos($encryptedAssertion->tagName, 'saml2:') !== false) {
$ns = 'xmlns:saml2';
} else if (strpos($encryptedAssertion->tagName, 'saml:') !== false) {
@@ -1061,26 +1160,42 @@ class OneLogin_Saml2_Response
} else {
$ns = 'xmlns';
}
-
- $decrypted->setAttributeNS('http://www.w3.org/2000/xmlns/', $ns, OneLogin_Saml2_Constants::NS_SAML);
+ $decrypted->setAttributeNS('http://www.w3.org/2000/xmlns/', $ns, Constants::NS_SAML);
}
- $container->replaceChild($decrypted, $encryptedAssertion);
+ Utils::treeCopyReplace($encryptedAssertion, $decrypted);
- return $decrypted->ownerDocument;
+ // Rebuild the DOM will fix issues with namespaces as well
+ $dom = new DOMDocument();
+ return Utils::loadXML($dom, $container->ownerDocument->saveXML());
}
}
- /* After execute a validation process, if fails this method returns the cause
+ /**
+ * After execute a validation process, if fails this method returns the cause
*
- * @return string Cause
+ * @return Exception|null Cause
*/
- public function getError()
+ public function getErrorException()
{
return $this->_error;
}
- /*
+ /**
+ * After execute a validation process, if fails this method returns the cause
+ *
+ * @return null|string Error reason
+ */
+ public function getError()
+ {
+ $errorMsg = null;
+ if (isset($this->_error)) {
+ $errorMsg = htmlentities($this->_error->getMessage());
+ }
+ return $errorMsg;
+ }
+
+ /**
* Returns the SAML Response document (If contains an encrypted assertion, decrypts it)
*
* @return DomDocument SAML Response
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Settings.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Settings.php
index 74defa72..a6a41b78 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Settings.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Settings.php
@@ -1,11 +1,30 @@
<?php
-
/**
- * Configuration of the OneLogin PHP Toolkit
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
*
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
*/
-class OneLogin_Saml2_Settings
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+use RobRichards\XMLSecLibs\XMLSecurityDSig;
+
+use DOMDocument;
+use Exception;
+
+/**
+ * Configuration of the OneLogin PHP Toolkit
+ */
+class Settings
{
/**
* List of paths.
@@ -17,7 +36,7 @@ class OneLogin_Saml2_Settings
/**
* @var string
*/
- private $_baseurl;
+ private $_baseurl;
/**
* Strict. If active, PHP Toolkit will reject unsigned or unencrypted messages
@@ -86,9 +105,9 @@ class OneLogin_Saml2_Settings
private $_errors = array();
/**
- * Setting errors.
+ * Valitate SP data only flag
*
- * @var array
+ * @var bool
*/
private $_spValidationOnly = false;
@@ -97,44 +116,31 @@ class OneLogin_Saml2_Settings
* - Sets the paths of the different folders
* - Loads settings info from settings file or array/object provided
*
- * @param array|object|null $settings SAML Toolkit Settings
+ * @param array|null $settings SAML Toolkit Settings
+ * @param bool $spValidationOnly Validate or not the IdP data
*
- * @throws OneLogin_Saml2_Error If any settings parameter is invalid
- * @throws Exception If OneLogin_Saml2_Settings is incorrectly supplied
+ * @throws Error If any settings parameter is invalid
+ * @throws Exception If Settings is incorrectly supplied
*/
- public function __construct($settings = null, $spValidationOnly = false)
+ public function __construct(array $settings = null, $spValidationOnly = false)
{
$this->_spValidationOnly = $spValidationOnly;
$this->_loadPaths();
if (!isset($settings)) {
if (!$this->_loadSettingsFromFile()) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'Invalid file settings: %s',
- OneLogin_Saml2_Error::SETTINGS_INVALID,
+ Error::SETTINGS_INVALID,
array(implode(', ', $this->_errors))
);
}
$this->_addDefaultValues();
- } else if (is_array($settings)) {
- if (!$this->_loadSettingsFromArray($settings)) {
- throw new OneLogin_Saml2_Error(
- 'Invalid array settings: %s',
- OneLogin_Saml2_Error::SETTINGS_INVALID,
- array(implode(', ', $this->_errors))
- );
- }
- } else if ($settings instanceof OneLogin_Saml2_Settings) {
- throw new OneLogin_Saml2_Error(
- 'Only instances of OneLogin_Saml_Settings are supported.',
- OneLogin_Saml2_Error::UNSUPPORTED_SETTINGS_OBJECT,
- array(implode(', ', $this->_errors))
- );
} else {
- if (!$this->_loadSettingsFromArray($settings->getValues())) {
- throw new OneLogin_Saml2_Error(
+ if (!$this->_loadSettingsFromArray($settings)) {
+ throw new Error(
'Invalid array settings: %s',
- OneLogin_Saml2_Error::SETTINGS_INVALID,
+ Error::SETTINGS_INVALID,
array(implode(', ', $this->_errors))
);
}
@@ -143,25 +149,27 @@ class OneLogin_Saml2_Settings
$this->formatIdPCert();
$this->formatSPCert();
$this->formatSPKey();
+ $this->formatSPCertNew();
+ $this->formatIdPCertMulti();
}
/**
* Sets the paths of the different folders
+ * @suppress PhanUndeclaredConstant
*/
private function _loadPaths()
{
- $basePath = dirname(dirname(dirname(__FILE__))).'/';
- $this->_paths = array (
+ $basePath = dirname(dirname(__DIR__)) . '/';
+ $this->_paths = array(
'base' => $basePath,
'config' => $basePath,
'cert' => $basePath.'certs/',
- 'lib' => $basePath.'lib/',
- 'extlib' => $basePath.'extlib/'
+ 'lib' => $basePath.'src/'
);
if (defined('ONELOGIN_CUSTOMPATH')) {
$this->_paths['config'] = ONELOGIN_CUSTOMPATH;
- $this->_paths['cert'] = ONELOGIN_CUSTOMPATH.'certs/';
+ $this->_paths['cert'] = ONELOGIN_CUSTOMPATH . 'certs/';
}
}
@@ -206,16 +214,6 @@ class OneLogin_Saml2_Settings
}
/**
- * Returns external lib path.
- *
- * @return string The external library folder path
- */
- public function getExtLibPath()
- {
- return $this->_paths['extlib'];
- }
-
- /**
* Returns schema path.
*
* @return string The external library folder path
@@ -232,7 +230,7 @@ class OneLogin_Saml2_Settings
*
* @return bool True if the settings info is valid
*/
- private function _loadSettingsFromArray($settings)
+ private function _loadSettingsFromArray(array $settings)
{
if (isset($settings['sp'])) {
$this->_sp = $settings['sp'];
@@ -284,27 +282,31 @@ class OneLogin_Saml2_Settings
* Loads settings info from the settings file
*
* @return bool True if the settings info is valid
- * @throws OneLogin_Saml2_Error
+ *
+ * @throws Error
+ *
+ * @suppress PhanUndeclaredVariable
*/
private function _loadSettingsFromFile()
{
$filename = $this->getConfigPath().'settings.php';
if (!file_exists($filename)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'Settings file not found: %s',
- OneLogin_Saml2_Error::SETTINGS_FILE_NOT_FOUND,
+ Error::SETTINGS_FILE_NOT_FOUND,
array($filename)
);
}
+ /** @var array $settings */
include $filename;
// Add advance_settings if exists
-
$advancedFilename = $this->getConfigPath().'advanced_settings.php';
if (file_exists($advancedFilename)) {
+ /** @var array $advancedSettings */
include $advancedFilename;
$settings = array_merge($settings, $advancedSettings);
}
@@ -319,10 +321,10 @@ class OneLogin_Saml2_Settings
private function _addDefaultValues()
{
if (!isset($this->_sp['assertionConsumerService']['binding'])) {
- $this->_sp['assertionConsumerService']['binding'] = OneLogin_Saml2_Constants::BINDING_HTTP_POST;
+ $this->_sp['assertionConsumerService']['binding'] = Constants::BINDING_HTTP_POST;
}
if (isset($this->_sp['singleLogoutService']) && !isset($this->_sp['singleLogoutService']['binding'])) {
- $this->_sp['singleLogoutService']['binding'] = OneLogin_Saml2_Constants::BINDING_HTTP_REDIRECT;
+ $this->_sp['singleLogoutService']['binding'] = Constants::BINDING_HTTP_REDIRECT;
}
if (!isset($this->_compress['requests'])) {
@@ -335,7 +337,7 @@ class OneLogin_Saml2_Settings
// Related to nameID
if (!isset($this->_sp['NameIDFormat'])) {
- $this->_sp['NameIDFormat'] = OneLogin_Saml2_Constants::NAMEID_UNSPECIFIED;
+ $this->_sp['NameIDFormat'] = Constants::NAMEID_UNSPECIFIED;
}
if (!isset($this->_security['nameIdEncrypted'])) {
$this->_security['nameIdEncrypted'] = false;
@@ -391,12 +393,12 @@ class OneLogin_Saml2_Settings
// SignatureAlgorithm
if (!isset($this->_security['signatureAlgorithm'])) {
- $this->_security['signatureAlgorithm'] = XMLSecurityKey::RSA_SHA1;
+ $this->_security['signatureAlgorithm'] = XMLSecurityKey::RSA_SHA256;
}
// DigestAlgorithm
if (!isset($this->_security['digestAlgorithm'])) {
- $this->_security['digestAlgorithm'] = XMLSecurityDSig::SHA1;
+ $this->_security['digestAlgorithm'] = XMLSecurityDSig::SHA256;
}
if (!isset($this->_security['lowercaseUrlencoding'])) {
@@ -429,11 +431,9 @@ class OneLogin_Saml2_Settings
*
* @return array $errors Errors found on the settings data
*/
- public function checkSettings($settings)
+ public function checkSettings(array $settings)
{
- assert('is_array($settings)');
-
- if (!is_array($settings) || empty($settings)) {
+ if (empty($settings)) {
$errors = array('invalid_syntax');
} else {
$errors = array();
@@ -465,14 +465,12 @@ class OneLogin_Saml2_Settings
if (isset($settings['compress'])) {
if (!is_array($settings['compress'])) {
$errors[] = "invalid_syntax";
- } else if (
- isset($settings['compress']['requests'])
+ } else if (isset($settings['compress']['requests'])
&& $settings['compress']['requests'] !== true
&& $settings['compress']['requests'] !== false
) {
$errors[] = "'compress'=>'requests' values must be true or false.";
- } else if (
- isset($settings['compress']['responses'])
+ } else if (isset($settings['compress']['responses'])
&& $settings['compress']['responses'] !== true
&& $settings['compress']['responses'] !== false
) {
@@ -489,11 +487,9 @@ class OneLogin_Saml2_Settings
*
* @return array $errors Errors found on the IdP settings data
*/
- public function checkIdPSettings($settings)
+ public function checkIdPSettings(array $settings)
{
- assert('is_array($settings)');
-
- if (!is_array($settings) || empty($settings)) {
+ if (empty($settings)) {
return array('invalid_syntax');
}
@@ -528,15 +524,16 @@ class OneLogin_Saml2_Settings
$security = $settings['security'];
$existsX509 = isset($idp['x509cert']) && !empty($idp['x509cert']);
+ $existsMultiX509Sign = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['signing']) && !empty($idp['x509certMulti']['signing']);
+ $existsMultiX509Enc = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['encryption']) && !empty($idp['x509certMulti']['encryption']);
+
$existsFingerprint = isset($idp['certFingerprint']) && !empty($idp['certFingerprint']);
- if (((isset($security['wantAssertionsSigned']) && $security['wantAssertionsSigned'] == true)
- || (isset($security['wantMessagesSigned']) && $security['wantMessagesSigned'] == true))
- && !($existsX509 || $existsFingerprint)
+ if (!($existsX509 || $existsFingerprint || $existsMultiX509Sign)
) {
$errors[] = 'idp_cert_or_fingerprint_not_found_and_required';
}
if ((isset($security['nameIdEncrypted']) && $security['nameIdEncrypted'] == true)
- && !($existsX509)
+ && !($existsX509 || $existsMultiX509Enc)
) {
$errors[] = 'idp_cert_not_found_and_required';
}
@@ -553,11 +550,9 @@ class OneLogin_Saml2_Settings
*
* @return array $errors Errors found on the SP settings data
*/
- public function checkSPSettings($settings)
+ public function checkSPSettings(array $settings)
{
- assert('is_array($settings)');
-
- if (!is_array($settings) || empty($settings)) {
+ if (empty($settings)) {
return array('invalid_syntax');
}
@@ -700,6 +695,29 @@ class OneLogin_Saml2_Settings
}
/**
+ * Returns the x509 public of the SP that is
+ * planed to be used soon instead the other
+ * public cert
+ *
+ * @return string SP public cert New
+ */
+ public function getSPcertNew()
+ {
+ $cert = null;
+
+ if (isset($this->_sp['x509certNew']) && !empty($this->_sp['x509certNew'])) {
+ $cert = $this->_sp['x509certNew'];
+ } else {
+ $certFile = $this->_paths['cert'].'sp_new.crt';
+
+ if (file_exists($certFile)) {
+ $cert = file_get_contents($certFile);
+ }
+ }
+ return $cert;
+ }
+
+ /**
* Gets the IdP data.
*
* @return array IdP info
@@ -750,20 +768,20 @@ class OneLogin_Saml2_Settings
}
/**
- * Should SAML requests be compressed?
- *
- * @return bool Yes/No as True/False
- */
+ * Should SAML requests be compressed?
+ *
+ * @return bool Yes/No as True/False
+ */
public function shouldCompressRequests()
{
return $this->_compress['requests'];
}
/**
- * Should SAML responses be compressed?
- *
- * @return bool Yes/No as True/False
- */
+ * Should SAML responses be compressed?
+ *
+ * @return bool Yes/No as True/False
+ */
public function shouldCompressResponses()
{
return $this->_compress['responses'];
@@ -772,21 +790,37 @@ class OneLogin_Saml2_Settings
/**
* Gets the SP metadata. The XML representation.
*
+ * @param bool $alwaysPublishEncryptionCert When 'true', the returned
+ * metadata will always include an 'encryption' KeyDescriptor. Otherwise,
+ * the 'encryption' KeyDescriptor will only be included if
+ * $advancedSettings['security']['wantNameIdEncrypted'] or
+ * $advancedSettings['security']['wantAssertionsEncrypted'] are enabled.
+ * @param int|null $validUntil Metadata's valid time
+ * @param int|null $cacheDuration Duration of the cache in seconds
+ *
* @return string SP metadata (xml)
* @throws Exception
- * @throws OneLogin_Saml2_Error
+ * @throws Error
*/
- public function getSPMetadata()
+ public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil = null, $cacheDuration = null)
{
- $metadata = OneLogin_Saml2_Metadata::builder($this->_sp, $this->_security['authnRequestsSigned'], $this->_security['wantAssertionsSigned'], null, null, $this->getContacts(), $this->getOrganization());
+ $metadata = Metadata::builder($this->_sp, $this->_security['authnRequestsSigned'], $this->_security['wantAssertionsSigned'], $validUntil, $cacheDuration, $this->getContacts(), $this->getOrganization());
- $cert = $this->getSPcert();
+ $certNew = $this->getSPcertNew();
+ if (!empty($certNew)) {
+ $metadata = Metadata::addX509KeyDescriptors(
+ $metadata,
+ $certNew,
+ $alwaysPublishEncryptionCert || $this->_security['wantNameIdEncrypted'] || $this->_security['wantAssertionsEncrypted']
+ );
+ }
+ $cert = $this->getSPcert();
if (!empty($cert)) {
- $metadata = OneLogin_Saml2_Metadata::addX509KeyDescriptors(
+ $metadata = Metadata::addX509KeyDescriptors(
$metadata,
$cert,
- $this->_security['wantNameIdEncrypted'] || $this->_security['wantAssertionsEncrypted']
+ $alwaysPublishEncryptionCert || $this->_security['wantNameIdEncrypted'] || $this->_security['wantAssertionsEncrypted']
);
}
@@ -797,25 +831,25 @@ class OneLogin_Saml2_Settings
$certMetadata = $cert;
if (!$keyMetadata) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SP Private key not found.',
- OneLogin_Saml2_Error::PRIVATE_KEY_FILE_NOT_FOUND
+ Error::PRIVATE_KEY_FILE_NOT_FOUND
);
}
if (!$certMetadata) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SP Public cert not found.',
- OneLogin_Saml2_Error::PUBLIC_CERT_FILE_NOT_FOUND
+ Error::PUBLIC_CERT_FILE_NOT_FOUND
);
}
} else {
if (!isset($this->_security['signMetadata']['keyFileName'])
|| !isset($this->_security['signMetadata']['certFileName'])
) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'Invalid Setting: signMetadata value of the sp is not valid',
- OneLogin_Saml2_Error::SETTINGS_INVALID_SYNTAX
+ Error::SETTINGS_INVALID_SYNTAX
);
}
$keyFileName = $this->_security['signMetadata']['keyFileName'];
@@ -824,19 +858,18 @@ class OneLogin_Saml2_Settings
$keyMetadataFile = $this->_paths['cert'].$keyFileName;
$certMetadataFile = $this->_paths['cert'].$certFileName;
-
if (!file_exists($keyMetadataFile)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SP Private key file not found: %s',
- OneLogin_Saml2_Error::PRIVATE_KEY_FILE_NOT_FOUND,
+ Error::PRIVATE_KEY_FILE_NOT_FOUND,
array($keyMetadataFile)
);
}
if (!file_exists($certMetadataFile)) {
- throw new OneLogin_Saml2_Error(
+ throw new Error(
'SP Public cert file not found: %s',
- OneLogin_Saml2_Error::PUBLIC_CERT_FILE_NOT_FOUND,
+ Error::PUBLIC_CERT_FILE_NOT_FOUND,
array($certMetadataFile)
);
}
@@ -846,7 +879,7 @@ class OneLogin_Saml2_Settings
$signatureAlgorithm = $this->_security['signatureAlgorithm'];
$digestAlgorithm = $this->_security['digestAlgorithm'];
- $metadata = OneLogin_Saml2_Metadata::signMetadata($metadata, $keyMetadata, $certMetadata, $signatureAlgorithm, $digestAlgorithm);
+ $metadata = Metadata::signMetadata($metadata, $keyMetadata, $certMetadata, $signatureAlgorithm, $digestAlgorithm);
}
return $metadata;
}
@@ -856,14 +889,16 @@ class OneLogin_Saml2_Settings
*
* @param string $xml Metadata's XML that will be validate
*
- * @return Array The list of found errors
+ * @return array The list of found errors
+ *
+ * @throws Exception
*/
public function validateMetadata($xml)
{
- assert('is_string($xml)');
+ assert(is_string($xml));
$errors = array();
- $res = OneLogin_Saml2_Utils::validateXML($xml, 'saml-schema-metadata-2.0.xsd', $this->_debug);
+ $res = Utils::validateXML($xml, 'saml-schema-metadata-2.0.xsd', $this->_debug);
if (!$res instanceof DOMDocument) {
$errors[] = $res;
} else {
@@ -875,13 +910,13 @@ class OneLogin_Saml2_Settings
$validUntil = $cacheDuration = $expireTime = null;
if ($element->hasAttribute('validUntil')) {
- $validUntil = OneLogin_Saml2_Utils::parseSAML2Time($element->getAttribute('validUntil'));
+ $validUntil = Utils::parseSAML2Time($element->getAttribute('validUntil'));
}
if ($element->hasAttribute('cacheDuration')) {
$cacheDuration = $element->getAttribute('cacheDuration');
}
- $expireTime = OneLogin_Saml2_Utils::getExpireTime($cacheDuration, $validUntil);
+ $expireTime = Utils::getExpireTime($cacheDuration, $validUntil);
if (isset($expireTime) && time() > $expireTime) {
$errors[] = 'expired_xml';
}
@@ -899,7 +934,26 @@ class OneLogin_Saml2_Settings
public function formatIdPCert()
{
if (isset($this->_idp['x509cert'])) {
- $this->_idp['x509cert'] = OneLogin_Saml2_Utils::formatCert($this->_idp['x509cert']);
+ $this->_idp['x509cert'] = Utils::formatCert($this->_idp['x509cert']);
+ }
+ }
+
+ /**
+ * Formats the Multple IdP certs.
+ */
+ public function formatIdPCertMulti()
+ {
+ if (isset($this->_idp['x509certMulti'])) {
+ if (isset($this->_idp['x509certMulti']['signing'])) {
+ foreach ($this->_idp['x509certMulti']['signing'] as $i => $cert) {
+ $this->_idp['x509certMulti']['signing'][$i] = Utils::formatCert($cert);
+ }
+ }
+ if (isset($this->_idp['x509certMulti']['encryption'])) {
+ foreach ($this->_idp['x509certMulti']['encryption'] as $i => $cert) {
+ $this->_idp['x509certMulti']['encryption'][$i] = Utils::formatCert($cert);
+ }
+ }
}
}
@@ -909,7 +963,17 @@ class OneLogin_Saml2_Settings
public function formatSPCert()
{
if (isset($this->_sp['x509cert'])) {
- $this->_sp['x509cert'] = OneLogin_Saml2_Utils::formatCert($this->_sp['x509cert']);
+ $this->_sp['x509cert'] = Utils::formatCert($this->_sp['x509cert']);
+ }
+ }
+
+ /**
+ * Formats the SP cert.
+ */
+ public function formatSPCertNew()
+ {
+ if (isset($this->_sp['x509certNew'])) {
+ $this->_sp['x509certNew'] = Utils::formatCert($this->_sp['x509certNew']);
}
}
@@ -919,7 +983,7 @@ class OneLogin_Saml2_Settings
public function formatSPKey()
{
if (isset($this->_sp['privateKey'])) {
- $this->_sp['privateKey'] = OneLogin_Saml2_Utils::formatPrivateKey($this->_sp['privateKey']);
+ $this->_sp['privateKey'] = Utils::formatPrivateKey($this->_sp['privateKey']);
}
}
@@ -937,10 +1001,12 @@ class OneLogin_Saml2_Settings
* Activates or deactivates the strict mode.
*
* @param bool $value Strict parameter
+ *
+ * @throws Exception
*/
public function setStrict($value)
{
- if (! (is_bool($value))) {
+ if (!is_bool($value)) {
throw new Exception('Invalid value passed to setStrict()');
}
@@ -969,6 +1035,8 @@ class OneLogin_Saml2_Settings
/**
* Set a baseurl value.
+ *
+ * @param string $baseurl Base URL.
*/
public function setBaseURL($baseurl)
{
@@ -988,11 +1056,11 @@ class OneLogin_Saml2_Settings
/**
* Sets the IdP certificate.
*
- * @param string $value IdP certificate
+ * @param string $cert IdP certificate
*/
public function setIdPCert($cert)
{
- $this->_idp['x509cert'] = $cert;
- $this->formatIdPCert();
+ $this->_idp['x509cert'] = $cert;
+ $this->formatIdPCert();
}
}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Utils.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Utils.php
index 6714d9af..f88298af 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Utils.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/Utils.php
@@ -1,12 +1,37 @@
<?php
-
+/**
+ * This file is part of php-saml.
+ *
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
+ */
+
+namespace OneLogin\Saml2;
+
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+use RobRichards\XMLSecLibs\XMLSecurityDSig;
+use RobRichards\XMLSecLibs\XMLSecEnc;
+
+use DOMDocument;
+use DOMElement;
+use DOMNodeList;
+use DomNode;
+use DOMXPath;
+use Exception;
+
/**
* Utils of OneLogin PHP Toolkit
*
* Defines several often used methods
*/
-
-class OneLogin_Saml2_Utils
+class Utils
{
const RESPONSE_SIGNATURE_XPATH = "/samlp:Response/ds:Signature";
const ASSERTION_SIGNATURE_XPATH = "/samlp:Response/saml:Assertion/ds:Signature";
@@ -16,53 +41,30 @@ class OneLogin_Saml2_Utils
*/
private static $_proxyVars = false;
-
/**
- * @var string
+ * @var string|null
*/
private static $_host;
/**
- * @var string
+ * @var string|null
*/
private static $_protocol;
/**
- * @var int
+ * @var string
*/
- private static $_port;
+ private static $_protocolRegex = '@^https?://@i';
/**
- * @var string
+ * @var int|null
*/
- private static $_baseurlpath;
-
+ private static $_port;
/**
- * Translates any string. Accepts args
- *
- * @param string $msg Message to be translated
- * @param array|null $args Arguments
- *
- * @return string $translatedMsg Translated text
+ * @var string|null
*/
- public static function t($msg, $args = array())
- {
- assert('is_string($msg)');
- if (extension_loaded('gettext')) {
- bindtextdomain("phptoolkit", dirname(dirname(dirname(__FILE__))).'/locale');
- textdomain('phptoolkit');
-
- $translatedMsg = gettext($msg);
- } else {
- $translatedMsg = $msg;
- }
- if (!empty($args)) {
- $params = array_merge(array($translatedMsg), $args);
- $translatedMsg = call_user_func_array('sprintf', $params);
- }
- return $translatedMsg;
- }
+ private static $_baseurlpath;
/**
* This function load an XML string in a save way.
@@ -71,14 +73,14 @@ class OneLogin_Saml2_Utils
* @param DOMDocument $dom The document where load the xml.
* @param string $xml The XML string to be loaded.
*
- * @throws Exception
+ * @return DOMDocument|false $dom The result of load the XML at the DOMDocument
*
- * @return DOMDocument $dom The result of load the XML at the DomDocument
+ * @throws Exception
*/
- public static function loadXML($dom, $xml)
+ public static function loadXML(DOMDocument $dom, $xml)
{
- assert('$dom instanceof DOMDocument');
- assert('is_string($xml)');
+ assert($dom instanceof DOMDocument);
+ assert(is_string($xml));
if (strpos($xml, '<!ENTITY') !== false) {
throw new Exception('Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks');
@@ -98,18 +100,20 @@ class OneLogin_Saml2_Utils
/**
* This function attempts to validate an XML string against the specified schema.
*
- * It will parse the string into a DOM document and validate this document against the schema.
+ * It will parse the string into a DOMDocument and validate this document against the schema.
*
* @param string|DOMDocument $xml The XML string or document which should be validated.
* @param string $schema The schema filename which should be used.
* @param bool $debug To disable/enable the debug mode
*
* @return string|DOMDocument $dom string that explains the problem or the DOMDocument
+ *
+ * @throws Exception
*/
public static function validateXML($xml, $schema, $debug = false)
{
- assert('is_string($xml) || $xml instanceof DOMDocument');
- assert('is_string($schema)');
+ assert(is_string($xml) || $xml instanceof DOMDocument);
+ assert(is_string($schema));
libxml_clear_errors();
libxml_use_internal_errors(true);
@@ -124,37 +128,75 @@ class OneLogin_Saml2_Utils
}
}
- $schemaFile = dirname(__FILE__).'/schemas/' . $schema;
+ $schemaFile = __DIR__ . '/schemas/' . $schema;
$oldEntityLoader = libxml_disable_entity_loader(false);
$res = $dom->schemaValidate($schemaFile);
libxml_disable_entity_loader($oldEntityLoader);
if (!$res) {
-
$xmlErrors = libxml_get_errors();
syslog(LOG_INFO, 'Error validating the metadata: '.var_export($xmlErrors, true));
if ($debug) {
foreach ($xmlErrors as $error) {
- echo $error->message."\n";
+ echo htmlentities($error->message)."\n";
}
}
-
return 'invalid_xml';
}
-
return $dom;
}
/**
+ * Import a node tree into a target document
+ * Copy it before a reference node as a sibling
+ * and at the end of the copy remove
+ * the reference node in the target document
+ * As it were 'replacing' it
+ * Leaving nested default namespaces alone
+ * (Standard importNode with deep copy
+ * mangles nested default namespaces)
+ *
+ * The reference node must not be a DomDocument
+ * It CAN be the top element of a document
+ * Returns the copied node in the target document
+ *
+ * @param DomNode $targetNode
+ * @param DomNode $sourceNode
+ * @param bool $recurse
+ * @return DOMNode
+ * @throws Exception
+ */
+ public static function treeCopyReplace(DomNode $targetNode, DomNode $sourceNode, $recurse = false)
+ {
+ if ($targetNode->parentNode === null) {
+ throw new Exception('Illegal argument targetNode. It has no parentNode.');
+ }
+ $clonedNode = $targetNode->ownerDocument->importNode($sourceNode, false);
+ if ($recurse) {
+ $resultNode = $targetNode->appendChild($clonedNode);
+ } else {
+ $resultNode = $targetNode->parentNode->insertBefore($clonedNode, $targetNode);
+ }
+ if ($sourceNode->childNodes !== null) {
+ foreach ($sourceNode->childNodes as $child) {
+ self::treeCopyReplace($resultNode, $child, true);
+ }
+ }
+ if (!$recurse) {
+ $targetNode->parentNode->removeChild($targetNode);
+ }
+ return $resultNode;
+ }
+
+ /**
* Returns a x509 cert (adding header & footer if required).
*
- * @param string $cert A x509 unformated cert
- * @param bool $heads True if we want to include head and footer
+ * @param string $cert A x509 unformated cert
+ * @param bool $heads True if we want to include head and footer
*
* @return string $x509 Formatted cert
*/
-
public static function formatCert($cert, $heads = true)
{
$x509cert = str_replace(array("\x0D", "\r", "\n"), "", $cert);
@@ -174,26 +216,24 @@ class OneLogin_Saml2_Utils
/**
* Returns a private key (adding header & footer if required).
*
- * @param string $key A private key
- * @param bool $heads True if we want to include head and footer
+ * @param string $key A private key
+ * @param bool $heads True if we want to include head and footer
*
* @return string $rsaKey Formatted private key
*/
-
public static function formatPrivateKey($key, $heads = true)
{
$key = str_replace(array("\x0D", "\r", "\n"), "", $key);
if (!empty($key)) {
-
if (strpos($key, '-----BEGIN PRIVATE KEY-----') !== false) {
- $key = OneLogin_Saml2_Utils::get_string_between($key, '-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----');
+ $key = Utils::getStringBetween($key, '-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----');
$key = str_replace(' ', '', $key);
if ($heads) {
$key = "-----BEGIN PRIVATE KEY-----\n".chunk_split($key, 64, "\n")."-----END PRIVATE KEY-----\n";
}
} else if (strpos($key, '-----BEGIN RSA PRIVATE KEY-----') !== false) {
- $key = OneLogin_Saml2_Utils::get_string_between($key, '-----BEGIN RSA PRIVATE KEY-----', '-----END RSA PRIVATE KEY-----');
+ $key = Utils::getStringBetween($key, '-----BEGIN RSA PRIVATE KEY-----', '-----END RSA PRIVATE KEY-----');
$key = str_replace(' ', '', $key);
if ($heads) {
@@ -213,14 +253,14 @@ class OneLogin_Saml2_Utils
/**
* Extracts a substring between 2 marks
*
- * @param string $str The target string
- * @param string $start The initial mark
- * @param string $end The end mark
+ * @param string $str The target string
+ * @param string $start The initial mark
+ * @param string $end The end mark
*
* @return string A substring or an empty string if is not able to find the marks
* or if there is no string between the marks
*/
- public static function get_string_between($str, $start, $end)
+ public static function getStringBetween($str, $start, $end)
{
$str = ' ' . $str;
$ini = strpos($str, $start);
@@ -237,32 +277,35 @@ class OneLogin_Saml2_Utils
/**
* Executes a redirection to the provided url (or return the target url).
*
- * @param string $url The target url
- * @param array $parameters Extra parameters to be passed as part of the url
- * @param bool $stay True if we want to stay (returns the url string) False to redirect
+ * @param string $url The target url
+ * @param array $parameters Extra parameters to be passed as part of the url
+ * @param bool $stay True if we want to stay (returns the url string) False to redirect
*
* @return string|null $url
*
- * @throws OneLogin_Saml2_Error
+ * @throws Error
*/
- public static function redirect($url, $parameters = array(), $stay = false)
+ public static function redirect($url, array $parameters = array(), $stay = false)
{
- assert('is_string($url)');
- assert('is_array($parameters)');
+ assert(is_string($url));
if (substr($url, 0, 1) === '/') {
$url = self::getSelfURLhost() . $url;
}
- /* Verify that the URL is to a http or https site. */
- if (!preg_match('@^https?:\/\/@i', $url)) {
- throw new OneLogin_Saml2_Error(
+ /**
+ * 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);
+ $url = filter_var($url, FILTER_VALIDATE_URL);
+ if ($wrongProtocol || empty($url)) {
+ throw new Error(
'Redirect to invalid URL: ' . $url,
- OneLogin_Saml2_Error::REDIRECT_INVALID_URL
+ Error::REDIRECT_INVALID_URL
);
}
-
/* Add encoded parameters */
if (strpos($url, '?') === false) {
$paramPrefix = '?';
@@ -271,7 +314,6 @@ class OneLogin_Saml2_Utils
}
foreach ($parameters as $name => $value) {
-
if ($value === null) {
$param = urlencode($name);
} else if (is_array($value)) {
@@ -302,14 +344,27 @@ class OneLogin_Saml2_Utils
exit();
}
+ /**
+ * @param $protocolRegex string
+ */
+ public static function setProtocolRegex($protocolRegex)
+ {
+ if (!empty($protocolRegex)) {
+ self::$_protocolRegex = $protocolRegex;
+ }
+ }
+
/**
- * @param $baseurl string The base url to be used when constructing URLs
+ * Set the Base URL value.
+ *
+ * @param string $baseurl The base url to be used when constructing URLs
*/
public static function setBaseURL($baseurl)
{
if (!empty($baseurl)) {
$baseurlpath = '/';
- if (preg_match('#^https?:\/\/([^\/]*)\/?(.*)#i', $baseurl, $matches)) {
+ $matches = array();
+ if (preg_match('#^https?://([^/]*)/?(.*)#i', $baseurl, $matches)) {
if (strpos($baseurl, 'https://') === false) {
self::setSelfProtocol('http');
$port = '80';
@@ -334,11 +389,16 @@ class OneLogin_Saml2_Utils
self::setSelfPort($port);
self::setBaseURLPath($baseurlpath);
}
+ } else {
+ self::$_host = null;
+ self::$_protocol = null;
+ self::$_port = null;
+ self::$_baseurlpath = null;
}
}
/**
- * @param $proxyVars bool Whether to use `X-Forwarded-*` headers to determine port/domain/protocol
+ * @param bool $proxyVars Whether to use `X-Forwarded-*` headers to determine port/domain/protocol
*/
public static function setProxyVars($proxyVars)
{
@@ -346,7 +406,7 @@ class OneLogin_Saml2_Utils
}
/**
- * return bool
+ * @return bool
*/
public static function getProxyVars()
{
@@ -357,7 +417,7 @@ class OneLogin_Saml2_Utils
* Returns the protocol + the current host + the port (if different than
* common ports).
*
- * @return string $url
+ * @return string The URL
*/
public static function getSelfURLhost()
{
@@ -381,7 +441,7 @@ class OneLogin_Saml2_Utils
}
/**
- * @param $host string The host to use when constructing URLs
+ * @param string $host The host to use when constructing URLs
*/
public static function setSelfHost($host)
{
@@ -389,19 +449,21 @@ class OneLogin_Saml2_Utils
}
/**
- * @param $baseurlpath string The baseurl path to use when constructing URLs
+ * @param string $baseurlpath The baseurl path to use when constructing URLs
*/
public static function setBaseURLPath($baseurlpath)
{
- if (empty($baseurlpath) || $baseurlpath == '/') {
- $baseurlpath = '/';
+ if (empty($baseurlpath)) {
+ self::$_baseurlpath = null;
+ } else if ($baseurlpath == '/') {
+ self::$_baseurlpath = '/';
} else {
self::$_baseurlpath = '/' . trim($baseurlpath, '/') . '/';
}
}
/**
- * return string The baseurlpath to be used when constructing URLs
+ * @return string The baseurlpath to be used when constructing URLs
*/
public static function getBaseURLPath()
{
@@ -432,7 +494,7 @@ class OneLogin_Saml2_Utils
}
/**
- * @param $port int The port number to use when constructing URLs
+ * @param int $port The port number to use when constructing URLs
*/
public static function setSelfPort($port)
{
@@ -440,7 +502,7 @@ class OneLogin_Saml2_Utils
}
/**
- * @param $protocol string The protocol to identify as using, usually http or https
+ * @param string $protocol The protocol to identify as using, usually http or https
*/
public static function setSelfProtocol($protocol)
{
@@ -582,10 +644,9 @@ class OneLogin_Saml2_Utils
$requestURI = '';
if (!empty($_SERVER['REQUEST_URI'])) {
$requestURI = $_SERVER['REQUEST_URI'];
- if ($requestURI[0] !== '/') {
- if (preg_match('#^https?:\/\/[^\/]*(\/.*)#i', $requestURI, $matches)) {
- $requestURI = $matches[1];
- }
+ $matches = array();
+ if ($requestURI[0] !== '/' && preg_match('#^https?://[^/]*(/.*)#i', $requestURI, $matches)) {
+ $requestURI = $matches[1];
}
}
@@ -600,6 +661,8 @@ class OneLogin_Saml2_Utils
/**
* Returns the part of the URL with the BaseURLPath.
*
+ * @param string $info Contains path info
+ *
* @return string
*/
protected static function buildWithBaseURLPath($info)
@@ -614,7 +677,7 @@ class OneLogin_Saml2_Utils
if (!empty($extractedInfo)) {
$result .= $extractedInfo;
}
- }
+ }
}
return $result;
}
@@ -626,7 +689,7 @@ class OneLogin_Saml2_Utils
*
* @return string
*/
- public static function extractOriginalQueryParam ($name)
+ public static function extractOriginalQueryParam($name)
{
$index = strpos($_SERVER['QUERY_STRING'], $name.'=');
$substring = substr($_SERVER['QUERY_STRING'], $index + strlen($name) + 1);
@@ -641,23 +704,21 @@ class OneLogin_Saml2_Utils
*/
public static function generateUniqueID()
{
- return 'ONELOGIN_' . sha1(uniqid(mt_rand(), true));
+ return 'ONELOGIN_' . sha1(uniqid((string)mt_rand(), true));
}
/**
* Converts a UNIX timestamp to SAML2 timestamp on the form
* yyyy-mm-ddThh:mm:ss(\.s+)?Z.
*
- * @param string $time The time we should convert (DateTime).
+ * @param string|int $time The time we should convert (DateTime).
*
* @return string $timestamp SAML2 timestamp.
*/
public static function parseTime2SAML($time)
{
- $defaultTimezone = date_default_timezone_get();
- date_default_timezone_set('UTC');
- $timestamp = strftime("%Y-%m-%dT%H:%M:%SZ", $time);
- date_default_timezone_set($defaultTimezone);
+ $date = new \DateTime("@$time", new \DateTimeZone('UTC'));
+ $timestamp = $date->format("Y-m-d\TH:i:s\Z");
return $timestamp;
}
@@ -686,15 +747,15 @@ class OneLogin_Saml2_Utils
}
/* Extract the different components of the time from the
- * matches in the regex. intval will ignore leading zeroes
+ * matches in the regex. int cast will ignore leading zeroes
* in the string.
*/
- $year = intval($matches[1]);
- $month = intval($matches[2]);
- $day = intval($matches[3]);
- $hour = intval($matches[4]);
- $minute = intval($matches[5]);
- $second = intval($matches[6]);
+ $year = (int) $matches[1];
+ $month = (int) $matches[2];
+ $day = (int) $matches[3];
+ $hour = (int) $matches[4];
+ $minute = (int) $matches[5];
+ $second = (int) $matches[6];
/* We use gmmktime because the timestamp will always be given
* in UTC.
@@ -713,14 +774,16 @@ class OneLogin_Saml2_Utils
* duration to. Optional, default to the
* current time.
*
- * @return int|null The new timestamp, after the duration is applied.
+ * @return int The new timestamp, after the duration is applied.
*
* @throws Exception
*/
public static function parseDuration($duration, $timestamp = null)
{
- assert('is_string($duration)');
- assert('is_null($timestamp) || is_int($timestamp)');
+ assert(is_string($duration));
+ assert(is_null($timestamp) || is_int($timestamp));
+
+ $matches = array();
/* Parse the duration. We use a very strict pattern. */
$durationRegEx = '#^(-?)P(?:(?:(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?)|(?:(\\d+)W))$#D';
@@ -760,8 +823,8 @@ class OneLogin_Saml2_Utils
* gmtime function. Instead we use the gmdate function, and split the result.
*/
$yearmonth = explode(':', gmdate('Y:n', $timestamp));
- $year = (int)($yearmonth[0]);
- $month = (int)($yearmonth[1]);
+ $year = (int)$yearmonth[0];
+ $month = (int)$yearmonth[1];
/* Remove the year and month from the timestamp. */
$timestamp -= gmmktime(0, 0, 0, $month, 1, $year);
@@ -795,10 +858,12 @@ class OneLogin_Saml2_Utils
/**
* Compares 2 dates and returns the earliest.
*
- * @param string $cacheDuration The duration, as a string.
- * @param string $validUntil The valid until date, as a string or as a timestamp
+ * @param string|null $cacheDuration The duration, as a string.
+ * @param string|int|null $validUntil The valid until date, as a string or as a timestamp
+ *
+ * @return int|null $expireTime The expiration time.
*
- * @return int $expireTime The expiration time.
+ * @throws Exception
*/
public static function getExpireTime($cacheDuration = null, $validUntil = null)
{
@@ -826,19 +891,22 @@ class OneLogin_Saml2_Utils
/**
* Extracts nodes from the DOMDocument.
*
- * @param DOMDocument $dom The DOMDocument
- * @param string $query Xpath Expresion
- * @param DomElement $context Context Node (DomElement)
+ * @param DOMDocument $dom The DOMDocument
+ * @param string $query \Xpath Expression
+ * @param DOMElement|null $context Context Node (DOMElement)
*
* @return DOMNodeList The queried nodes
*/
- public static function query($dom, $query, $context = null)
+ public static function query(DOMDocument $dom, $query, DOMElement $context = null)
{
$xpath = new DOMXPath($dom);
- $xpath->registerNamespace('samlp', OneLogin_Saml2_Constants::NS_SAMLP);
- $xpath->registerNamespace('saml', OneLogin_Saml2_Constants::NS_SAML);
- $xpath->registerNamespace('ds', OneLogin_Saml2_Constants::NS_DS);
- $xpath->registerNamespace('xenc', OneLogin_Saml2_Constants::NS_XENC);
+ $xpath->registerNamespace('samlp', Constants::NS_SAMLP);
+ $xpath->registerNamespace('saml', Constants::NS_SAML);
+ $xpath->registerNamespace('ds', Constants::NS_DS);
+ $xpath->registerNamespace('xenc', Constants::NS_XENC);
+ $xpath->registerNamespace('xsi', Constants::NS_XSI);
+ $xpath->registerNamespace('xs', Constants::NS_XS);
+ $xpath->registerNamespace('md', Constants::NS_MD);
if (isset($context)) {
$res = $xpath->query($query, $context);
@@ -855,7 +923,7 @@ class OneLogin_Saml2_Utils
*/
public static function isSessionStarted()
{
- if (version_compare(phpversion(), '5.4.0', '>=')) {
+ if (PHP_VERSION_ID >= 50400) {
return session_status() === PHP_SESSION_ACTIVE ? true : false;
} else {
return session_id() === '' ? false : true;
@@ -868,7 +936,7 @@ class OneLogin_Saml2_Utils
public static function deleteLocalSession()
{
- if (OneLogin_Saml2_Utils::isSessionStarted()) {
+ if (Utils::isSessionStarted()) {
session_destroy();
}
@@ -878,42 +946,46 @@ class OneLogin_Saml2_Utils
/**
* Calculates the fingerprint of a x509cert.
*
- * @param string $x509cert x509 cert
+ * @param string $x509cert x509 cert formatted
+ * @param string $alg Algorithm to be used in order to calculate the fingerprint
*
* @return null|string Formatted fingerprint
*/
- public static function calculateX509Fingerprint($x509cert, $alg='sha1')
+ public static function calculateX509Fingerprint($x509cert, $alg = 'sha1')
{
- assert('is_string($x509cert)');
-
- $lines = explode("\n", $x509cert);
+ assert(is_string($x509cert));
+ $arCert = explode("\n", $x509cert);
$data = '';
-
- foreach ($lines as $line) {
- /* Remove '\r' from end of line if present. */
- $line = rtrim($line);
- if ($line === '-----BEGIN CERTIFICATE-----') {
- /* Delete junk from before the certificate. */
- $data = '';
- } elseif ($line === '-----END CERTIFICATE-----') {
- /* Ignore data after the certificate. */
- break;
- } elseif ($line === '-----BEGIN PUBLIC KEY-----' || $line === '-----BEGIN RSA PRIVATE KEY-----') {
- /* This isn't an X509 certificate. */
- return null;
+ $inData = false;
+
+ foreach ($arCert as $curData) {
+ if (! $inData) {
+ if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
+ $inData = true;
+ } elseif ((strncmp($curData, '-----BEGIN PUBLIC KEY', 21) == 0) || (strncmp($curData, '-----BEGIN RSA PRIVATE KEY', 26) == 0)) {
+ /* This isn't an X509 certificate. */
+ return null;
+ }
} else {
- /* Append the current line to the certificate data. */
- $data .= $line;
+ if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
+ break;
+ }
+ $data .= trim($curData);
}
}
+
+ if (empty($data)) {
+ return null;
+ }
+
$decodedData = base64_decode($data);
switch ($alg) {
case 'sha512':
case 'sha384':
case 'sha256':
- $fingerprint = hash($alg, $decodedData, FALSE);
+ $fingerprint = hash($alg, $decodedData, false);
break;
case 'sha1':
default:
@@ -942,12 +1014,15 @@ class OneLogin_Saml2_Utils
*
* @param string $value fingerprint
* @param string $spnq SP Name Qualifier
- * @param string $format SP Format
+ * @param string|null $format SP Format
* @param string|null $cert IdP Public cert to encrypt the nameID
+ * @param string|null $nq IdP Name Qualifier
*
* @return string $nameIDElement DOMElement | XMLSec nameID
+ *
+ * @throws Exception
*/
- public static function generateNameId($value, $spnq, $format, $cert = null)
+ public static function generateNameId($value, $spnq, $format = null, $cert = null, $nq = null)
{
$doc = new DOMDocument();
@@ -956,7 +1031,12 @@ class OneLogin_Saml2_Utils
if (isset($spnq)) {
$nameId->setAttribute('SPNameQualifier', $spnq);
}
- $nameId->setAttribute('Format', $format);
+ if (isset($nq)) {
+ $nameId->setAttribute('NameQualifier', $nq);
+ }
+ if (isset($format)) {
+ $nameId->setAttribute('Format', $format);
+ }
$nameId->appendChild($doc->createTextNode($value));
$doc->appendChild($nameId);
@@ -997,25 +1077,25 @@ class OneLogin_Saml2_Utils
*
* @return array $status The Status, an array with the code and a message.
*
- * @throws Exception
+ * @throws ValidationError
*/
- public static function getStatus($dom)
+ public static function getStatus(DOMDocument $dom)
{
$status = array();
$statusEntry = self::query($dom, '/samlp:Response/samlp:Status');
if ($statusEntry->length != 1) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Missing Status on response",
- OneLogin_Saml2_ValidationError::MISSING_STATUS
+ ValidationError::MISSING_STATUS
);
}
$codeEntry = self::query($dom, '/samlp:Response/samlp:Status/samlp:StatusCode', $statusEntry->item(0));
if ($codeEntry->length != 1) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Missing Status Code on response",
- OneLogin_Saml2_ValidationError::MISSING_STATUS_CODE
+ ValidationError::MISSING_STATUS_CODE
);
}
$code = $codeEntry->item(0)->getAttribute('Value');
@@ -1041,12 +1121,13 @@ class OneLogin_Saml2_Utils
*
* @param DOMElement $encryptedData The encrypted data.
* @param XMLSecurityKey $inputKey The decryption key.
+ * @param bool $formatOutput Format or not the output.
*
* @return DOMElement The decrypted element.
*
- * @throws Exception
+ * @throws ValidationError
*/
- public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey)
+ public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey, $formatOutput = true)
{
$enc = new XMLSecEnc();
@@ -1056,17 +1137,17 @@ class OneLogin_Saml2_Utils
$symmetricKey = $enc->locateKey($encryptedData);
if (!$symmetricKey) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Could not locate key algorithm in encrypted data.',
- OneLogin_Saml2_ValidationError::KEY_ALGORITHM_ERROR
+ ValidationError::KEY_ALGORITHM_ERROR
);
}
$symmetricKeyInfo = $enc->locateKeyInfo($symmetricKey);
if (!$symmetricKeyInfo) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
"Could not locate <dsig:KeyInfo> for the encrypted key.",
- OneLogin_Saml2_ValidationError::KEYINFO_NOT_FOUND_IN_ENCRYPTED_DATA
+ ValidationError::KEYINFO_NOT_FOUND_IN_ENCRYPTED_DATA
);
}
@@ -1079,12 +1160,12 @@ class OneLogin_Saml2_Utils
}
if ($inputKeyAlgo !== $symKeyInfoAlgo) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Algorithm mismatch between input key and key used to encrypt ' .
' the symmetric key for the message. Key was: ' .
var_export($inputKeyAlgo, true) . '; message was: ' .
var_export($symKeyInfoAlgo, true),
- OneLogin_Saml2_ValidationError::KEY_ALGORITHM_ERROR
+ ValidationError::KEY_ALGORITHM_ERROR
);
}
@@ -1093,9 +1174,9 @@ class OneLogin_Saml2_Utils
$keySize = $symmetricKey->getSymmetricKeySize();
if ($keySize === null) {
// To protect against "key oracle" attacks
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Unknown key size for encryption algorithm: ' . var_export($symmetricKey->type, true),
- OneLogin_Saml2_ValidationError::KEY_ALGORITHM_ERROR
+ ValidationError::KEY_ALGORITHM_ERROR
);
}
@@ -1113,15 +1194,15 @@ class OneLogin_Saml2_Utils
$key = str_pad($key, $keySize);
}
}
- $symmetricKey->loadkey($key);
+ $symmetricKey->loadKey($key);
} else {
$symKeyAlgo = $symmetricKey->getAlgorithm();
if ($inputKeyAlgo !== $symKeyAlgo) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Algorithm mismatch between input key and key in message. ' .
'Key was: ' . var_export($inputKeyAlgo, true) . '; message was: ' .
var_export($symKeyAlgo, true),
- OneLogin_Saml2_ValidationError::KEY_ALGORITHM_ERROR
+ ValidationError::KEY_ALGORITHM_ERROR
);
}
$symmetricKey = $inputKey;
@@ -1131,21 +1212,23 @@ class OneLogin_Saml2_Utils
$xml = '<root xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'.$decrypted.'</root>';
$newDoc = new DOMDocument();
- $newDoc->preserveWhiteSpace = false;
- $newDoc->formatOutput = true;
+ if ($formatOutput) {
+ $newDoc->preserveWhiteSpace = false;
+ $newDoc->formatOutput = true;
+ }
$newDoc = self::loadXML($newDoc, $xml);
if (!$newDoc) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Failed to parse decrypted XML.',
- OneLogin_Saml2_ValidationError::INVALID_XML_FORMAT
+ ValidationError::INVALID_XML_FORMAT
);
}
-
+
$decryptedElement = $newDoc->firstChild->firstChild;
if ($decryptedElement === null) {
- throw new OneLogin_Saml2_ValidationError(
+ throw new ValidationError(
'Missing encrypted element.',
- OneLogin_Saml2_ValidationError::MISSING_ENCRYPTED_ELEMENT
+ ValidationError::MISSING_ENCRYPTED_ELEMENT
);
}
@@ -1155,9 +1238,9 @@ class OneLogin_Saml2_Utils
/**
* Converts a XMLSecurityKey to the correct algorithm.
*
- * @param XMLSecurityKey $key The key.
- * @param string $algorithm The desired algorithm.
- * @param string $type Public or private key, defaults to public.
+ * @param XMLSecurityKey $key The key.
+ * @param string $algorithm The desired algorithm.
+ * @param string $type Public or private key, defaults to public.
*
* @return XMLSecurityKey The new key.
*
@@ -1165,12 +1248,18 @@ class OneLogin_Saml2_Utils
*/
public static function castKey(XMLSecurityKey $key, $algorithm, $type = 'public')
{
- assert('is_string($algorithm)');
- assert('$type === "public" || $type === "private"');
+ assert(is_string($algorithm));
+ assert($type === 'public' || $type === 'private');
+
// do nothing if algorithm is already the type of the key
if ($key->type === $algorithm) {
return $key;
}
+
+ if (!Utils::isSupportedSigningAlgorithm($algorithm)) {
+ throw new Exception('Unsupported signing algorithm.');
+ }
+
$keyInfo = openssl_pkey_get_details($key->key);
if ($keyInfo === false) {
throw new Exception('Unable to get key details from XMLSecurityKey.');
@@ -1184,19 +1273,38 @@ class OneLogin_Saml2_Utils
}
/**
+ * @param $algorithm
+ *
+ * @return bool
+ */
+ public static function isSupportedSigningAlgorithm($algorithm)
+ {
+ return in_array(
+ $algorithm,
+ array(
+ XMLSecurityKey::RSA_1_5,
+ XMLSecurityKey::RSA_SHA1,
+ XMLSecurityKey::RSA_SHA256,
+ XMLSecurityKey::RSA_SHA384,
+ XMLSecurityKey::RSA_SHA512
+ )
+ );
+ }
+
+ /**
* Adds signature key and senders certificate to an element (Message or Assertion).
*
- * @param string|DomDocument $xml The element we should sign
- * @param string $key The private key
- * @param string $cert The public
- * @param string $signAlgorithm Signature algorithm method
+ * @param string|DOMDocument $xml The element we should sign
+ * @param string $key The private key
+ * @param string $cert The public
+ * @param string $signAlgorithm Signature algorithm method
* @param string $digestAlgorithm Digest algorithm method
*
* @return string
*
* @throws Exception
*/
- public static function addSign($xml, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA1, $digestAlgorithm = XMLSecurityDSig::SHA1)
+ public static function addSign($xml, $key, $cert, $signAlgorithm = XMLSecurityKey::RSA_SHA256, $digestAlgorithm = XMLSecurityDSig::SHA256)
{
if ($xml instanceof DOMDocument) {
$dom = $xml;
@@ -1252,17 +1360,18 @@ class OneLogin_Saml2_Utils
/**
* Validates a signature (Message or Assertion).
*
- * @param string|DomNode $xml The element we should validate
- * @param string|null $cert The pubic cert
- * @param string|null $fingerprint The fingerprint of the public cert
- * @param string|null $fingerprintalg The algorithm used to get the fingerprint
- * @param string|null $xpath The xpath of the signed element
+ * @param string|\DomNode $xml The element we should validate
+ * @param string|null $cert The pubic cert
+ * @param string|null $fingerprint The fingerprint of the public cert
+ * @param string|null $fingerprintalg The algorithm used to get the fingerprint
+ * @param string|null $xpath The xpath of the signed element
+ * @param array|null $multiCerts Multiple public certs
*
* @return bool
*
* @throws Exception
*/
- public static function validateSign($xml, $cert = null, $fingerprint = null, $fingerprintalg = 'sha1', $xpath=null)
+ public static function validateSign($xml, $cert = null, $fingerprint = null, $fingerprintalg = 'sha1', $xpath = null, $multiCerts = null)
{
if ($xml instanceof DOMDocument) {
$dom = clone $xml;
@@ -1277,7 +1386,7 @@ class OneLogin_Saml2_Utils
$objXMLSecDSig->idKeys = array('ID');
if ($xpath) {
- $nodeset = OneLogin_Saml2_Utils::query($dom, $xpath);
+ $nodeset = Utils::query($dom, $xpath);
$objDSig = $nodeset->item(0);
$objXMLSecDSig->sigNode = $objDSig;
} else {
@@ -1293,6 +1402,10 @@ class OneLogin_Saml2_Utils
throw new Exception('We have no idea about the key');
}
+ if (!Utils::isSupportedSigningAlgorithm($objKey->type)) {
+ throw new Exception('Unsupported signing algorithm.');
+ }
+
$objXMLSecDSig->canonicalizeSignedInfo();
try {
@@ -1303,18 +1416,120 @@ class OneLogin_Saml2_Utils
XMLSecEnc::staticLocateKeyInfo($objKey, $objDSig);
- if (!empty($cert)) {
- $objKey->loadKey($cert, false, true);
- return ($objXMLSecDSig->verify($objKey) === 1);
+ if (!empty($multiCerts)) {
+ // If multiple certs are provided, I may ignore $cert and
+ // $fingerprint provided by the method and just check the
+ // certs on the array
+ $fingerprint = null;
} else {
- $domCert = $objKey->getX509Certificate();
- $domCertFingerprint = OneLogin_Saml2_Utils::calculateX509Fingerprint($domCert, $fingerprintalg);
- if (OneLogin_Saml2_Utils::formatFingerPrint($fingerprint) !== $domCertFingerprint) {
- return false;
+ // else I add the cert to the array in order to check
+ // validate signatures with it and the with it and the
+ // $fingerprint value
+ $multiCerts = array($cert);
+ }
+
+ $valid = false;
+ foreach ($multiCerts as $cert) {
+ if (!empty($cert)) {
+ $objKey->loadKey($cert, false, true);
+ if ($objXMLSecDSig->verify($objKey) === 1) {
+ $valid = true;
+ break;
+ }
} else {
- $objKey->loadKey($domCert, false, true);
- return ($objXMLSecDSig->verify($objKey) === 1);
+ if (!empty($fingerprint)) {
+ $domCert = $objKey->getX509Certificate();
+ $domCertFingerprint = Utils::calculateX509Fingerprint($domCert, $fingerprintalg);
+ if (Utils::formatFingerPrint($fingerprint) == $domCertFingerprint) {
+ $objKey->loadKey($domCert, false, true);
+ if ($objXMLSecDSig->verify($objKey) === 1) {
+ $valid = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return $valid;
+ }
+
+ /**
+ * Validates a binary signature
+ *
+ * @param string $messageType Type of SAML Message
+ * @param array $getData HTTP GET array
+ * @param array $idpData IdP setting data
+ * @param bool $retrieveParametersFromServer Indicates where to get the values in order to validate the Sign, from getData or from $_SERVER
+ *
+ * @return bool
+ *
+ * @throws Exception
+ */
+ public static function validateBinarySign($messageType, $getData, $idpData, $retrieveParametersFromServer = false)
+ {
+ if (!isset($getData['SigAlg'])) {
+ $signAlg = XMLSecurityKey::RSA_SHA1;
+ } else {
+ $signAlg = $getData['SigAlg'];
+ }
+
+ if ($retrieveParametersFromServer) {
+ $signedQuery = $messageType.'='.Utils::extractOriginalQueryParam($messageType);
+ if (isset($getData['RelayState'])) {
+ $signedQuery .= '&RelayState='.Utils::extractOriginalQueryParam('RelayState');
+ }
+ $signedQuery .= '&SigAlg='.Utils::extractOriginalQueryParam('SigAlg');
+ } else {
+ $signedQuery = $messageType.'='.urlencode($getData[$messageType]);
+ if (isset($getData['RelayState'])) {
+ $signedQuery .= '&RelayState='.urlencode($getData['RelayState']);
+ }
+ $signedQuery .= '&SigAlg='.urlencode($signAlg);
+ }
+
+ if ($messageType == "SAMLRequest") {
+ $strMessageType = "Logout Request";
+ } else {
+ $strMessageType = "Logout Response";
+ }
+ $existsMultiX509Sign = isset($idpData['x509certMulti']) && isset($idpData['x509certMulti']['signing']) && !empty($idpData['x509certMulti']['signing']);
+ if ((!isset($idpData['x509cert']) || empty($idpData['x509cert'])) && !$existsMultiX509Sign) {
+ throw new Error(
+ "In order to validate the sign on the ".$strMessageType.", the x509cert of the IdP is required",
+ Error::CERT_NOT_FOUND
+ );
+ }
+
+ if ($existsMultiX509Sign) {
+ $multiCerts = $idpData['x509certMulti']['signing'];
+ } else {
+ $multiCerts = array($idpData['x509cert']);
+ }
+
+ $signatureValid = false;
+ foreach ($multiCerts as $cert) {
+ $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
+ $objKey->loadKey($cert, false, true);
+
+ if ($signAlg != XMLSecurityKey::RSA_SHA1) {
+ try {
+ $objKey = Utils::castKey($objKey, $signAlg, 'public');
+ } catch (Exception $e) {
+ $ex = new ValidationError(
+ "Invalid signAlg in the recieved ".$strMessageType,
+ ValidationError::INVALID_SIGNATURE
+ );
+ if (count($multiCerts) == 1) {
+ throw $ex;
+ }
+ }
+ }
+
+ if ($objKey->verifySignature($signedQuery, base64_decode($_GET['Signature'])) === 1) {
+ $signatureValid = true;
+ break;
}
}
+ return $signatureValid;
}
}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Error.php b/3rdparty/vendor/onelogin/php-saml/src/Saml2/ValidationError.php
index a3d9bd40..889f531c 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/Error.php
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/ValidationError.php
@@ -1,56 +1,31 @@
<?php
-
/**
- * Error class of OneLogin PHP Toolkit
+ * This file is part of php-saml.
*
- * Defines the Error class
+ * (c) OneLogin Inc
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @package OneLogin
+ * @author OneLogin Inc <saml-info@onelogin.com>
+ * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
+ * @link https://github.com/onelogin/php-saml
*/
-class OneLogin_Saml2_Error extends Exception
-{
- // Errors
- const SETTINGS_FILE_NOT_FOUND = 0;
- const SETTINGS_INVALID_SYNTAX = 1;
- const SETTINGS_INVALID = 2;
- const METADATA_SP_INVALID = 3;
- const SP_CERTS_NOT_FOUND = 4;
- // SP_CERTS_NOT_FOUND is deprecated, use CERT_NOT_FOUND instead
- const CERT_NOT_FOUND = 4;
- const REDIRECT_INVALID_URL = 5;
- const PUBLIC_CERT_FILE_NOT_FOUND = 6;
- const PRIVATE_KEY_FILE_NOT_FOUND = 7;
- const SAML_RESPONSE_NOT_FOUND = 8;
- const SAML_LOGOUTMESSAGE_NOT_FOUND = 9;
- const SAML_LOGOUTREQUEST_INVALID = 10;
- const SAML_LOGOUTRESPONSE_INVALID = 11;
- const SAML_SINGLE_LOGOUT_NOT_SUPPORTED = 12;
- const PRIVATE_KEY_NOT_FOUND = 13;
- const UNSUPPORTED_SETTINGS_OBJECT = 14;
-
- /**
- * Constructor
- *
- * @param string $msg Describes the error.
- * @param int $code The code error (defined in the error class).
- * @param array|null $args Arguments used in the message that describes the error.
- */
- public function __construct($msg, $code = 0, $args = null)
- {
- assert('is_string($msg)');
- assert('is_int($code)');
- $message = OneLogin_Saml2_Utils::t($msg, $args);
+namespace OneLogin\Saml2;
- parent::__construct($message, $code);
- }
-}
+use Exception;
/**
+ * ValidationError class of OneLogin PHP Toolkit
+ *
* This class implements another custom Exception handler,
* related to exceptions that happens during validation process.
*/
-class OneLogin_Saml2_ValidationError extends Exception
+class ValidationError extends Exception
{
- # Validation Errors
+ // Validation Errors
const UNSUPPORTED_SAML_VERSION = 0;
const MISSING_ID = 1;
const WRONG_NUMBER_OF_ASSERTIONS = 2;
@@ -109,12 +84,16 @@ class OneLogin_Saml2_ValidationError extends Exception
* @param int $code The code error (defined in the error class).
* @param array|null $args Arguments used in the message that describes the error.
*/
- public function __construct($msg, $code = 0, $args = null)
+ public function __construct($msg, $code = 0, $args = array())
{
- assert('is_string($msg)');
- assert('is_int($code)');
+ assert(is_string($msg));
+ assert(is_int($code));
- $message = OneLogin_Saml2_Utils::t($msg, $args);
+ if (!isset($args)) {
+ $args = array();
+ }
+ $params = array_merge(array($msg), $args);
+ $message = call_user_func_array('sprintf', $params);
parent::__construct($message, $code);
}
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-assertion-2.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-assertion-2.0.xsd
index 2b2f7b80..2b2f7b80 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-assertion-2.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-assertion-2.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-2.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-2.0.xsd
index e4754faf..e4754faf 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-2.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-2.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd
index 8513959a..8513959a 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-authn-context-types-2.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-metadata-2.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-metadata-2.0.xsd
index 86e58f9b..86e58f9b 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-metadata-2.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-metadata-2.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-protocol-2.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-protocol-2.0.xsd
index 7fa6f489..7fa6f489 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/saml-schema-protocol-2.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/saml-schema-protocol-2.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-metadata-attr.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-metadata-attr.xsd
index f23e462a..f23e462a 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-metadata-attr.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-metadata-attr.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-attribute-ext.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-attribute-ext.xsd
index ad309c14..ad309c14 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-attribute-ext.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-attribute-ext.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd
index 3236ffcd..3236ffcd 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-algsupport-v1.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd
index de0b754a..de0b754a 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/sstc-saml-metadata-ui-v1.0.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xenc-schema.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xenc-schema.xsd
index d6d79103..d6d79103 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xenc-schema.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xenc-schema.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xml.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xml.xsd
index aea7d0db..aea7d0db 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xml.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xml.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xmldsig-core-schema.xsd b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xmldsig-core-schema.xsd
index 6f5acc75..6f5acc75 100644
--- a/3rdparty/vendor/onelogin/php-saml/lib/Saml2/schemas/xmldsig-core-schema.xsd
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/schemas/xmldsig-core-schema.xsd
diff --git a/3rdparty/vendor/onelogin/php-saml/src/Saml2/version.json b/3rdparty/vendor/onelogin/php-saml/src/Saml2/version.json
new file mode 100644
index 00000000..ebdf4ece
--- /dev/null
+++ b/3rdparty/vendor/onelogin/php-saml/src/Saml2/version.json
@@ -0,0 +1,6 @@
+{
+ "php-saml": {
+ "version": "3.0.0",
+ "released": "02/11/2018"
+ }
+}
diff --git a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/CHANGELOG.txt b/3rdparty/vendor/robrichards/xmlseclibs/CHANGELOG.txt
index c0b8cfe4..62ea9cdc 100644
--- a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/CHANGELOG.txt
+++ b/3rdparty/vendor/robrichards/xmlseclibs/CHANGELOG.txt
@@ -1,9 +1,70 @@
xmlseclibs.php
-??, ??? ????, 2.0.0
+|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+27, Sep 2018, 3.0.2
+Security Improvements:
+- OpenSSL is now a requirement rather than suggestion. (Slaven Bacelic)
+- Filter input to avoid XPath injection. (Jaime Pérez)
+
+Bug Fixes:
+- Fix missing parentheses (Tim van Dijen)
+
+Improvements:
+- Use strict comparison operator to compare digest values. (Jaime Pérez)
+- Remove call to file_get_contents that doesn't even work. (Jaime Pérez)
+- Document potentially dangerous return value behaviour. (Thijs Kinkhorst)
+
+31, Aug 2017, 3.0.1
+Bug Fixes:
+- Fixed missing () in function call. (Dennis Væversted)
+
+Improvements:
+- Add OneLogin to supported software.
+- Add .gitattributes to remove unneeded files. (Filippo Tessarotto)
+- Fix bug in example code. (Dan Church)
+- Travis: add PHP 7.1, move hhvm to allowed failures. (Thijs Kinkhorst)
+- Drop failing extract-win-cert test (Thijs Kinkhorst). (Thijs Kinkhorst)
+- Add comments to warn about return values of verify(). (Thijs Kinkhorst)
+- Fix tests to properly check return code of verify(). (Thijs Kinkhorst)
+- Restore support for PHP >= 5.4. (Jaime Pérez)
+
+25, May 2017, 3.0.0
+Improvements:
+- Remove use of mcrypt (skymeyer)
+
+08, Sep 2016, 2.0.1
+Bug Fixes:
+- Strip whitespace characters when parsing X509Certificate. fixes #84
+ (klemen.bratec)
+- Certificate 'subject' values can be arrays. fixes #80 (Andreas Stangl)
+- HHVM signing node with ID attribute w/out namespace regenerates ID value.
+ fixes #88 (Milos Tomic)
+
+Improvements:
+- Fix typos and add some PHPDoc Blocks. (gfaust-qb)
+- Update lightSAML link. (Milos Tomic)
+- Update copyright dates.
+
+31, Jul 2015, 2.0.0
+Features:
+- Namespace support. Classes now in the RobRichards\XMLSecLibs\ namespace.
+
+Improvements:
+- Dropped support for PHP 5.2
+
+31, Jul 2015, 1.4.1
+Bug Fixes:
+- Allow for large digest values that may have line breaks. fixes #62
+
Features:
- Support for locating specific signature when multiple exist in
document. (griga3k)
+Improvements:
+- Add optional argument to XMLSecurityDSig to define the prefix to be used,
+ also allowing for null to use no prefix, for the dsig namespace. fixes #13
+- Code cleanup
+- Depreciated XMLSecurityDSig::generate_GUID for XMLSecurityDSig::generateGUID
+
23, Jun 2015, 1.4.0
Features:
- Support for PSR-0 standard.
diff --git a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/LICENSE b/3rdparty/vendor/robrichards/xmlseclibs/LICENSE
index 2a102b76..54b1e87d 100644
--- a/3rdparty/vendor/onelogin/php-saml/extlib/xmlseclibs/LICENSE
+++ b/3rdparty/vendor/robrichards/xmlseclibs/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2007-2013, Robert Richards <rrichards@cdatazone.org>.
+Copyright (c) 2007-2018, Robert Richards <rrichards@cdatazone.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -28,4 +28,4 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/README.md b/3rdparty/vendor/robrichards/xmlseclibs/README.md
new file mode 100644
index 00000000..e8ebd028
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/README.md
@@ -0,0 +1,84 @@
+#xmlseclibs
+
+xmlseclibs is a library written in PHP for working with XML Encryption and Signatures.
+
+The author of xmlseclibs is Rob Richards.
+
+# Branches
+Both the master and the 2.0 branches are actively maintained.
+* master: Removes mcrypt usage requiring 5.4+ (5.6.24+ recommended for security reasons)
+* 2.0: Contains namespace support requiring 5.3+
+* 1.4: Contains auto-loader support while also maintaining backwards compatiblity with the older 1.3 version using the xmlseclibs.php file. Supports PHP 5.2+
+
+# Requirements
+
+xmlseclibs requires PHP version 5.4 or greater. **5.6.24+ recommended for security reasons**
+
+
+## How to Install
+
+Install with [`composer.phar`](http://getcomposer.org).
+
+```sh
+php composer.phar require "robrichards/xmlseclibs"
+```
+
+
+## Use cases
+
+xmlseclibs is being used in many different software.
+
+* [SimpleSAMLPHP](https://github.com/simplesamlphp/simplesamlphp)
+* [LightSAML](https://github.com/lightsaml/lightsaml)
+* [OneLogin](https://github.com/onelogin/php-saml)
+
+## Basic usage
+
+The example below shows basic usage of xmlseclibs, with a SHA-256 signature.
+
+```php
+use RobRichards\XMLSecLibs\XMLSecurityDSig;
+use RobRichards\XMLSecLibs\XMLSecurityKey;
+
+// Load the XML to be signed
+$doc = new DOMDocument();
+$doc->load('./path/to/file/tobesigned.xml');
+
+// Create a new Security object
+$objDSig = new XMLSecurityDSig();
+// Use the c14n exclusive canonicalization
+$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
+// Sign using SHA-256
+$objDSig->addReference(
+ $doc,
+ XMLSecurityDSig::SHA256,
+ array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')
+);
+
+// Create a new (private) Security key
+$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type'=>'private'));
+/*
+If key has a passphrase, set it using
+$objKey->passphrase = '<passphrase>';
+*/
+// Load the private key
+$objKey->loadKey('./path/to/privatekey.pem', TRUE);
+
+// Sign the XML file
+$objDSig->sign($objKey);
+
+// Add the associated public key to the signature
+$objDSig->add509Cert(file_get_contents('./path/to/file/mycert.pem'));
+
+// Append the signature to the XML
+$objDSig->appendSignature($doc->documentElement);
+// Save the signed XML
+$doc->save('./path/to/signed.xml');
+```
+
+## How to Contribute
+
+* [Open Issues](https://github.com/robrichards/xmlseclibs/issues)
+* [Open Pull Requests](https://github.com/robrichards/xmlseclibs/pulls)
+
+Mailing List: https://groups.google.com/forum/#!forum/xmlseclibs
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/composer.json b/3rdparty/vendor/robrichards/xmlseclibs/composer.json
new file mode 100644
index 00000000..22ce7a3e
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/composer.json
@@ -0,0 +1,21 @@
+{
+ "name": "robrichards/xmlseclibs",
+ "description": "A PHP library for XML Security",
+ "license": "BSD-3-Clause",
+ "keywords": [
+ "xml",
+ "xmldsig",
+ "signature",
+ "security"
+ ],
+ "homepage": "https://github.com/robrichards/xmlseclibs",
+ "autoload": {
+ "psr-4": {
+ "RobRichards\\XMLSecLibs\\": "src"
+ }
+ },
+ "require": {
+ "php": ">= 5.4",
+ "ext-openssl": "*"
+ }
+}
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/src/Utils/XPath.php b/3rdparty/vendor/robrichards/xmlseclibs/src/Utils/XPath.php
new file mode 100644
index 00000000..11e51fb6
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/src/Utils/XPath.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace RobRichards\XMLSecLibs\Utils;
+
+class XPath
+{
+ const ALPHANUMERIC = '\w\d';
+ const NUMERIC = '\d';
+ const LETTERS = '\w';
+ const EXTENDED_ALPHANUMERIC = '\w\d\s-_:\.';
+
+ const SINGLE_QUOTE = '\'';
+ const DOUBLE_QUOTE = '"';
+ const ALL_QUOTES = '[\'"]';
+
+
+ /**
+ * Filter an attribute value for save inclusion in an XPath query.
+ *
+ * @param string $value The value to filter.
+ * @param string $quotes The quotes used to delimit the value in the XPath query.
+ *
+ * @return string The filtered attribute value.
+ */
+ public static function filterAttrValue($value, $quotes = self::ALL_QUOTES)
+ {
+ return preg_replace('#'.$quotes.'#', '', $value);
+ }
+
+
+ /**
+ * Filter an attribute name for save inclusion in an XPath query.
+ *
+ * @param string $name The attribute name to filter.
+ * @param mixed $allow The set of characters to allow. Can be one of the constants provided by this class, or a
+ * custom regex excluding the '#' character (used as delimiter).
+ *
+ * @return string The filtered attribute name.
+ */
+ public static function filterAttrName($name, $allow = self::EXTENDED_ALPHANUMERIC)
+ {
+ return preg_replace('#[^'.$allow.']#', '', $name);
+ }
+}
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php
new file mode 100644
index 00000000..8d00fa05
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php
@@ -0,0 +1,510 @@
+<?php
+namespace RobRichards\XMLSecLibs;
+
+use DOMDocument;
+use DOMNode;
+use DOMXPath;
+use Exception;
+use RobRichards\XMLSecLibs\Utils\XPath as XPath;
+
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007-2018, Robert Richards <rrichards@cdatazone.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Robert Richards nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Robert Richards <rrichards@cdatazone.org>
+ * @copyright 2007-2018 Robert Richards <rrichards@cdatazone.org>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ */
+
+class XMLSecEnc
+{
+ const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
+ <xenc:CipherData>
+ <xenc:CipherValue></xenc:CipherValue>
+ </xenc:CipherData>
+</xenc:EncryptedData>";
+
+ const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
+ const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
+ const URI = 3;
+ const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
+
+ /** @var null|DOMDocument */
+ private $encdoc = null;
+
+ /** @var null|DOMNode */
+ private $rawNode = null;
+
+ /** @var null|string */
+ public $type = null;
+
+ /** @var null|DOMElement */
+ public $encKey = null;
+
+ /** @var array */
+ private $references = array();
+
+ public function __construct()
+ {
+ $this->_resetTemplate();
+ }
+
+ private function _resetTemplate()
+ {
+ $this->encdoc = new DOMDocument();
+ $this->encdoc->loadXML(self::template);
+ }
+
+ /**
+ * @param string $name
+ * @param DOMNode $node
+ * @param string $type
+ * @throws Exception
+ */
+ public function addReference($name, $node, $type)
+ {
+ if (! $node instanceOf DOMNode) {
+ throw new Exception('$node is not of type DOMNode');
+ }
+ $curencdoc = $this->encdoc;
+ $this->_resetTemplate();
+ $encdoc = $this->encdoc;
+ $this->encdoc = $curencdoc;
+ $refuri = XMLSecurityDSig::generateGUID();
+ $element = $encdoc->documentElement;
+ $element->setAttribute("Id", $refuri);
+ $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
+ }
+
+ /**
+ * @param DOMNode $node
+ */
+ public function setNode($node)
+ {
+ $this->rawNode = $node;
+ }
+
+ /**
+ * Encrypt the selected node with the given key.
+ *
+ * @param XMLSecurityKey $objKey The encryption key and algorithm.
+ * @param bool $replace Whether the encrypted node should be replaced in the original tree. Default is true.
+ * @throws Exception
+ *
+ * @return DOMElement The <xenc:EncryptedData>-element.
+ */
+ public function encryptNode($objKey, $replace = true)
+ {
+ $data = '';
+ if (empty($this->rawNode)) {
+ throw new Exception('Node to encrypt has not been set');
+ }
+ if (! $objKey instanceof XMLSecurityKey) {
+ throw new Exception('Invalid Key');
+ }
+ $doc = $this->rawNode->ownerDocument;
+ $xPath = new DOMXPath($this->encdoc);
+ $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
+ $cipherValue = $objList->item(0);
+ if ($cipherValue == null) {
+ throw new Exception('Error locating CipherValue element within template');
+ }
+ switch ($this->type) {
+ case (self::Element):
+ $data = $doc->saveXML($this->rawNode);
+ $this->encdoc->documentElement->setAttribute('Type', self::Element);
+ break;
+ case (self::Content):
+ $children = $this->rawNode->childNodes;
+ foreach ($children AS $child) {
+ $data .= $doc->saveXML($child);
+ }
+ $this->encdoc->documentElement->setAttribute('Type', self::Content);
+ break;
+ default:
+ throw new Exception('Type is currently not supported');
+ }
+
+ $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
+ $encMethod->setAttribute('Algorithm', $objKey->getAlgorithm());
+ $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
+
+ $strEncrypt = base64_encode($objKey->encryptData($data));
+ $value = $this->encdoc->createTextNode($strEncrypt);
+ $cipherValue->appendChild($value);
+
+ if ($replace) {
+ switch ($this->type) {
+ case (self::Element):
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+ return $this->encdoc;
+ }
+ $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
+ $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+ return $importEnc;
+ case (self::Content):
+ $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
+ while ($this->rawNode->firstChild) {
+ $this->rawNode->removeChild($this->rawNode->firstChild);
+ }
+ $this->rawNode->appendChild($importEnc);
+ return $importEnc;
+ }
+ } else {
+ return $this->encdoc->documentElement;
+ }
+ }
+
+ /**
+ * @param XMLSecurityKey $objKey
+ * @throws Exception
+ */
+ public function encryptReferences($objKey)
+ {
+ $curRawNode = $this->rawNode;
+ $curType = $this->type;
+ foreach ($this->references AS $name => $reference) {
+ $this->encdoc = $reference["encnode"];
+ $this->rawNode = $reference["node"];
+ $this->type = $reference["type"];
+ try {
+ $encNode = $this->encryptNode($objKey);
+ $this->references[$name]["encnode"] = $encNode;
+ } catch (Exception $e) {
+ $this->rawNode = $curRawNode;
+ $this->type = $curType;
+ throw $e;
+ }
+ }
+ $this->rawNode = $curRawNode;
+ $this->type = $curType;
+ }
+
+ /**
+ * Retrieve the CipherValue text from this encrypted node.
+ *
+ * @throws Exception
+ * @return string|null The Ciphervalue text, or null if no CipherValue is found.
+ */
+ public function getCipherValue()
+ {
+ if (empty($this->rawNode)) {
+ throw new Exception('Node to decrypt has not been set');
+ }
+
+ $doc = $this->rawNode->ownerDocument;
+ $xPath = new DOMXPath($doc);
+ $xPath->registerNamespace('xmlencr', self::XMLENCNS);
+ /* Only handles embedded content right now and not a reference */
+ $query = "./xmlencr:CipherData/xmlencr:CipherValue";
+ $nodeset = $xPath->query($query, $this->rawNode);
+ $node = $nodeset->item(0);
+
+ if (!$node) {
+ return null;
+ }
+
+ return base64_decode($node->nodeValue);
+ }
+
+ /**
+ * Decrypt this encrypted node.
+ *
+ * The behaviour of this function depends on the value of $replace.
+ * If $replace is false, we will return the decrypted data as a string.
+ * If $replace is true, we will insert the decrypted element(s) into the
+ * document, and return the decrypted element(s).
+ *
+ * @param XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
+ * @param boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
+ *
+ * @return string|DOMElement The decrypted data.
+ */
+ public function decryptNode($objKey, $replace=true)
+ {
+ if (! $objKey instanceof XMLSecurityKey) {
+ throw new Exception('Invalid Key');
+ }
+
+ $encryptedData = $this->getCipherValue();
+ if ($encryptedData) {
+ $decrypted = $objKey->decryptData($encryptedData);
+ if ($replace) {
+ switch ($this->type) {
+ case (self::Element):
+ $newdoc = new DOMDocument();
+ $newdoc->loadXML($decrypted);
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+ return $newdoc;
+ }
+ $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, true);
+ $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
+ return $importEnc;
+ case (self::Content):
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
+ $doc = $this->rawNode;
+ } else {
+ $doc = $this->rawNode->ownerDocument;
+ }
+ $newFrag = $doc->createDocumentFragment();
+ $newFrag->appendXML($decrypted);
+ $parent = $this->rawNode->parentNode;
+ $parent->replaceChild($newFrag, $this->rawNode);
+ return $parent;
+ default:
+ return $decrypted;
+ }
+ } else {
+ return $decrypted;
+ }
+ } else {
+ throw new Exception("Cannot locate encrypted data");
+ }
+ }
+
+ /**
+ * Encrypt the XMLSecurityKey
+ *
+ * @param XMLSecurityKey $srcKey
+ * @param XMLSecurityKey $rawKey
+ * @param bool $append
+ * @throws Exception
+ */
+ public function encryptKey($srcKey, $rawKey, $append=true)
+ {
+ if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
+ throw new Exception('Invalid Key');
+ }
+ $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
+ $root = $this->encdoc->documentElement;
+ $encKey = $this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptedKey');
+ if ($append) {
+ $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
+ $keyInfo->appendChild($encKey);
+ } else {
+ $this->encKey = $encKey;
+ }
+ $encMethod = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
+ $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
+ if (! empty($srcKey->name)) {
+ $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
+ $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
+ }
+ $cipherData = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherData'));
+ $cipherData->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherValue', $strEncKey));
+ if (is_array($this->references) && count($this->references) > 0) {
+ $refList = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:ReferenceList'));
+ foreach ($this->references AS $name => $reference) {
+ $refuri = $reference["refuri"];
+ $dataRef = $refList->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:DataReference'));
+ $dataRef->setAttribute("URI", '#' . $refuri);
+ }
+ }
+ return;
+ }
+
+ /**
+ * @param XMLSecurityKey $encKey
+ * @return DOMElement|string
+ * @throws Exception
+ */
+ public function decryptKey($encKey)
+ {
+ if (! $encKey->isEncrypted) {
+ throw new Exception("Key is not Encrypted");
+ }
+ if (empty($encKey->key)) {
+ throw new Exception("Key is missing data to perform the decryption");
+ }
+ return $this->decryptNode($encKey, false);
+ }
+
+ /**
+ * @param DOMDocument $element
+ * @return DOMNode|null
+ */
+ public function locateEncryptedData($element)
+ {
+ if ($element instanceof DOMDocument) {
+ $doc = $element;
+ } else {
+ $doc = $element->ownerDocument;
+ }
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $query = "//*[local-name()='EncryptedData' and namespace-uri()='".self::XMLENCNS."']";
+ $nodeset = $xpath->query($query);
+ return $nodeset->item(0);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the key from the DOM
+ * @param null|DOMNode $node
+ * @return null|XMLSecurityKey
+ */
+ public function locateKey($node=null)
+ {
+ if (empty($node)) {
+ $node = $this->rawNode;
+ }
+ if (! $node instanceof DOMNode) {
+ return null;
+ }
+ if ($doc = $node->ownerDocument) {
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
+ $query = ".//xmlsecenc:EncryptionMethod";
+ $nodeset = $xpath->query($query, $node);
+ if ($encmeth = $nodeset->item(0)) {
+ $attrAlgorithm = $encmeth->getAttribute("Algorithm");
+ try {
+ $objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
+ } catch (Exception $e) {
+ return null;
+ }
+ return $objKey;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param null|XMLSecurityKey $objBaseKey
+ * @param null|DOMNode $node
+ * @return null|XMLSecurityKey
+ * @throws Exception
+ */
+ public static function staticLocateKeyInfo($objBaseKey=null, $node=null)
+ {
+ if (empty($node) || (! $node instanceof DOMNode)) {
+ return null;
+ }
+ $doc = $node->ownerDocument;
+ if (!$doc) {
+ return null;
+ }
+
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
+ $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
+ $query = "./xmlsecdsig:KeyInfo";
+ $nodeset = $xpath->query($query, $node);
+ $encmeth = $nodeset->item(0);
+ if (!$encmeth) {
+ /* No KeyInfo in EncryptedData / EncryptedKey. */
+ return $objBaseKey;
+ }
+
+ foreach ($encmeth->childNodes AS $child) {
+ switch ($child->localName) {
+ case 'KeyName':
+ if (! empty($objBaseKey)) {
+ $objBaseKey->name = $child->nodeValue;
+ }
+ break;
+ case 'KeyValue':
+ foreach ($child->childNodes AS $keyval) {
+ switch ($keyval->localName) {
+ case 'DSAKeyValue':
+ throw new Exception("DSAKeyValue currently not supported");
+ case 'RSAKeyValue':
+ $modulus = null;
+ $exponent = null;
+ if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
+ $modulus = base64_decode($modulusNode->nodeValue);
+ }
+ if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
+ $exponent = base64_decode($exponentNode->nodeValue);
+ }
+ if (empty($modulus) || empty($exponent)) {
+ throw new Exception("Missing Modulus or Exponent");
+ }
+ $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
+ $objBaseKey->loadKey($publicKey);
+ break;
+ }
+ }
+ break;
+ case 'RetrievalMethod':
+ $type = $child->getAttribute('Type');
+ if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
+ /* Unsupported key type. */
+ break;
+ }
+ $uri = $child->getAttribute('URI');
+ if ($uri[0] !== '#') {
+ /* URI not a reference - unsupported. */
+ break;
+ }
+ $id = substr($uri, 1);
+
+ $query = '//xmlsecenc:EncryptedKey[@Id="'.XPath::filterAttrValue($id, XPAth::DOUBLE_QUOTE).'"]';
+ $keyElement = $xpath->query($query)->item(0);
+ if (!$keyElement) {
+ throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
+ }
+
+ return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
+ case 'EncryptedKey':
+ return XMLSecurityKey::fromEncryptedKeyElement($child);
+ case 'X509Data':
+ if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
+ if ($x509certNodes->length > 0) {
+ $x509cert = $x509certNodes->item(0)->textContent;
+ $x509cert = str_replace(array("\r", "\n", " "), "", $x509cert);
+ $x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
+ $objBaseKey->loadKey($x509cert, false, true);
+ }
+ }
+ break;
+ }
+ }
+ return $objBaseKey;
+ }
+
+ /**
+ * @param null|XMLSecurityKey $objBaseKey
+ * @param null|DOMNode $node
+ * @return null|XMLSecurityKey
+ */
+ public function locateKeyInfo($objBaseKey=null, $node=null)
+ {
+ if (empty($node)) {
+ $node = $this->rawNode;
+ }
+ return self::staticLocateKeyInfo($objBaseKey, $node);
+ }
+}
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
new file mode 100644
index 00000000..9eabde07
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
@@ -0,0 +1,1142 @@
+<?php
+namespace RobRichards\XMLSecLibs;
+
+use DOMDocument;
+use DOMElement;
+use DOMNode;
+use DOMXPath;
+use Exception;
+use RobRichards\XMLSecLibs\Utils\XPath as XPath;
+
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007-2018, Robert Richards <rrichards@cdatazone.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Robert Richards nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Robert Richards <rrichards@cdatazone.org>
+ * @copyright 2007-2018 Robert Richards <rrichards@cdatazone.org>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ */
+
+class XMLSecurityDSig
+{
+ const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
+ const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
+ const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
+ const SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384';
+ const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
+ const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
+
+ const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+ const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
+ const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
+ const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
+
+ const template = '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:SignatureMethod />
+ </ds:SignedInfo>
+</ds:Signature>';
+
+ const BASE_TEMPLATE = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <SignedInfo>
+ <SignatureMethod />
+ </SignedInfo>
+</Signature>';
+
+ /** @var DOMElement|null */
+ public $sigNode = null;
+
+ /** @var array */
+ public $idKeys = array();
+
+ /** @var array */
+ public $idNS = array();
+
+ /** @var string|null */
+ private $signedInfo = null;
+
+ /** @var DomXPath|null */
+ private $xPathCtx = null;
+
+ /** @var string|null */
+ private $canonicalMethod = null;
+
+ /** @var string */
+ private $prefix = '';
+
+ /** @var string */
+ private $searchpfx = 'secdsig';
+
+ /**
+ * This variable contains an associative array of validated nodes.
+ * @var array|null
+ */
+ private $validatedNodes = null;
+
+ /**
+ * @param string $prefix
+ */
+ public function __construct($prefix='ds')
+ {
+ $template = self::BASE_TEMPLATE;
+ if (! empty($prefix)) {
+ $this->prefix = $prefix.':';
+ $search = array("<S", "</S", "xmlns=");
+ $replace = array("<$prefix:S", "</$prefix:S", "xmlns:$prefix=");
+ $template = str_replace($search, $replace, $template);
+ }
+ $sigdoc = new DOMDocument();
+ $sigdoc->loadXML($template);
+ $this->sigNode = $sigdoc->documentElement;
+ }
+
+ /**
+ * Reset the XPathObj to null
+ */
+ private function resetXPathObj()
+ {
+ $this->xPathCtx = null;
+ }
+
+ /**
+ * Returns the XPathObj or null if xPathCtx is set and sigNode is empty.
+ *
+ * @return DOMXPath|null
+ */
+ private function getXPathObj()
+ {
+ if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
+ $xpath = new DOMXPath($this->sigNode->ownerDocument);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $this->xPathCtx = $xpath;
+ }
+ return $this->xPathCtx;
+ }
+
+ /**
+ * Generate guid
+ *
+ * @param string $prefix Prefix to use for guid. defaults to pfx
+ *
+ * @return string The generated guid
+ */
+ public static function generateGUID($prefix='pfx')
+ {
+ $uuid = md5(uniqid(mt_rand(), true));
+ $guid = $prefix.substr($uuid, 0, 8)."-".
+ substr($uuid, 8, 4)."-".
+ substr($uuid, 12, 4)."-".
+ substr($uuid, 16, 4)."-".
+ substr($uuid, 20, 12);
+ return $guid;
+ }
+
+ /**
+ * Generate guid
+ *
+ * @param string $prefix Prefix to use for guid. defaults to pfx
+ *
+ * @return string The generated guid
+ *
+ * @deprecated Method deprecated in Release 1.4.1
+ */
+ public static function generate_GUID($prefix='pfx')
+ {
+ return self::generateGUID($prefix);
+ }
+
+ /**
+ * @param DOMDocument $objDoc
+ * @param int $pos
+ * @return DOMNode|null
+ */
+ public function locateSignature($objDoc, $pos=0)
+ {
+ if ($objDoc instanceof DOMDocument) {
+ $doc = $objDoc;
+ } else {
+ $doc = $objDoc->ownerDocument;
+ }
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $query = ".//secdsig:Signature";
+ $nodeset = $xpath->query($query, $objDoc);
+ $this->sigNode = $nodeset->item($pos);
+ return $this->sigNode;
+ }
+ return null;
+ }
+
+ /**
+ * @param string $name
+ * @param null|string $value
+ * @return DOMElement
+ */
+ public function createNewSignNode($name, $value=null)
+ {
+ $doc = $this->sigNode->ownerDocument;
+ if (! is_null($value)) {
+ $node = $doc->createElementNS(self::XMLDSIGNS, $this->prefix.$name, $value);
+ } else {
+ $node = $doc->createElementNS(self::XMLDSIGNS, $this->prefix.$name);
+ }
+ return $node;
+ }
+
+ /**
+ * @param string $method
+ * @throws Exception
+ */
+ public function setCanonicalMethod($method)
+ {
+ switch ($method) {
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+ $this->canonicalMethod = $method;
+ break;
+ default:
+ throw new Exception('Invalid Canonical Method');
+ }
+ if ($xpath = $this->getXPathObj()) {
+ $query = './'.$this->searchpfx.':SignedInfo';
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($sinfo = $nodeset->item(0)) {
+ $query = './'.$this->searchpfx.'CanonicalizationMethod';
+ $nodeset = $xpath->query($query, $sinfo);
+ if (! ($canonNode = $nodeset->item(0))) {
+ $canonNode = $this->createNewSignNode('CanonicalizationMethod');
+ $sinfo->insertBefore($canonNode, $sinfo->firstChild);
+ }
+ $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
+ }
+ }
+ }
+
+ /**
+ * @param DOMNode $node
+ * @param string $canonicalmethod
+ * @param null|array $arXPath
+ * @param null|array $prefixList
+ * @return string
+ */
+ private function canonicalizeData($node, $canonicalmethod, $arXPath=null, $prefixList=null)
+ {
+ $exclusive = false;
+ $withComments = false;
+ switch ($canonicalmethod) {
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+ $exclusive = false;
+ $withComments = false;
+ break;
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+ $withComments = true;
+ break;
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+ $exclusive = true;
+ break;
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+ $exclusive = true;
+ $withComments = true;
+ break;
+ }
+
+ if (is_null($arXPath) && ($node instanceof DOMNode) && ($node->ownerDocument !== null) && $node->isSameNode($node->ownerDocument->documentElement)) {
+ /* Check for any PI or comments as they would have been excluded */
+ $element = $node;
+ while ($refnode = $element->previousSibling) {
+ if ($refnode->nodeType == XML_PI_NODE || (($refnode->nodeType == XML_COMMENT_NODE) && $withComments)) {
+ break;
+ }
+ $element = $refnode;
+ }
+ if ($refnode == null) {
+ $node = $node->ownerDocument;
+ }
+ }
+
+ return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
+ }
+
+ /**
+ * @return null|string
+ */
+ public function canonicalizeSignedInfo()
+ {
+
+ $doc = $this->sigNode->ownerDocument;
+ $canonicalmethod = null;
+ if ($doc) {
+ $xpath = $this->getXPathObj();
+ $query = "./secdsig:SignedInfo";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($signInfoNode = $nodeset->item(0)) {
+ $query = "./secdsig:CanonicalizationMethod";
+ $nodeset = $xpath->query($query, $signInfoNode);
+ if ($canonNode = $nodeset->item(0)) {
+ $canonicalmethod = $canonNode->getAttribute('Algorithm');
+ }
+ $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
+ return $this->signedInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param string $digestAlgorithm
+ * @param string $data
+ * @param bool $encode
+ * @return string
+ * @throws Exception
+ */
+ public function calculateDigest($digestAlgorithm, $data, $encode = true)
+ {
+ switch ($digestAlgorithm) {
+ case self::SHA1:
+ $alg = 'sha1';
+ break;
+ case self::SHA256:
+ $alg = 'sha256';
+ break;
+ case self::SHA384:
+ $alg = 'sha384';
+ break;
+ case self::SHA512:
+ $alg = 'sha512';
+ break;
+ case self::RIPEMD160:
+ $alg = 'ripemd160';
+ break;
+ default:
+ throw new Exception("Cannot validate digest: Unsupported Algorithm <$digestAlgorithm>");
+ }
+
+ $digest = hash($alg, $data, true);
+ if ($encode) {
+ $digest = base64_encode($digest);
+ }
+ return $digest;
+
+ }
+
+ /**
+ * @param $refNode
+ * @param string $data
+ * @return bool
+ */
+ public function validateDigest($refNode, $data)
+ {
+ $xpath = new DOMXPath($refNode->ownerDocument);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $query = 'string(./secdsig:DigestMethod/@Algorithm)';
+ $digestAlgorithm = $xpath->evaluate($query, $refNode);
+ $digValue = $this->calculateDigest($digestAlgorithm, $data, false);
+ $query = 'string(./secdsig:DigestValue)';
+ $digestValue = $xpath->evaluate($query, $refNode);
+ return ($digValue === base64_decode($digestValue));
+ }
+
+ /**
+ * @param $refNode
+ * @param DOMNode $objData
+ * @param bool $includeCommentNodes
+ * @return string
+ */
+ public function processTransforms($refNode, $objData, $includeCommentNodes = true)
+ {
+ $data = $objData;
+ $xpath = new DOMXPath($refNode->ownerDocument);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $query = './secdsig:Transforms/secdsig:Transform';
+ $nodelist = $xpath->query($query, $refNode);
+ $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+ $arXPath = null;
+ $prefixList = null;
+ foreach ($nodelist AS $transform) {
+ $algorithm = $transform->getAttribute("Algorithm");
+ switch ($algorithm) {
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
+
+ if (!$includeCommentNodes) {
+ /* We remove comment nodes by forcing it to use a canonicalization
+ * without comments.
+ */
+ $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
+ } else {
+ $canonicalMethod = $algorithm;
+ }
+
+ $node = $transform->firstChild;
+ while ($node) {
+ if ($node->localName == 'InclusiveNamespaces') {
+ if ($pfx = $node->getAttribute('PrefixList')) {
+ $arpfx = array();
+ $pfxlist = explode(" ", $pfx);
+ foreach ($pfxlist AS $pfx) {
+ $val = trim($pfx);
+ if (! empty($val)) {
+ $arpfx[] = $val;
+ }
+ }
+ if (count($arpfx) > 0) {
+ $prefixList = $arpfx;
+ }
+ }
+ break;
+ }
+ $node = $node->nextSibling;
+ }
+ break;
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
+ if (!$includeCommentNodes) {
+ /* We remove comment nodes by forcing it to use a canonicalization
+ * without comments.
+ */
+ $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
+ } else {
+ $canonicalMethod = $algorithm;
+ }
+
+ break;
+ case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
+ $node = $transform->firstChild;
+ while ($node) {
+ if ($node->localName == 'XPath') {
+ $arXPath = array();
+ $arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
+ $arXpath['namespaces'] = array();
+ $nslist = $xpath->query('./namespace::*', $node);
+ foreach ($nslist AS $nsnode) {
+ if ($nsnode->localName != "xml") {
+ $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
+ }
+ }
+ break;
+ }
+ $node = $node->nextSibling;
+ }
+ break;
+ }
+ }
+ if ($data instanceof DOMNode) {
+ $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
+ }
+ return $data;
+ }
+
+ /**
+ * @param DOMNode $refNode
+ * @return bool
+ */
+ public function processRefNode($refNode)
+ {
+ $dataObject = null;
+
+ /*
+ * Depending on the URI, we may not want to include comments in the result
+ * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
+ */
+ $includeCommentNodes = true;
+
+ if ($uri = $refNode->getAttribute("URI")) {
+ $arUrl = parse_url($uri);
+ if (empty($arUrl['path'])) {
+ if ($identifier = $arUrl['fragment']) {
+
+ /* This reference identifies a node with the given id by using
+ * a URI on the form "#identifier". This should not include comments.
+ */
+ $includeCommentNodes = false;
+
+ $xPath = new DOMXPath($refNode->ownerDocument);
+ if ($this->idNS && is_array($this->idNS)) {
+ foreach ($this->idNS AS $nspf => $ns) {
+ $xPath->registerNamespace($nspf, $ns);
+ }
+ }
+ $iDlist = '@Id="'.XPath::filterAttrValue($identifier, XPath::DOUBLE_QUOTE).'"';
+ if (is_array($this->idKeys)) {
+ foreach ($this->idKeys AS $idKey) {
+ $iDlist .= " or @".XPath::filterAttrName($idKey).'="'.
+ XPATH::filterAttrValue($identifier, XPAth::DOUBLE_QUOTE).'"';
+ }
+ }
+ $query = '//*['.$iDlist.']';
+ $dataObject = $xPath->query($query)->item(0);
+ } else {
+ $dataObject = $refNode->ownerDocument;
+ }
+ }
+ } else {
+ /* This reference identifies the root node with an empty URI. This should
+ * not include comments.
+ */
+ $includeCommentNodes = false;
+
+ $dataObject = $refNode->ownerDocument;
+ }
+ $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
+ if (!$this->validateDigest($refNode, $data)) {
+ return false;
+ }
+
+ if ($dataObject instanceof DOMNode) {
+ /* Add this node to the list of validated nodes. */
+ if (! empty($identifier)) {
+ $this->validatedNodes[$identifier] = $dataObject;
+ } else {
+ $this->validatedNodes[] = $dataObject;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param DOMNode $refNode
+ * @return null
+ */
+ public function getRefNodeID($refNode)
+ {
+ if ($uri = $refNode->getAttribute("URI")) {
+ $arUrl = parse_url($uri);
+ if (empty($arUrl['path'])) {
+ if ($identifier = $arUrl['fragment']) {
+ return $identifier;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return array
+ * @throws Exception
+ */
+ public function getRefIDs()
+ {
+ $refids = array();
+
+ $xpath = $this->getXPathObj();
+ $query = "./secdsig:SignedInfo/secdsig:Reference";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($nodeset->length == 0) {
+ throw new Exception("Reference nodes not found");
+ }
+ foreach ($nodeset AS $refNode) {
+ $refids[] = $this->getRefNodeID($refNode);
+ }
+ return $refids;
+ }
+
+ /**
+ * @return bool
+ * @throws Exception
+ */
+ public function validateReference()
+ {
+ $docElem = $this->sigNode->ownerDocument->documentElement;
+ if (! $docElem->isSameNode($this->sigNode)) {
+ if ($this->sigNode->parentNode != null) {
+ $this->sigNode->parentNode->removeChild($this->sigNode);
+ }
+ }
+ $xpath = $this->getXPathObj();
+ $query = "./secdsig:SignedInfo/secdsig:Reference";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($nodeset->length == 0) {
+ throw new Exception("Reference nodes not found");
+ }
+
+ /* Initialize/reset the list of validated nodes. */
+ $this->validatedNodes = array();
+
+ foreach ($nodeset AS $refNode) {
+ if (! $this->processRefNode($refNode)) {
+ /* Clear the list of validated nodes. */
+ $this->validatedNodes = null;
+ throw new Exception("Reference validation failed");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @param DOMNode $sinfoNode
+ * @param DOMDocument $node
+ * @param string $algorithm
+ * @param null|array $arTransforms
+ * @param null|array $options
+ */
+ private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=null, $options=null)
+ {
+ $prefix = null;
+ $prefix_ns = null;
+ $id_name = 'Id';
+ $overwrite_id = true;
+ $force_uri = false;
+
+ if (is_array($options)) {
+ $prefix = empty($options['prefix']) ? null : $options['prefix'];
+ $prefix_ns = empty($options['prefix_ns']) ? null : $options['prefix_ns'];
+ $id_name = empty($options['id_name']) ? 'Id' : $options['id_name'];
+ $overwrite_id = !isset($options['overwrite']) ? true : (bool) $options['overwrite'];
+ $force_uri = !isset($options['force_uri']) ? false : (bool) $options['force_uri'];
+ }
+
+ $attname = $id_name;
+ if (! empty($prefix)) {
+ $attname = $prefix.':'.$attname;
+ }
+
+ $refNode = $this->createNewSignNode('Reference');
+ $sinfoNode->appendChild($refNode);
+
+ if (! $node instanceof DOMDocument) {
+ $uri = null;
+ if (! $overwrite_id) {
+ $uri = $prefix_ns ? $node->getAttributeNS($prefix_ns, $id_name) : $node->getAttribute($id_name);
+ }
+ if (empty($uri)) {
+ $uri = self::generateGUID();
+ $node->setAttributeNS($prefix_ns, $attname, $uri);
+ }
+ $refNode->setAttribute("URI", '#'.$uri);
+ } elseif ($force_uri) {
+ $refNode->setAttribute("URI", '');
+ }
+
+ $transNodes = $this->createNewSignNode('Transforms');
+ $refNode->appendChild($transNodes);
+
+ if (is_array($arTransforms)) {
+ foreach ($arTransforms AS $transform) {
+ $transNode = $this->createNewSignNode('Transform');
+ $transNodes->appendChild($transNode);
+ if (is_array($transform) &&
+ (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
+ (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
+ $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
+ $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
+ $transNode->appendChild($XPathNode);
+ if (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
+ foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
+ $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
+ }
+ }
+ } else {
+ $transNode->setAttribute('Algorithm', $transform);
+ }
+ }
+ } elseif (! empty($this->canonicalMethod)) {
+ $transNode = $this->createNewSignNode('Transform');
+ $transNodes->appendChild($transNode);
+ $transNode->setAttribute('Algorithm', $this->canonicalMethod);
+ }
+
+ $canonicalData = $this->processTransforms($refNode, $node);
+ $digValue = $this->calculateDigest($algorithm, $canonicalData);
+
+ $digestMethod = $this->createNewSignNode('DigestMethod');
+ $refNode->appendChild($digestMethod);
+ $digestMethod->setAttribute('Algorithm', $algorithm);
+
+ $digestValue = $this->createNewSignNode('DigestValue', $digValue);
+ $refNode->appendChild($digestValue);
+ }
+
+ /**
+ * @param DOMDocument $node
+ * @param string $algorithm
+ * @param null|array $arTransforms
+ * @param null|array $options
+ */
+ public function addReference($node, $algorithm, $arTransforms=null, $options=null)
+ {
+ if ($xpath = $this->getXPathObj()) {
+ $query = "./secdsig:SignedInfo";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($sInfo = $nodeset->item(0)) {
+ $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+ }
+ }
+ }
+
+ /**
+ * @param array $arNodes
+ * @param string $algorithm
+ * @param null|array $arTransforms
+ * @param null|array $options
+ */
+ public function addReferenceList($arNodes, $algorithm, $arTransforms=null, $options=null)
+ {
+ if ($xpath = $this->getXPathObj()) {
+ $query = "./secdsig:SignedInfo";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($sInfo = $nodeset->item(0)) {
+ foreach ($arNodes AS $node) {
+ $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param DOMElement|string $data
+ * @param null|string $mimetype
+ * @param null|string $encoding
+ * @return DOMElement
+ */
+ public function addObject($data, $mimetype=null, $encoding=null)
+ {
+ $objNode = $this->createNewSignNode('Object');
+ $this->sigNode->appendChild($objNode);
+ if (! empty($mimetype)) {
+ $objNode->setAttribute('MimeType', $mimetype);
+ }
+ if (! empty($encoding)) {
+ $objNode->setAttribute('Encoding', $encoding);
+ }
+
+ if ($data instanceof DOMElement) {
+ $newData = $this->sigNode->ownerDocument->importNode($data, true);
+ } else {
+ $newData = $this->sigNode->ownerDocument->createTextNode($data);
+ }
+ $objNode->appendChild($newData);
+
+ return $objNode;
+ }
+
+ /**
+ * @param null|DOMNode $node
+ * @return null|XMLSecurityKey
+ */
+ public function locateKey($node=null)
+ {
+ if (empty($node)) {
+ $node = $this->sigNode;
+ }
+ if (! $node instanceof DOMNode) {
+ return null;
+ }
+ if ($doc = $node->ownerDocument) {
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
+ $algorithm = $xpath->evaluate($query, $node);
+ if ($algorithm) {
+ try {
+ $objKey = new XMLSecurityKey($algorithm, array('type' => 'public'));
+ } catch (Exception $e) {
+ return null;
+ }
+ return $objKey;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns:
+ * Bool when verifying HMAC_SHA1;
+ * Int otherwise, with following meanings:
+ * 1 on succesful signature verification,
+ * 0 when signature verification failed,
+ * -1 if an error occurred during processing.
+ *
+ * NOTE: be very careful when checking the int return value, because in
+ * PHP, -1 will be cast to True when in boolean context. Always check the
+ * return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
+ *
+ * @param XMLSecurityKey $objKey
+ * @return bool|int
+ * @throws Exception
+ */
+ public function verify($objKey)
+ {
+ $doc = $this->sigNode->ownerDocument;
+ $xpath = new DOMXPath($doc);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ $query = "string(./secdsig:SignatureValue)";
+ $sigValue = $xpath->evaluate($query, $this->sigNode);
+ if (empty($sigValue)) {
+ throw new Exception("Unable to locate SignatureValue");
+ }
+ return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
+ }
+
+ /**
+ * @param XMLSecurityKey $objKey
+ * @param string $data
+ * @return mixed|string
+ */
+ public function signData($objKey, $data)
+ {
+ return $objKey->signData($data);
+ }
+
+ /**
+ * @param XMLSecurityKey $objKey
+ * @param null|DOMNode $appendToNode
+ */
+ public function sign($objKey, $appendToNode = null)
+ {
+ // If we have a parent node append it now so C14N properly works
+ if ($appendToNode != null) {
+ $this->resetXPathObj();
+ $this->appendSignature($appendToNode);
+ $this->sigNode = $appendToNode->lastChild;
+ }
+ if ($xpath = $this->getXPathObj()) {
+ $query = "./secdsig:SignedInfo";
+ $nodeset = $xpath->query($query, $this->sigNode);
+ if ($sInfo = $nodeset->item(0)) {
+ $query = "./secdsig:SignatureMethod";
+ $nodeset = $xpath->query($query, $sInfo);
+ $sMethod = $nodeset->item(0);
+ $sMethod->setAttribute('Algorithm', $objKey->type);
+ $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
+ $sigValue = base64_encode($this->signData($objKey, $data));
+ $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
+ if ($infoSibling = $sInfo->nextSibling) {
+ $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
+ } else {
+ $this->sigNode->appendChild($sigValueNode);
+ }
+ }
+ }
+ }
+
+ public function appendCert()
+ {
+
+ }
+
+ /**
+ * @param XMLSecurityKey $objKey
+ * @param null|DOMNode $parent
+ */
+ public function appendKey($objKey, $parent=null)
+ {
+ $objKey->serializeKey($parent);
+ }
+
+
+ /**
+ * This function inserts the signature element.
+ *
+ * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
+ * is specified, the signature element will be inserted as the last element before $beforeNode.
+ *
+ * @param DOMNode $node The node the signature element should be inserted into.
+ * @param DOMNode $beforeNode The node the signature element should be located before.
+ *
+ * @return DOMNode The signature element node
+ */
+ public function insertSignature($node, $beforeNode = null)
+ {
+
+ $document = $node->ownerDocument;
+ $signatureElement = $document->importNode($this->sigNode, true);
+
+ if ($beforeNode == null) {
+ return $node->insertBefore($signatureElement);
+ } else {
+ return $node->insertBefore($signatureElement, $beforeNode);
+ }
+ }
+
+ /**
+ * @param DOMNode $parentNode
+ * @param bool $insertBefore
+ * @return DOMNode
+ */
+ public function appendSignature($parentNode, $insertBefore = false)
+ {
+ $beforeNode = $insertBefore ? $parentNode->firstChild : null;
+ return $this->insertSignature($parentNode, $beforeNode);
+ }
+
+ /**
+ * @param string $cert
+ * @param bool $isPEMFormat
+ * @return string
+ */
+ public static function get509XCert($cert, $isPEMFormat=true)
+ {
+ $certs = self::staticGet509XCerts($cert, $isPEMFormat);
+ if (! empty($certs)) {
+ return $certs[0];
+ }
+ return '';
+ }
+
+ /**
+ * @param string $certs
+ * @param bool $isPEMFormat
+ * @return array
+ */
+ public static function staticGet509XCerts($certs, $isPEMFormat=true)
+ {
+ if ($isPEMFormat) {
+ $data = '';
+ $certlist = array();
+ $arCert = explode("\n", $certs);
+ $inData = false;
+ foreach ($arCert AS $curData) {
+ if (! $inData) {
+ if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
+ $inData = true;
+ }
+ } else {
+ if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
+ $inData = false;
+ $certlist[] = $data;
+ $data = '';
+ continue;
+ }
+ $data .= trim($curData);
+ }
+ }
+ return $certlist;
+ } else {
+ return array($certs);
+ }
+ }
+
+ /**
+ * @param DOMElement $parentRef
+ * @param string $cert
+ * @param bool $isPEMFormat
+ * @param bool $isURL
+ * @param null|DOMXPath $xpath
+ * @param null|array $options
+ * @throws Exception
+ */
+ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $isURL=false, $xpath=null, $options=null)
+ {
+ if ($isURL) {
+ $cert = file_get_contents($cert);
+ }
+ if (! $parentRef instanceof DOMElement) {
+ throw new Exception('Invalid parent Node parameter');
+ }
+ $baseDoc = $parentRef->ownerDocument;
+
+ if (empty($xpath)) {
+ $xpath = new DOMXPath($parentRef->ownerDocument);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ }
+
+ $query = "./secdsig:KeyInfo";
+ $nodeset = $xpath->query($query, $parentRef);
+ $keyInfo = $nodeset->item(0);
+ $dsig_pfx = '';
+ if (! $keyInfo) {
+ $pfx = $parentRef->lookupPrefix(self::XMLDSIGNS);
+ if (! empty($pfx)) {
+ $dsig_pfx = $pfx.":";
+ }
+ $inserted = false;
+ $keyInfo = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'KeyInfo');
+
+ $query = "./secdsig:Object";
+ $nodeset = $xpath->query($query, $parentRef);
+ if ($sObject = $nodeset->item(0)) {
+ $sObject->parentNode->insertBefore($keyInfo, $sObject);
+ $inserted = true;
+ }
+
+ if (! $inserted) {
+ $parentRef->appendChild($keyInfo);
+ }
+ } else {
+ $pfx = $keyInfo->lookupPrefix(self::XMLDSIGNS);
+ if (! empty($pfx)) {
+ $dsig_pfx = $pfx.":";
+ }
+ }
+
+ // Add all certs if there are more than one
+ $certs = self::staticGet509XCerts($cert, $isPEMFormat);
+
+ // Attach X509 data node
+ $x509DataNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509Data');
+ $keyInfo->appendChild($x509DataNode);
+
+ $issuerSerial = false;
+ $subjectName = false;
+ if (is_array($options)) {
+ if (! empty($options['issuerSerial'])) {
+ $issuerSerial = true;
+ }
+ if (! empty($options['subjectName'])) {
+ $subjectName = true;
+ }
+ }
+
+ // Attach all certificate nodes and any additional data
+ foreach ($certs as $X509Cert) {
+ if ($issuerSerial || $subjectName) {
+ if ($certData = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n".chunk_split($X509Cert, 64, "\n")."-----END CERTIFICATE-----\n")) {
+ if ($subjectName && ! empty($certData['subject'])) {
+ if (is_array($certData['subject'])) {
+ $parts = array();
+ foreach ($certData['subject'] AS $key => $value) {
+ if (is_array($value)) {
+ foreach ($value as $valueElement) {
+ array_unshift($parts, "$key=$valueElement");
+ }
+ } else {
+ array_unshift($parts, "$key=$value");
+ }
+ }
+ $subjectNameValue = implode(',', $parts);
+ } else {
+ $subjectNameValue = $certData['issuer'];
+ }
+ $x509SubjectNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509SubjectName', $subjectNameValue);
+ $x509DataNode->appendChild($x509SubjectNode);
+ }
+ if ($issuerSerial && ! empty($certData['issuer']) && ! empty($certData['serialNumber'])) {
+ if (is_array($certData['issuer'])) {
+ $parts = array();
+ foreach ($certData['issuer'] AS $key => $value) {
+ array_unshift($parts, "$key=$value");
+ }
+ $issuerName = implode(',', $parts);
+ } else {
+ $issuerName = $certData['issuer'];
+ }
+
+ $x509IssuerNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509IssuerSerial');
+ $x509DataNode->appendChild($x509IssuerNode);
+
+ $x509Node = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509IssuerName', $issuerName);
+ $x509IssuerNode->appendChild($x509Node);
+ $x509Node = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509SerialNumber', $certData['serialNumber']);
+ $x509IssuerNode->appendChild($x509Node);
+ }
+ }
+
+ }
+ $x509CertNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509Certificate', $X509Cert);
+ $x509DataNode->appendChild($x509CertNode);
+ }
+ }
+
+ /**
+ * @param string $cert
+ * @param bool $isPEMFormat
+ * @param bool $isURL
+ * @param null|array $options
+ */
+ public function add509Cert($cert, $isPEMFormat=true, $isURL=false, $options=null)
+ {
+ if ($xpath = $this->getXPathObj()) {
+ self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath, $options);
+ }
+ }
+
+ /**
+ * This function appends a node to the KeyInfo.
+ *
+ * The KeyInfo element will be created if one does not exist in the document.
+ *
+ * @param DOMNode $node The node to append to the KeyInfo.
+ *
+ * @return DOMNode The KeyInfo element node
+ */
+ public function appendToKeyInfo($node)
+ {
+ $parentRef = $this->sigNode;
+ $baseDoc = $parentRef->ownerDocument;
+
+ $xpath = $this->getXPathObj();
+ if (empty($xpath)) {
+ $xpath = new DOMXPath($parentRef->ownerDocument);
+ $xpath->registerNamespace('secdsig', self::XMLDSIGNS);
+ }
+
+ $query = "./secdsig:KeyInfo";
+ $nodeset = $xpath->query($query, $parentRef);
+ $keyInfo = $nodeset->item(0);
+ if (! $keyInfo) {
+ $dsig_pfx = '';
+ $pfx = $parentRef->lookupPrefix(self::XMLDSIGNS);
+ if (! empty($pfx)) {
+ $dsig_pfx = $pfx.":";
+ }
+ $inserted = false;
+ $keyInfo = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'KeyInfo');
+
+ $query = "./secdsig:Object";
+ $nodeset = $xpath->query($query, $parentRef);
+ if ($sObject = $nodeset->item(0)) {
+ $sObject->parentNode->insertBefore($keyInfo, $sObject);
+ $inserted = true;
+ }
+
+ if (! $inserted) {
+ $parentRef->appendChild($keyInfo);
+ }
+ }
+
+ $keyInfo->appendChild($node);
+
+ return $keyInfo;
+ }
+
+ /**
+ * This function retrieves an associative array of the validated nodes.
+ *
+ * The array will contain the id of the referenced node as the key and the node itself
+ * as the value.
+ *
+ * Returns:
+ * An associative array of validated nodes or null if no nodes have been validated.
+ *
+ * @return array Associative array of validated nodes
+ */
+ public function getValidatedNodes()
+ {
+ return $this->validatedNodes;
+ }
+}
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php
new file mode 100644
index 00000000..5d855bf9
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php
@@ -0,0 +1,749 @@
+<?php
+namespace RobRichards\XMLSecLibs;
+
+use DOMElement;
+use Exception;
+
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007-2018, Robert Richards <rrichards@cdatazone.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Robert Richards nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Robert Richards <rrichards@cdatazone.org>
+ * @copyright 2007-2018 Robert Richards <rrichards@cdatazone.org>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ */
+
+class XMLSecurityKey
+{
+ const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+ const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+ const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+ const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+ const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+ const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+ const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
+ const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+ const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
+ const RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
+ const RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
+ const HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
+
+ /** @var array */
+ private $cryptParams = array();
+
+ /** @var int|string */
+ public $type = 0;
+
+ /** @var mixed|null */
+ public $key = null;
+
+ /** @var string */
+ public $passphrase = "";
+
+ /** @var string|null */
+ public $iv = null;
+
+ /** @var string|null */
+ public $name = null;
+
+ /** @var mixed|null */
+ public $keyChain = null;
+
+ /** @var bool */
+ public $isEncrypted = false;
+
+ /** @var XMLSecEnc|null */
+ public $encryptedCtx = null;
+
+ /** @var mixed|null */
+ public $guid = null;
+
+ /**
+ * This variable contains the certificate as a string if this key represents an X509-certificate.
+ * If this key doesn't represent a certificate, this will be null.
+ * @var string|null
+ */
+ private $x509Certificate = null;
+
+ /**
+ * This variable contains the certificate thumbprint if we have loaded an X509-certificate.
+ * @var string|null
+ */
+ private $X509Thumbprint = null;
+
+ /**
+ * @param string $type
+ * @param null|array $params
+ * @throws Exception
+ */
+ public function __construct($type, $params=null)
+ {
+ switch ($type) {
+ case (self::TRIPLEDES_CBC):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['cipher'] = 'des-ede3-cbc';
+ $this->cryptParams['type'] = 'symmetric';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
+ $this->cryptParams['keysize'] = 24;
+ $this->cryptParams['blocksize'] = 8;
+ break;
+ case (self::AES128_CBC):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['cipher'] = 'aes-128-cbc';
+ $this->cryptParams['type'] = 'symmetric';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
+ $this->cryptParams['keysize'] = 16;
+ $this->cryptParams['blocksize'] = 16;
+ break;
+ case (self::AES192_CBC):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['cipher'] = 'aes-192-cbc';
+ $this->cryptParams['type'] = 'symmetric';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
+ $this->cryptParams['keysize'] = 24;
+ $this->cryptParams['blocksize'] = 16;
+ break;
+ case (self::AES256_CBC):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['cipher'] = 'aes-256-cbc';
+ $this->cryptParams['type'] = 'symmetric';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
+ $this->cryptParams['keysize'] = 32;
+ $this->cryptParams['blocksize'] = 16;
+ break;
+ case (self::RSA_1_5):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::RSA_OAEP_MGF1P):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
+ $this->cryptParams['hash'] = null;
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::RSA_SHA1):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::RSA_SHA256):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+ $this->cryptParams['digest'] = 'SHA256';
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::RSA_SHA384):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+ $this->cryptParams['digest'] = 'SHA384';
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::RSA_SHA512):
+ $this->cryptParams['library'] = 'openssl';
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
+ $this->cryptParams['digest'] = 'SHA512';
+ if (is_array($params) && ! empty($params['type'])) {
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
+ $this->cryptParams['type'] = $params['type'];
+ break;
+ }
+ }
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
+ case (self::HMAC_SHA1):
+ $this->cryptParams['library'] = $type;
+ $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
+ break;
+ default:
+ throw new Exception('Invalid Key Type');
+ }
+ $this->type = $type;
+ }
+
+ /**
+ * Retrieve the key size for the symmetric encryption algorithm..
+ *
+ * If the key size is unknown, or this isn't a symmetric encryption algorithm,
+ * null is returned.
+ *
+ * @return int|null The number of bytes in the key.
+ */
+ public function getSymmetricKeySize()
+ {
+ if (! isset($this->cryptParams['keysize'])) {
+ return null;
+ }
+ return $this->cryptParams['keysize'];
+ }
+
+ /**
+ * Generates a session key using the openssl-extension.
+ * In case of using DES3-CBC the key is checked for a proper parity bits set.
+ * @return string
+ * @throws Exception
+ */
+ public function generateSessionKey()
+ {
+ if (!isset($this->cryptParams['keysize'])) {
+ throw new Exception('Unknown key size for type "' . $this->type . '".');
+ }
+ $keysize = $this->cryptParams['keysize'];
+
+ $key = openssl_random_pseudo_bytes($keysize);
+
+ if ($this->type === self::TRIPLEDES_CBC) {
+ /* Make sure that the generated key has the proper parity bits set.
+ * Mcrypt doesn't care about the parity bits, but others may care.
+ */
+ for ($i = 0; $i < strlen($key); $i++) {
+ $byte = ord($key[$i]) & 0xfe;
+ $parity = 1;
+ for ($j = 1; $j < 8; $j++) {
+ $parity ^= ($byte >> $j) & 1;
+ }
+ $byte |= $parity;
+ $key[$i] = chr($byte);
+ }
+ }
+
+ $this->key = $key;
+ return $key;
+ }
+
+ /**
+ * Get the raw thumbprint of a certificate
+ *
+ * @param string $cert
+ * @return null|string
+ */
+ public static function getRawThumbprint($cert)
+ {
+
+ $arCert = explode("\n", $cert);
+ $data = '';
+ $inData = false;
+
+ foreach ($arCert AS $curData) {
+ if (! $inData) {
+ if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
+ $inData = true;
+ }
+ } else {
+ if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
+ break;
+ }
+ $data .= trim($curData);
+ }
+ }
+
+ if (! empty($data)) {
+ return strtolower(sha1(base64_decode($data)));
+ }
+
+ return null;
+ }
+
+ /**
+ * Loads the given key, or - with isFile set true - the key from the keyfile.
+ *
+ * @param string $key
+ * @param bool $isFile
+ * @param bool $isCert
+ * @throws Exception
+ */
+ public function loadKey($key, $isFile=false, $isCert = false)
+ {
+ if ($isFile) {
+ $this->key = file_get_contents($key);
+ } else {
+ $this->key = $key;
+ }
+ if ($isCert) {
+ $this->key = openssl_x509_read($this->key);
+ openssl_x509_export($this->key, $str_cert);
+ $this->x509Certificate = $str_cert;
+ $this->key = $str_cert;
+ } else {
+ $this->x509Certificate = null;
+ }
+ if ($this->cryptParams['library'] == 'openssl') {
+ switch ($this->cryptParams['type']) {
+ case 'public':
+ if ($isCert) {
+ /* Load the thumbprint if this is an X509 certificate. */
+ $this->X509Thumbprint = self::getRawThumbprint($this->key);
+ }
+ $this->key = openssl_get_publickey($this->key);
+ if (! $this->key) {
+ throw new Exception('Unable to extract public key');
+ }
+ break;
+
+ case 'private':
+ $this->key = openssl_get_privatekey($this->key, $this->passphrase);
+ break;
+
+ case'symmetric':
+ if (strlen($this->key) < $this->cryptParams['keysize']) {
+ throw new Exception('Key must contain at least 25 characters for this cipher');
+ }
+ break;
+
+ default:
+ throw new Exception('Unknown type');
+ }
+ }
+ }
+
+ /**
+ * ISO 10126 Padding
+ *
+ * @param string $data
+ * @param integer $blockSize
+ * @throws Exception
+ * @return string
+ */
+ private function padISO10126($data, $blockSize)
+ {
+ if ($blockSize > 256) {
+ throw new Exception('Block size higher than 256 not allowed');
+ }
+ $padChr = $blockSize - (strlen($data) % $blockSize);
+ $pattern = chr($padChr);
+ return $data . str_repeat($pattern, $padChr);
+ }
+
+ /**
+ * Remove ISO 10126 Padding
+ *
+ * @param string $data
+ * @return string
+ */
+ private function unpadISO10126($data)
+ {
+ $padChr = substr($data, -1);
+ $padLen = ord($padChr);
+ return substr($data, 0, -$padLen);
+ }
+
+ /**
+ * Encrypts the given data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ */
+ private function encryptSymmetric($data)
+ {
+ $this->iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->cryptParams['cipher']));
+ $data = $this->padISO10126($data, $this->cryptParams['blocksize']);
+ $encrypted = openssl_encrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
+ if (false === $encrypted) {
+ throw new Exception('Failure encrypting Data (openssl symmetric) - ' . openssl_error_string());
+ }
+ return $this->iv . $encrypted;
+ }
+
+ /**
+ * Decrypts the given data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ */
+ private function decryptSymmetric($data)
+ {
+ $iv_length = openssl_cipher_iv_length($this->cryptParams['cipher']);
+ $this->iv = substr($data, 0, $iv_length);
+ $data = substr($data, $iv_length);
+ $decrypted = openssl_decrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
+ if (false === $decrypted) {
+ throw new Exception('Failure decrypting Data (openssl symmetric) - ' . openssl_error_string());
+ }
+ return $this->unpadISO10126($decrypted);
+ }
+
+ /**
+ * Encrypts the given public data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ * @throws Exception
+ */
+ private function encryptPublic($data)
+ {
+ if (! openssl_public_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
+ throw new Exception('Failure encrypting Data (openssl public) - ' . openssl_error_string());
+ }
+ return $encrypted;
+ }
+
+ /**
+ * Decrypts the given public data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ * @throws Exception
+ */
+ private function decryptPublic($data)
+ {
+ if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+ throw new Exception('Failure decrypting Data (openssl public) - ' . openssl_error_string());
+ }
+ return $decrypted;
+ }
+
+ /**
+ * Encrypts the given private data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ * @throws Exception
+ */
+ private function encryptPrivate($data)
+ {
+ if (! openssl_private_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
+ throw new Exception('Failure encrypting Data (openssl private) - ' . openssl_error_string());
+ }
+ return $encrypted;
+ }
+
+ /**
+ * Decrypts the given private data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ * @throws Exception
+ */
+ private function decryptPrivate($data)
+ {
+ if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
+ throw new Exception('Failure decrypting Data (openssl private) - ' . openssl_error_string());
+ }
+ return $decrypted;
+ }
+
+ /**
+ * Signs the given data (string) using the openssl-extension
+ *
+ * @param string $data
+ * @return string
+ * @throws Exception
+ */
+ private function signOpenSSL($data)
+ {
+ $algo = OPENSSL_ALGO_SHA1;
+ if (! empty($this->cryptParams['digest'])) {
+ $algo = $this->cryptParams['digest'];
+ }
+ if (! openssl_sign($data, $signature, $this->key, $algo)) {
+ throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
+ }
+ return $signature;
+ }
+
+ /**
+ * Verifies the given data (string) belonging to the given signature using the openssl-extension
+ *
+ * Returns:
+ * 1 on succesful signature verification,
+ * 0 when signature verification failed,
+ * -1 if an error occurred during processing.
+ *
+ * NOTE: be very careful when checking the return value, because in PHP,
+ * -1 will be cast to True when in boolean context. So always check the
+ * return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
+ *
+ * @param string $data
+ * @param string $signature
+ * @return int
+ */
+ private function verifyOpenSSL($data, $signature)
+ {
+ $algo = OPENSSL_ALGO_SHA1;
+ if (! empty($this->cryptParams['digest'])) {
+ $algo = $this->cryptParams['digest'];
+ }
+ return openssl_verify($data, $signature, $this->key, $algo);
+ }
+
+ /**
+ * Encrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
+ *
+ * @param string $data
+ * @return mixed|string
+ */
+ public function encryptData($data)
+ {
+ if ($this->cryptParams['library'] === 'openssl') {
+ switch ($this->cryptParams['type']) {
+ case 'symmetric':
+ return $this->encryptSymmetric($data);
+ case 'public':
+ return $this->encryptPublic($data);
+ case 'private':
+ return $this->encryptPrivate($data);
+ }
+ }
+ }
+
+ /**
+ * Decrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
+ *
+ * @param string $data
+ * @return mixed|string
+ */
+ public function decryptData($data)
+ {
+ if ($this->cryptParams['library'] === 'openssl') {
+ switch ($this->cryptParams['type']) {
+ case 'symmetric':
+ return $this->decryptSymmetric($data);
+ case 'public':
+ return $this->decryptPublic($data);
+ case 'private':
+ return $this->decryptPrivate($data);
+ }
+ }
+ }
+
+ /**
+ * Signs the data (string) using the extension assigned to the type in the constructor.
+ *
+ * @param string $data
+ * @return mixed|string
+ */
+ public function signData($data)
+ {
+ switch ($this->cryptParams['library']) {
+ case 'openssl':
+ return $this->signOpenSSL($data);
+ case (self::HMAC_SHA1):
+ return hash_hmac("sha1", $data, $this->key, true);
+ }
+ }
+
+ /**
+ * Verifies the data (string) against the given signature using the extension assigned to the type in the constructor.
+ *
+ * Returns in case of openSSL:
+ * 1 on succesful signature verification,
+ * 0 when signature verification failed,
+ * -1 if an error occurred during processing.
+ *
+ * NOTE: be very careful when checking the return value, because in PHP,
+ * -1 will be cast to True when in boolean context. So always check the
+ * return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
+ *
+ * @param string $data
+ * @param string $signature
+ * @return bool|int
+ */
+ public function verifySignature($data, $signature)
+ {
+ switch ($this->cryptParams['library']) {
+ case 'openssl':
+ return $this->verifyOpenSSL($data, $signature);
+ case (self::HMAC_SHA1):
+ $expectedSignature = hash_hmac("sha1", $data, $this->key, true);
+ return strcmp($signature, $expectedSignature) == 0;
+ }
+ }
+
+ /**
+ * @deprecated
+ * @see getAlgorithm()
+ * @return mixed
+ */
+ public function getAlgorith()
+ {
+ return $this->getAlgorithm();
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getAlgorithm()
+ {
+ return $this->cryptParams['method'];
+ }
+
+ /**
+ *
+ * @param int $type
+ * @param string $string
+ * @return null|string
+ */
+ public static function makeAsnSegment($type, $string)
+ {
+ switch ($type) {
+ case 0x02:
+ if (ord($string) > 0x7f)
+ $string = chr(0).$string;
+ break;
+ case 0x03:
+ $string = chr(0).$string;
+ break;
+ }
+
+ $length = strlen($string);
+
+ if ($length < 128) {
+ $output = sprintf("%c%c%s", $type, $length, $string);
+ } else if ($length < 0x0100) {
+ $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
+ } else if ($length < 0x010000) {
+ $output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
+ } else {
+ $output = null;
+ }
+ return $output;
+ }
+
+ /**
+ *
+ * Hint: Modulus and Exponent must already be base64 decoded
+ * @param string $modulus
+ * @param string $exponent
+ * @return string
+ */
+ public static function convertRSA($modulus, $exponent)
+ {
+ /* make an ASN publicKeyInfo */
+ $exponentEncoding = self::makeAsnSegment(0x02, $exponent);
+ $modulusEncoding = self::makeAsnSegment(0x02, $modulus);
+ $sequenceEncoding = self::makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
+ $bitstringEncoding = self::makeAsnSegment(0x03, $sequenceEncoding);
+ $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
+ $publicKeyInfo = self::makeAsnSegment(0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
+
+ /* encode the publicKeyInfo in base64 and add PEM brackets */
+ $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
+ $encoding = "-----BEGIN PUBLIC KEY-----\n";
+ $offset = 0;
+ while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
+ $encoding = $encoding.$segment."\n";
+ $offset += 64;
+ }
+ return $encoding."-----END PUBLIC KEY-----\n";
+ }
+
+ /**
+ * @param mixed $parent
+ */
+ public function serializeKey($parent)
+ {
+
+ }
+
+ /**
+ * Retrieve the X509 certificate this key represents.
+ *
+ * Will return the X509 certificate in PEM-format if this key represents
+ * an X509 certificate.
+ *
+ * @return string The X509 certificate or null if this key doesn't represent an X509-certificate.
+ */
+ public function getX509Certificate()
+ {
+ return $this->x509Certificate;
+ }
+
+ /**
+ * Get the thumbprint of this X509 certificate.
+ *
+ * Returns:
+ * The thumbprint as a lowercase 40-character hexadecimal number, or null
+ * if this isn't a X509 certificate.
+ *
+ * @return string Lowercase 40-character hexadecimal number of thumbprint
+ */
+ public function getX509Thumbprint()
+ {
+ return $this->X509Thumbprint;
+ }
+
+
+ /**
+ * Create key from an EncryptedKey-element.
+ *
+ * @param DOMElement $element The EncryptedKey-element.
+ * @throws Exception
+ *
+ * @return XMLSecurityKey The new key.
+ */
+ public static function fromEncryptedKeyElement(DOMElement $element)
+ {
+
+ $objenc = new XMLSecEnc();
+ $objenc->setNode($element);
+ if (! $objKey = $objenc->locateKey()) {
+ throw new Exception("Unable to locate algorithm for this Encrypted Key");
+ }
+ $objKey->isEncrypted = true;
+ $objKey->encryptedCtx = $objenc;
+ XMLSecEnc::staticLocateKeyInfo($objKey, $element);
+ return $objKey;
+ }
+
+}
diff --git a/3rdparty/vendor/robrichards/xmlseclibs/xmlseclibs.php b/3rdparty/vendor/robrichards/xmlseclibs/xmlseclibs.php
new file mode 100644
index 00000000..b5322b8a
--- /dev/null
+++ b/3rdparty/vendor/robrichards/xmlseclibs/xmlseclibs.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * xmlseclibs.php
+ *
+ * Copyright (c) 2007-2018, Robert Richards <rrichards@cdatazone.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Robert Richards nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @author Robert Richards <rrichards@cdatazone.org>
+ * @copyright 2007-2018 Robert Richards <rrichards@cdatazone.org>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version 3.0.2
+ */
+
+$xmlseclibs_srcdir = dirname(__FILE__) . '/src/';
+require $xmlseclibs_srcdir . '/XMLSecurityKey.php';
+require $xmlseclibs_srcdir . '/XMLSecurityDSig.php';
+require $xmlseclibs_srcdir . '/XMLSecEnc.php';
+require $xmlseclibs_srcdir . '/Utils/XPath.php';