friendica-addons/saml/vendor/onelogin/php-saml/src/Saml2/Settings.php

1167 lines
34 KiB
PHP
Raw Normal View History

2021-05-17 03:56:37 +00:00
<?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 DOMDocument;
use Exception;
/**
* Configuration of the OneLogin PHP Toolkit
*/
class Settings
{
/**
* List of paths.
*
* @var array
*/
private $_paths = array();
/**
* @var string
*/
private $_baseurl;
/**
* Strict. If active, PHP Toolkit will reject unsigned or unencrypted messages
* if it expects them signed or encrypted. If not, the messages will be accepted
* and some security issues will be also relaxed.
*
* @var bool
*/
private $_strict = true;
/**
* Activate debug mode
*
* @var bool
*/
private $_debug = false;
/**
* SP data.
*
* @var array
*/
private $_sp = array();
/**
* IdP data.
*
* @var array
*/
private $_idp = array();
/**
* Compression settings that determine
* whether gzip compression should be used.
*
* @var array
*/
private $_compress = array();
/**
* Security Info related to the SP.
*
* @var array
*/
private $_security = array();
/**
* Setting contacts.
*
* @var array
*/
private $_contacts = array();
/**
* Setting organization.
*
* @var array
*/
private $_organization = array();
/**
* Setting errors.
*
* @var array
*/
private $_errors = array();
/**
* Valitate SP data only flag
*
* @var bool
*/
private $_spValidationOnly = false;
/**
* Initializes the settings:
* - Sets the paths of the different folders
* - Loads settings info from settings file or array/object provided
*
* @param array|null $settings SAML Toolkit Settings
* @param bool $spValidationOnly Validate or not the IdP data
*
* @throws Error If any settings parameter is invalid
* @throws Exception If Settings is incorrectly supplied
*/
public function __construct(array $settings = null,bool $spValidationOnly = false)
2021-05-17 03:56:37 +00:00
{
$this->_spValidationOnly = $spValidationOnly;
$this->_loadPaths();
if (!isset($settings)) {
if (!$this->_loadSettingsFromFile()) {
throw new Error(
'Invalid file settings: %s',
Error::SETTINGS_INVALID,
array(implode(', ', $this->_errors))
);
}
$this->_addDefaultValues();
} else {
if (!$this->_loadSettingsFromArray($settings)) {
throw new Error(
'Invalid array settings: %s',
Error::SETTINGS_INVALID,
array(implode(', ', $this->_errors))
);
}
}
$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(__DIR__)) . '/';
$this->_paths = array(
'base' => $basePath,
'config' => $basePath,
'cert' => $basePath.'certs/',
'lib' => __DIR__ . '/',
);
if (defined('ONELOGIN_CUSTOMPATH')) {
$this->_paths['config'] = ONELOGIN_CUSTOMPATH;
$this->_paths['cert'] = ONELOGIN_CUSTOMPATH . 'certs/';
}
}
/**
* Returns base path.
*
* @return string The base toolkit folder path
*/
public function getBasePath()
{
return $this->_paths['base'];
}
/**
* Returns cert path.
*
* @return string The cert folder path
*/
public function getCertPath()
{
return $this->_paths['cert'];
}
/**
* Returns config path.
*
* @return string The config folder path
*/
public function getConfigPath()
{
return $this->_paths['config'];
}
/**
* Returns lib path.
*
* @return string The library folder path
*/
public function getLibPath()
{
return $this->_paths['lib'];
}
/**
* Returns schema path.
*
* @return string The external library folder path
*/
public function getSchemasPath()
{
if (isset($this->_paths['schemas'])) {
return $this->_paths['schemas'];
}
return __DIR__ . '/schemas/';
}
/**
* Set schemas path
*
* @param string $path
* @return $this
*/
public function setSchemasPath($path)
{
$this->_paths['schemas'] = $path;
}
/**
* Loads settings info from a settings Array
*
* @param array $settings SAML Toolkit Settings
*
* @return bool True if the settings info is valid
*/
private function _loadSettingsFromArray(array $settings)
{
if (isset($settings['sp'])) {
$this->_sp = $settings['sp'];
}
if (isset($settings['idp'])) {
$this->_idp = $settings['idp'];
}
$errors = $this->checkSettings($settings);
if (empty($errors)) {
$this->_errors = array();
if (isset($settings['strict'])) {
$this->_strict = $settings['strict'];
}
if (isset($settings['debug'])) {
$this->_debug = $settings['debug'];
}
if (isset($settings['baseurl'])) {
$this->_baseurl = $settings['baseurl'];
}
if (isset($settings['compress'])) {
$this->_compress = $settings['compress'];
}
if (isset($settings['security'])) {
$this->_security = $settings['security'];
}
if (isset($settings['contactPerson'])) {
$this->_contacts = $settings['contactPerson'];
}
if (isset($settings['organization'])) {
$this->_organization = $settings['organization'];
}
$this->_addDefaultValues();
return true;
} else {
$this->_errors = $errors;
return false;
}
}
/**
* Loads settings info from the settings file
*
* @return bool True if the settings info is valid
*
* @throws Error
*
* @suppress PhanUndeclaredVariable
*/
private function _loadSettingsFromFile()
{
$filename = $this->getConfigPath().'settings.php';
if (!file_exists($filename)) {
throw new Error(
'Settings file not found: %s',
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);
}
return $this->_loadSettingsFromArray($settings);
}
/**
* Add default values if the settings info is not complete
*/
private function _addDefaultValues()
{
if (!isset($this->_sp['assertionConsumerService']['binding'])) {
$this->_sp['assertionConsumerService']['binding'] = Constants::BINDING_HTTP_POST;
}
if (isset($this->_sp['singleLogoutService']) && !isset($this->_sp['singleLogoutService']['binding'])) {
$this->_sp['singleLogoutService']['binding'] = Constants::BINDING_HTTP_REDIRECT;
}
if (!isset($this->_compress['requests'])) {
$this->_compress['requests'] = true;
}
if (!isset($this->_compress['responses'])) {
$this->_compress['responses'] = true;
}
// Related to nameID
if (!isset($this->_sp['NameIDFormat'])) {
$this->_sp['NameIDFormat'] = Constants::NAMEID_UNSPECIFIED;
}
if (!isset($this->_security['nameIdEncrypted'])) {
$this->_security['nameIdEncrypted'] = false;
}
if (!isset($this->_security['requestedAuthnContext'])) {
$this->_security['requestedAuthnContext'] = true;
}
// sign provided
if (!isset($this->_security['authnRequestsSigned'])) {
$this->_security['authnRequestsSigned'] = false;
}
if (!isset($this->_security['logoutRequestSigned'])) {
$this->_security['logoutRequestSigned'] = false;
}
if (!isset($this->_security['logoutResponseSigned'])) {
$this->_security['logoutResponseSigned'] = false;
}
if (!isset($this->_security['signMetadata'])) {
$this->_security['signMetadata'] = false;
}
// sign expected
if (!isset($this->_security['wantMessagesSigned'])) {
$this->_security['wantMessagesSigned'] = false;
}
if (!isset($this->_security['wantAssertionsSigned'])) {
$this->_security['wantAssertionsSigned'] = false;
}
// NameID element expected
if (!isset($this->_security['wantNameId'])) {
$this->_security['wantNameId'] = true;
}
// Relax Destination validation
if (!isset($this->_security['relaxDestinationValidation'])) {
$this->_security['relaxDestinationValidation'] = false;
}
// Strict Destination match validation
if (!isset($this->_security['destinationStrictlyMatches'])) {
$this->_security['destinationStrictlyMatches'] = false;
}
// Allow duplicated Attribute Names
if (!isset($this->_security['allowRepeatAttributeName'])) {
$this->_security['allowRepeatAttributeName'] = false;
}
// InResponseTo
if (!isset($this->_security['rejectUnsolicitedResponsesWithInResponseTo'])) {
$this->_security['rejectUnsolicitedResponsesWithInResponseTo'] = false;
}
// encrypt expected
if (!isset($this->_security['wantAssertionsEncrypted'])) {
$this->_security['wantAssertionsEncrypted'] = false;
}
if (!isset($this->_security['wantNameIdEncrypted'])) {
$this->_security['wantNameIdEncrypted'] = false;
}
// XML validation
if (!isset($this->_security['wantXMLValidation'])) {
$this->_security['wantXMLValidation'] = true;
}
// SignatureAlgorithm
if (!isset($this->_security['signatureAlgorithm'])) {
$this->_security['signatureAlgorithm'] = XMLSecurityKey::RSA_SHA256;
}
// DigestAlgorithm
if (!isset($this->_security['digestAlgorithm'])) {
$this->_security['digestAlgorithm'] = XMLSecurityDSig::SHA256;
}
// EncryptionAlgorithm
if (!isset($this->_security['encryption_algorithm'])) {
$this->_security['encryption_algorithm'] = XMLSecurityKey::AES128_CBC;
}
if (!isset($this->_security['lowercaseUrlencoding'])) {
$this->_security['lowercaseUrlencoding'] = false;
}
// Certificates / Private key /Fingerprint
if (!isset($this->_idp['x509cert'])) {
$this->_idp['x509cert'] = '';
}
if (!isset($this->_idp['certFingerprint'])) {
$this->_idp['certFingerprint'] = '';
}
if (!isset($this->_idp['certFingerprintAlgorithm'])) {
$this->_idp['certFingerprintAlgorithm'] = 'sha1';
}
if (!isset($this->_sp['x509cert'])) {
$this->_sp['x509cert'] = '';
}
if (!isset($this->_sp['privateKey'])) {
$this->_sp['privateKey'] = '';
}
}
/**
* Checks the settings info.
*
* @param array $settings Array with settings data
*
* @return array $errors Errors found on the settings data
*/
public function checkSettings(array $settings)
{
if (empty($settings)) {
$errors = array('invalid_syntax');
} else {
$errors = array();
if (!$this->_spValidationOnly) {
$idpErrors = $this->checkIdPSettings($settings);
$errors = array_merge($idpErrors, $errors);
}
$spErrors = $this->checkSPSettings($settings);
$errors = array_merge($spErrors, $errors);
$compressErrors = $this->checkCompressionSettings($settings);
$errors = array_merge($compressErrors, $errors);
}
return $errors;
}
/**
* Checks the compression settings info.
*
* @param array $settings Array with settings data
*
* @return array $errors Errors found on the settings data
*/
public function checkCompressionSettings($settings)
{
$errors = array();
if (isset($settings['compress'])) {
if (!is_array($settings['compress'])) {
$errors[] = "invalid_syntax";
} 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'])
&& $settings['compress']['responses'] !== true
&& $settings['compress']['responses'] !== false
) {
$errors[] = "'compress'=>'responses' values must be true or false.";
}
}
return $errors;
}
/**
* Checks the IdP settings info.
*
* @param array $settings Array with settings data
*
* @return array $errors Errors found on the IdP settings data
*/
public function checkIdPSettings(array $settings)
{
if (empty($settings)) {
return array('invalid_syntax');
}
$errors = array();
if (!isset($settings['idp']) || empty($settings['idp'])) {
$errors[] = 'idp_not_found';
} else {
$idp = $settings['idp'];
if (!isset($idp['entityId']) || empty($idp['entityId'])) {
$errors[] = 'idp_entityId_not_found';
}
if (!isset($idp['singleSignOnService'])
|| !isset($idp['singleSignOnService']['url'])
|| empty($idp['singleSignOnService']['url'])
) {
$errors[] = 'idp_sso_not_found';
} else if (!filter_var($idp['singleSignOnService']['url'], FILTER_VALIDATE_URL)) {
$errors[] = 'idp_sso_url_invalid';
}
if (isset($idp['singleLogoutService'])
&& isset($idp['singleLogoutService']['url'])
&& !empty($idp['singleLogoutService']['url'])
&& !filter_var($idp['singleLogoutService']['url'], FILTER_VALIDATE_URL)
) {
$errors[] = 'idp_slo_url_invalid';
}
if (isset($idp['singleLogoutService'])
&& isset($idp['singleLogoutService']['responseUrl'])
&& !empty($idp['singleLogoutService']['responseUrl'])
&& !filter_var($idp['singleLogoutService']['responseUrl'], FILTER_VALIDATE_URL)
) {
$errors[] = 'idp_slo_response_url_invalid';
}
$existsX509 = isset($idp['x509cert']) && !empty($idp['x509cert']);
$existsMultiX509Sign = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['signing']) && !empty($idp['x509certMulti']['signing']);
$existsFingerprint = isset($idp['certFingerprint']) && !empty($idp['certFingerprint']);
if (!($existsX509 || $existsFingerprint || $existsMultiX509Sign)
) {
$errors[] = 'idp_cert_or_fingerprint_not_found_and_required';
}
if (isset($settings['security'])) {
$existsMultiX509Enc = isset($idp['x509certMulti']) && isset($idp['x509certMulti']['encryption']) && !empty($idp['x509certMulti']['encryption']);
if ((isset($settings['security']['nameIdEncrypted']) && $settings['security']['nameIdEncrypted'] == true)
&& !($existsX509 || $existsMultiX509Enc)
) {
$errors[] = 'idp_cert_not_found_and_required';
}
}
}
return $errors;
}
/**
* Checks the SP settings info.
*
* @param array $settings Array with settings data
*
* @return array $errors Errors found on the SP settings data
*/
public function checkSPSettings(array $settings)
{
if (empty($settings)) {
return array('invalid_syntax');
}
$errors = array();
if (!isset($settings['sp']) || empty($settings['sp'])) {
$errors[] = 'sp_not_found';
} else {
$sp = $settings['sp'];
$security = array();
if (isset($settings['security'])) {
$security = $settings['security'];
}
if (!isset($sp['entityId']) || empty($sp['entityId'])) {
$errors[] = 'sp_entityId_not_found';
}
if (!isset($sp['assertionConsumerService'])
|| !isset($sp['assertionConsumerService']['url'])
|| empty($sp['assertionConsumerService']['url'])
) {
$errors[] = 'sp_acs_not_found';
} else if (!filter_var($sp['assertionConsumerService']['url'], FILTER_VALIDATE_URL)) {
$errors[] = 'sp_acs_url_invalid';
}
if (isset($sp['singleLogoutService'])
&& isset($sp['singleLogoutService']['url'])
&& !filter_var($sp['singleLogoutService']['url'], FILTER_VALIDATE_URL)
) {
$errors[] = 'sp_sls_url_invalid';
}
if (isset($security['signMetadata']) && is_array($security['signMetadata'])) {
if ((!isset($security['signMetadata']['keyFileName'])
|| !isset($security['signMetadata']['certFileName'])) &&
(!isset($security['signMetadata']['privateKey'])
|| !isset($security['signMetadata']['x509cert']))
) {
$errors[] = 'sp_signMetadata_invalid';
}
}
if (((isset($security['authnRequestsSigned']) && $security['authnRequestsSigned'] == true)
|| (isset($security['logoutRequestSigned']) && $security['logoutRequestSigned'] == true)
|| (isset($security['logoutResponseSigned']) && $security['logoutResponseSigned'] == true)
|| (isset($security['wantAssertionsEncrypted']) && $security['wantAssertionsEncrypted'] == true)
|| (isset($security['wantNameIdEncrypted']) && $security['wantNameIdEncrypted'] == true))
&& !$this->checkSPCerts()
) {
$errors[] = 'sp_certs_not_found_and_required';
}
}
if (isset($settings['contactPerson'])) {
$types = array_keys($settings['contactPerson']);
$validTypes = array('technical', 'support', 'administrative', 'billing', 'other');
foreach ($types as $type) {
if (!in_array($type, $validTypes)) {
$errors[] = 'contact_type_invalid';
break;
}
}
foreach ($settings['contactPerson'] as $type => $contact) {
if (!isset($contact['givenName']) || empty($contact['givenName'])
|| !isset($contact['emailAddress']) || empty($contact['emailAddress'])
) {
$errors[] = 'contact_not_enought_data';
break;
}
}
}
if (isset($settings['organization'])) {
foreach ($settings['organization'] as $organization) {
if (!isset($organization['name']) || empty($organization['name'])
|| !isset($organization['displayname']) || empty($organization['displayname'])
|| !isset($organization['url']) || empty($organization['url'])
) {
$errors[] = 'organization_not_enought_data';
break;
}
}
}
return $errors;
}
/**
* Checks if the x509 certs of the SP exists and are valid.
*
* @return bool
*/
public function checkSPCerts()
{
$key = $this->getSPkey();
$cert = $this->getSPcert();
return (!empty($key) && !empty($cert));
}
/**
* Returns the x509 private key of the SP.
*
* @return string SP private key
*/
public function getSPkey()
{
$key = null;
if (isset($this->_sp['privateKey']) && !empty($this->_sp['privateKey'])) {
$key = $this->_sp['privateKey'];
} else {
$keyFile = $this->_paths['cert'].'sp.key';
if (file_exists($keyFile)) {
$key = file_get_contents($keyFile);
}
}
return $key;
}
/**
* Returns the x509 public cert of the SP.
*
* @return string SP public cert
*/
public function getSPcert()
{
$cert = null;
if (isset($this->_sp['x509cert']) && !empty($this->_sp['x509cert'])) {
$cert = $this->_sp['x509cert'];
} else {
$certFile = $this->_paths['cert'].'sp.crt';
if (file_exists($certFile)) {
$cert = file_get_contents($certFile);
}
}
return $cert;
}
/**
* 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
*/
public function getIdPData()
{
return $this->_idp;
}
/**
* Gets the SP data.
*
* @return array SP info
*/
public function getSPData()
{
return $this->_sp;
}
/**
* Gets security data.
*
* @return array SP info
*/
public function getSecurityData()
{
return $this->_security;
}
/**
* Gets contact data.
*
* @return array SP info
*/
public function getContacts()
{
return $this->_contacts;
}
/**
* Gets organization data.
*
* @return array SP info
*/
public function getOrganization()
{
return $this->_organization;
}
/**
* 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
*/
public function shouldCompressResponses()
{
return $this->_compress['responses'];
}
/**
* Gets the IdP SSO url.
*
* @return string|null The url of the IdP Single Sign On Service
*/
public function getIdPSSOUrl()
{
$ssoUrl = null;
if (isset($this->_idp['singleSignOnService']) && isset($this->_idp['singleSignOnService']['url'])) {
$ssoUrl = $this->_idp['singleSignOnService']['url'];
}
return $ssoUrl;
}
/**
* Gets the IdP SLO url.
*
* @return string|null The request url of the IdP Single Logout Service
*/
public function getIdPSLOUrl()
{
$sloUrl = null;
if (isset($this->_idp['singleLogoutService']) && isset($this->_idp['singleLogoutService']['url'])) {
$sloUrl = $this->_idp['singleLogoutService']['url'];
}
return $sloUrl;
}
/**
* Gets the IdP SLO response url.
*
* @return string|null The response url of the IdP Single Logout Service
*/
public function getIdPSLOResponseUrl()
{
if (isset($this->_idp['singleLogoutService']) && isset($this->_idp['singleLogoutService']['responseUrl'])) {
return $this->_idp['singleLogoutService']['responseUrl'];
}
return $this->getIdPSLOUrl();
}
/**
* 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 Error
*/
public function getSPMetadata($alwaysPublishEncryptionCert = false, $validUntil = null, $cacheDuration = null)
{
$metadata = Metadata::builder($this->_sp, $this->_security['authnRequestsSigned'], $this->_security['wantAssertionsSigned'], $validUntil, $cacheDuration, $this->getContacts(), $this->getOrganization());
$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 = Metadata::addX509KeyDescriptors(
$metadata,
$cert,
$alwaysPublishEncryptionCert || $this->_security['wantNameIdEncrypted'] || $this->_security['wantAssertionsEncrypted']
);
}
//Sign Metadata
if (isset($this->_security['signMetadata']) && $this->_security['signMetadata'] != false) {
if ($this->_security['signMetadata'] === true) {
$keyMetadata = $this->getSPkey();
$certMetadata = $cert;
if (!$keyMetadata) {
throw new Error(
'SP Private key not found.',
Error::PRIVATE_KEY_FILE_NOT_FOUND
);
}
if (!$certMetadata) {
throw new Error(
'SP Public cert not found.',
Error::PUBLIC_CERT_FILE_NOT_FOUND
);
}
} else if (isset($this->_security['signMetadata']['keyFileName']) &&
isset($this->_security['signMetadata']['certFileName'])) {
$keyFileName = $this->_security['signMetadata']['keyFileName'];
$certFileName = $this->_security['signMetadata']['certFileName'];
$keyMetadataFile = $this->_paths['cert'].$keyFileName;
$certMetadataFile = $this->_paths['cert'].$certFileName;
if (!file_exists($keyMetadataFile)) {
throw new Error(
'SP Private key file not found: %s',
Error::PRIVATE_KEY_FILE_NOT_FOUND,
array($keyMetadataFile)
);
}
if (!file_exists($certMetadataFile)) {
throw new Error(
'SP Public cert file not found: %s',
Error::PUBLIC_CERT_FILE_NOT_FOUND,
array($certMetadataFile)
);
}
$keyMetadata = file_get_contents($keyMetadataFile);
$certMetadata = file_get_contents($certMetadataFile);
} else if (isset($this->_security['signMetadata']['privateKey']) &&
isset($this->_security['signMetadata']['x509cert'])) {
$keyMetadata = Utils::formatPrivateKey($this->_security['signMetadata']['privateKey']);
$certMetadata = Utils::formatCert($this->_security['signMetadata']['x509cert']);
if (!$keyMetadata) {
throw new Error(
'Private key not found.',
Error::PRIVATE_KEY_FILE_NOT_FOUND
);
}
if (!$certMetadata) {
throw new Error(
'Public cert not found.',
Error::PUBLIC_CERT_FILE_NOT_FOUND
);
}
} else {
throw new Error(
'Invalid Setting: signMetadata value of the sp is not valid',
Error::SETTINGS_INVALID_SYNTAX
);
}
$signatureAlgorithm = $this->_security['signatureAlgorithm'];
$digestAlgorithm = $this->_security['digestAlgorithm'];
$metadata = Metadata::signMetadata($metadata, $keyMetadata, $certMetadata, $signatureAlgorithm, $digestAlgorithm);
}
return $metadata;
}
/**
* Validates an XML SP Metadata.
*
* @param string $xml Metadata's XML that will be validate
*
* @return array The list of found errors
*
* @throws Exception
*/
public function validateMetadata($xml)
{
assert(is_string($xml));
$errors = array();
$res = Utils::validateXML($xml, 'saml-schema-metadata-2.0.xsd', $this->_debug, $this->getSchemasPath());
if (!$res instanceof DOMDocument) {
$errors[] = $res;
} else {
$dom = $res;
$element = $dom->documentElement;
if ($element->tagName !== 'md:EntityDescriptor') {
$errors[] = 'noEntityDescriptor_xml';
} else {
$validUntil = $cacheDuration = $expireTime = null;
if ($element->hasAttribute('validUntil')) {
$validUntil = Utils::parseSAML2Time($element->getAttribute('validUntil'));
}
if ($element->hasAttribute('cacheDuration')) {
$cacheDuration = $element->getAttribute('cacheDuration');
}
$expireTime = Utils::getExpireTime($cacheDuration, $validUntil);
if (isset($expireTime) && time() > $expireTime) {
$errors[] = 'expired_xml';
}
}
}
// TODO: Support Metadata Sign Validation
return $errors;
}
/**
* Formats the IdP cert.
*/
public function formatIdPCert()
{
if (isset($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);
}
}
}
}
/**
* Formats the SP cert.
*/
public function formatSPCert()
{
if (isset($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']);
}
}
/**
* Formats the SP private key.
*/
public function formatSPKey()
{
if (isset($this->_sp['privateKey'])) {
$this->_sp['privateKey'] = Utils::formatPrivateKey($this->_sp['privateKey']);
}
}
/**
* Returns an array with the errors, the array is empty when the settings is ok.
*
* @return array Errors
*/
public function getErrors()
{
return $this->_errors;
}
/**
* Activates or deactivates the strict mode.
*
* @param bool $value Strict parameter
*
* @throws Exception
*/
public function setStrict($value)
{
if (!is_bool($value)) {
throw new Exception('Invalid value passed to setStrict()');
}
$this->_strict = $value;
}
/**
* Returns if the 'strict' mode is active.
*
* @return bool Strict parameter
*/
public function isStrict()
{
return $this->_strict;
}
/**
* Returns if the debug is active.
*
* @return bool Debug parameter
*/
public function isDebugActive()
{
return $this->_debug;
}
/**
* Set a baseurl value.
*
* @param string $baseurl Base URL.
*/
public function setBaseURL($baseurl)
{
$this->_baseurl = $baseurl;
}
/**
* Returns the baseurl set on the settings if any.
*
* @return null|string The baseurl
*/
public function getBaseURL()
{
return $this->_baseurl;
}
/**
* Sets the IdP certificate.
*
* @param string $cert IdP certificate
*/
public function setIdPCert($cert)
{
$this->_idp['x509cert'] = $cert;
$this->formatIdPCert();
}
}