diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php index dfb49e6857b3bb4ef6fa134022e3b665b7494b75..54262ac859fa1b6a4194b6f1019bb30219a45779 100644 --- a/lib/SimpleSAML/Configuration.php +++ b/lib/SimpleSAML/Configuration.php @@ -559,36 +559,47 @@ class Configuration implements Utils\ClearableState /** * This function retrieves a boolean configuration option. * - * An exception will be thrown if this option isn't a boolean, or if this option isn't found, and no default value - * is given. + * An exception will be thrown if this option isn't a boolean, or if this option isn't found. * - * @param string $name The name of the option. - * @param mixed $default A default value which will be returned if the option isn't found. The option will be - * required if this parameter isn't given. The default value can be any value, including - * null. + * @param string $name The name of the option. + * @return boolean The option with the given name. * - * @return boolean|mixed The option with the given name, or $default if the option isn't found and $default is - * specified. - * - * @throws \Exception If the option is not boolean. + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not boolean. */ - public function getBoolean(string $name, $default = self::REQUIRED_OPTION) + public function getBoolean(string $name): bool { - $ret = $this->getValue($name, $default); + $ret = $this->getValue($name); - if ($ret === $default) { - // the option wasn't found, or it matches the default value. In any case, return this value - return $ret; - } + Assert::boolean( + $ret, + sprintf('%s: The option %s is not a valid boolean value.', $this->location, var_export($name, true)), + ); - if (!is_bool($ret)) { - throw new \Exception( - $this->location . ': The option ' . var_export($name, true) . - ' is not a valid boolean value.' - ); + return $ret; + } + + + /** + * This function retrieves a boolean configuration option. + * + * An exception will be thrown if this option isn't a boolean. + * + * @param string $name The name of the option. + * @param bool|null $default A default value which will be returned if the option isn't found. + * The default value can be null or a boolean. + * + * @return bool|null The option with the given name, or $default. + * + * @throws \SimpleSAML\Assert\AssertionFailedException If the option is not boolean. + */ + public function getOptionalBoolean(string $name, ?bool $default): ?bool + { + if (!$this->hasValue($name)) { + // the option wasn't found, or it matches the default value. In any case, return this value + return $default; } - return $ret; + return $this->getBoolean($name); } diff --git a/lib/SimpleSAML/Database.php b/lib/SimpleSAML/Database.php index df4fa1e720c00ee54c3e0a32e9b5c738dc53bfbd..7b294897b0478e7055e79f49b0c39c258f844268 100644 --- a/lib/SimpleSAML/Database.php +++ b/lib/SimpleSAML/Database.php @@ -136,7 +136,7 @@ class Database 'database.username' => $config->getString('database.username', null), 'database.password' => $config->getString('database.password', null), 'database.prefix' => $config->getString('database.prefix', ''), - 'database.persistent' => $config->getBoolean('database.persistent', true), + 'database.persistent' => $config->getOptionalBoolean('database.persistent', true), ], // TODO: deprecated: the "database.slave" terminology is preserved here for backwards compatibility. diff --git a/lib/SimpleSAML/Error/Error.php b/lib/SimpleSAML/Error/Error.php index f5a4b2d284e9cfc2424a980e01a8586346b7100a..7077b7e75c6d92cb8b3f8e453956e12ae50f0eed 100644 --- a/lib/SimpleSAML/Error/Error.php +++ b/lib/SimpleSAML/Error/Error.php @@ -230,7 +230,7 @@ class Error extends Exception $config = Configuration::getInstance(); $data = []; - $data['showerrors'] = $config->getBoolean('showerrors', true); + $data['showerrors'] = $config->getOptionalBoolean('showerrors', true); $data['error'] = $errorData; $data['errorCode'] = $this->errorCode; $data['parameters'] = $this->parameters; @@ -242,7 +242,7 @@ class Error extends Exception // check if there is a valid technical contact email address if ( - $config->getBoolean('errorreporting', true) + $config->getOptionalBoolean('errorreporting', true) && $config->getString('technicalcontact_email', 'na@example.org') !== 'na@example.org' ) { // enable error reporting diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php index 884d934306429549408cdf587e362709f62bf6c5..dccf0aa860c50c4e9f45a5bedfb88c02a06befd7 100644 --- a/lib/SimpleSAML/IdP.php +++ b/lib/SimpleSAML/IdP.php @@ -81,12 +81,12 @@ class IdP $globalConfig = Configuration::getInstance(); if (substr($id, 0, 6) === 'saml2:') { - if (!$globalConfig->getBoolean('enable.saml20-idp', false)) { + if (!$globalConfig->getOptionalBoolean('enable.saml20-idp', false)) { throw new Error\Exception('enable.saml20-idp disabled in config.php.'); } $this->config = $metadata->getMetaDataConfig(substr($id, 6), 'saml20-idp-hosted'); } elseif (substr($id, 0, 5) === 'adfs:') { - if (!$globalConfig->getBoolean('enable.adfs-idp', false)) { + if (!$globalConfig->getOptionalBoolean('enable.adfs-idp', false)) { throw new Error\Exception('enable.adfs-idp disabled in config.php.'); } $this->config = $metadata->getMetaDataConfig(substr($id, 5), 'adfs-idp-hosted'); diff --git a/lib/SimpleSAML/Locale/Language.php b/lib/SimpleSAML/Locale/Language.php index 3ae24285f5ec4c47b0ac774a71a4a3fe07cb5eab..d1c6a4dab78f6612f70a9bd638ef83ad02be5348 100644 --- a/lib/SimpleSAML/Locale/Language.php +++ b/lib/SimpleSAML/Locale/Language.php @@ -160,7 +160,7 @@ class Language if (isset($_GET[$this->languageParameterName])) { $this->setLanguage( $_GET[$this->languageParameterName], - $this->configuration->getBoolean('language.parameter.setcookie', true) + $this->configuration->getOptionalBoolean('language.parameter.setcookie', true) ); } } @@ -437,8 +437,8 @@ class Language 'lifetime' => ($config->getInteger('language.cookie.lifetime', 60 * 60 * 24 * 900)), 'domain' => ($config->getString('language.cookie.domain', '')), 'path' => ($config->getString('language.cookie.path', '/')), - 'secure' => ($config->getBoolean('language.cookie.secure', false)), - 'httponly' => ($config->getBoolean('language.cookie.httponly', false)), + 'secure' => ($config->getOptionalBoolean('language.cookie.secure', false)), + 'httponly' => ($config->getOptionalBoolean('language.cookie.httponly', false)), 'samesite' => ($config->getString('language.cookie.samesite', null)), ]; diff --git a/lib/SimpleSAML/Metadata/SAMLBuilder.php b/lib/SimpleSAML/Metadata/SAMLBuilder.php index 4458d679a23adff533dd04469a3c647bee5bd378..14c8e02a058bc2ae43ca2462c1f94d619bc3aafb 100644 --- a/lib/SimpleSAML/Metadata/SAMLBuilder.php +++ b/lib/SimpleSAML/Metadata/SAMLBuilder.php @@ -432,12 +432,8 @@ class SAMLBuilder */ $attributeconsumer = new AttributeConsumingService(); - $attributeconsumer->setIndex($metadata->getInteger('attributes.index', 0)); - - if ($metadata->hasValue('attributes.isDefault')) { - $attributeconsumer->setIsDefault($metadata->getBoolean('attributes.isDefault', false)); - } - + $attributeconsumer->setIndex($metadata->getOptionalInteger('attributes.index', 0)); + $attributeconsumer->setIsDefault($metadata->getOptionalBoolean('attributes.isDefault', false)); $attributeconsumer->setServiceName($name); $attributeconsumer->setServiceDescription($metadata->getLocalizedString('description', [])); diff --git a/lib/SimpleSAML/Metadata/Signer.php b/lib/SimpleSAML/Metadata/Signer.php index 01c1cffc3596fcce924c6cffa83cda8ff7edcf55..2e056e324c8b551a92cd77ec5f6112c4c5dcb995 100644 --- a/lib/SimpleSAML/Metadata/Signer.php +++ b/lib/SimpleSAML/Metadata/Signer.php @@ -144,7 +144,7 @@ class Signer return $entityMetadata['metadata.sign.enable']; } - return $config->getBoolean('metadata.sign.enable', false); + return $config->getOptionalBoolean('metadata.sign.enable', false); } diff --git a/lib/SimpleSAML/Module.php b/lib/SimpleSAML/Module.php index 440466898b067054ccfce66be632edbd3a0d63e0..d3ea8d94aa487ad1fe6f817292c7cd555f11fcbe 100644 --- a/lib/SimpleSAML/Module.php +++ b/lib/SimpleSAML/Module.php @@ -310,7 +310,7 @@ class Module 'max_age' => strval($cacheConfig->getInteger('max_age', 86400)) ]); $response->setAutoLastModified(); - if ($cacheConfig->getBoolean('etag', false)) { + if ($cacheConfig->getOptionalBoolean('etag', false)) { $response->setAutoEtag(); } $response->isNotModified($request); diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index 401fd6ade6777427523960471778c80236a4603f..260289ff218e9751de6019db5e77f2d60182db88 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -653,7 +653,7 @@ class Session implements Utils\ClearableState !$this->transient && (!empty($data['RememberMe']) || $this->rememberMeExpire !== null) - && self::$config->getBoolean('session.rememberme.enable', false) + && self::$config->getOptionalBoolean('session.rememberme.enable', false) ) { $this->setRememberMeExpire(); } else { diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php index 324c4f52117b8a3eecf8f93bbe51b02603febe69..1e3e1344b6fb2fec42f398ad8cb70c5430f95a4f 100644 --- a/lib/SimpleSAML/SessionHandler.php +++ b/lib/SimpleSAML/SessionHandler.php @@ -161,7 +161,7 @@ abstract class SessionHandler 'lifetime' => $config->getInteger('session.cookie.lifetime', 0), 'path' => $config->getString('session.cookie.path', '/'), 'domain' => $config->getString('session.cookie.domain', null), - 'secure' => $config->getBoolean('session.cookie.secure', false), + 'secure' => $config->getOptionalBoolean('session.cookie.secure', false), 'samesite' => $config->getString('session.cookie.samesite', null), 'httponly' => true, ]; diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php index 1f6b22f8f0624c336e2aee52f88c6656647e1c5a..b1dd93aad102fba3f5851db9480b09c069298d48 100644 --- a/lib/SimpleSAML/SessionHandlerPHP.php +++ b/lib/SimpleSAML/SessionHandlerPHP.php @@ -287,13 +287,13 @@ class SessionHandlerPHP extends SessionHandler 'You cannot set both the session.phpsession.limitedpath and session.cookie.path options.' ); } elseif ($config->hasValue('session.phpsession.limitedpath')) { - $ret['path'] = $config->getBoolean( + $ret['path'] = $config->getOptionalBoolean( 'session.phpsession.limitedpath', false ) ? $config->getBasePath() : '/'; } - $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', true); + $ret['httponly'] = $config->getOptionalBoolean('session.phpsession.httponly', true); return $ret; } diff --git a/lib/SimpleSAML/Utils/Config/Metadata.php b/lib/SimpleSAML/Utils/Config/Metadata.php index 0ec059974b21c0966e78efecfa463a9b02ab8853..517a155245ac26c47db0821848659795aeb4ffac 100644 --- a/lib/SimpleSAML/Utils/Config/Metadata.php +++ b/lib/SimpleSAML/Utils/Config/Metadata.php @@ -278,7 +278,7 @@ class Metadata $nameIdPolicy_cf = Configuration::loadFromArray($nameIdPolicy); $policy = [ 'Format' => $nameIdPolicy_cf->getString('Format', Constants::NAMEID_TRANSIENT), - 'AllowCreate' => $nameIdPolicy_cf->getBoolean('AllowCreate', true), + 'AllowCreate' => $nameIdPolicy_cf->getOptionalBoolean('AllowCreate', true), ]; $spNameQualifier = $nameIdPolicy_cf->getString('SPNameQualifier', false); if ($spNameQualifier !== false) { diff --git a/lib/SimpleSAML/Utils/HTTP.php b/lib/SimpleSAML/Utils/HTTP.php index 402901b67f67f9459cfbbe83ea6a72dc60f59cc6..6482e68e6d32b0bfcb192bdf44a5e7d48f1aba05 100644 --- a/lib/SimpleSAML/Utils/HTTP.php +++ b/lib/SimpleSAML/Utils/HTTP.php @@ -688,7 +688,7 @@ class HTTP public function getPOSTRedirectURL(string $destination, array $data): string { $config = Configuration::getInstance(); - $allowed = $config->getBoolean('enable.http_post', false); + $allowed = $config->getOptionalBoolean('enable.http_post', false); if ($allowed && preg_match("#^http:#", $destination) && $this->isHTTPS()) { // we need to post the data to HTTP @@ -1181,7 +1181,7 @@ class HTTP } $config = Configuration::getInstance(); - $allowed = $config->getBoolean('enable.http_post', false); + $allowed = $config->getOptionalBoolean('enable.http_post', false); if ($allowed && preg_match("#^http:#", $destination) && $this->isHTTPS()) { // we need to post the data to HTTP diff --git a/lib/SimpleSAML/XHTML/IdPDisco.php b/lib/SimpleSAML/XHTML/IdPDisco.php index 5abcd97c39ea631ec3dac8273f05a1d297b758a6..8a6275c68733136e2c98bc69cfbcd62af840df68 100644 --- a/lib/SimpleSAML/XHTML/IdPDisco.php +++ b/lib/SimpleSAML/XHTML/IdPDisco.php @@ -243,7 +243,7 @@ class IdPDisco return null; } - if (!$this->config->getBoolean('idpdisco.validate', true)) { + if (!$this->config->getOptionalBoolean('idpdisco.validate', true)) { return $idp; } @@ -308,7 +308,7 @@ class IdPDisco */ protected function getSavedIdP(): ?string { - if (!$this->config->getBoolean('idpdisco.enableremember', false)) { + if (!$this->config->getOptionalBoolean('idpdisco.enableremember', false)) { // saving of IdP choices is disabled return null; } @@ -402,7 +402,7 @@ class IdPDisco */ protected function saveIdP(): bool { - if (!$this->config->getBoolean('idpdisco.enableremember', false)) { + if (!$this->config->getOptionalBoolean('idpdisco.enableremember', false)) { // saving of IdP choices is disabled return false; } @@ -618,8 +618,8 @@ class IdPDisco $t->data['returnIDParam'] = $this->returnIdParam; $t->data['entityID'] = $this->spEntityId; $t->data['urlpattern'] = htmlspecialchars($httpUtils->getSelfURLNoQuery()); - $t->data['rememberenabled'] = $this->config->getBoolean('idpdisco.enableremember', false); - $t->data['rememberchecked'] = $this->config->getBoolean('idpdisco.rememberchecked', false); + $t->data['rememberenabled'] = $this->config->getOptionalBoolean('idpdisco.enableremember', false); + $t->data['rememberchecked'] = $this->config->getOptionalBoolean('idpdisco.rememberchecked', false); $t->send(); } } diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php index 5ad664905b14648e909f624f0f4c1cfd36d60de2..da2b9dbf83bdf1daa6e509fe5dd478000f91c93d 100644 --- a/lib/SimpleSAML/XHTML/Template.php +++ b/lib/SimpleSAML/XHTML/Template.php @@ -265,7 +265,7 @@ class Template extends Response */ private function setupTwig(): Environment { - $auto_reload = $this->configuration->getBoolean('template.auto_reload', true); + $auto_reload = $this->configuration->getOptionalBoolean('template.auto_reload', true); $cache = $this->configuration->getString('template.cache', false); // set up template paths @@ -312,7 +312,7 @@ class Template extends Response } $twig->addGlobal('queryParams', $queryParams); $twig->addGlobal('templateId', str_replace('.twig', '', $this->normalizeTemplateName($this->template))); - $twig->addGlobal('isProduction', $this->configuration->getBoolean('production', true)); + $twig->addGlobal('isProduction', $this->configuration->getOptionalBoolean('production', true)); $twig->addGlobal('baseurlpath', ltrim($this->configuration->getBasePath(), '/')); // add a filter for translations out of arrays diff --git a/modules/admin/lib/Controller/Config.php b/modules/admin/lib/Controller/Config.php index f29180ab7dc5cfb94cd693ba2c04fee5f4664343..b149465d8b51835f1ba93ce18dd0d11b931ed2f7 100644 --- a/modules/admin/lib/Controller/Config.php +++ b/modules/admin/lib/Controller/Config.php @@ -132,7 +132,7 @@ class Config ] ], 'enablematrix' => [ - 'saml20idp' => $this->config->getBoolean('enable.saml20-idp', false), + 'saml20idp' => $this->config->getOptionalBoolean('enable.saml20-idp', false), ], 'funcmatrix' => $this->getPrerequisiteChecks(), 'logouturl' => $this->authUtils->getAdminLogoutURL(), @@ -267,7 +267,7 @@ class Config ] ], 'curl_init' => [ - 'required' => $this->config->getBoolean('admin.checkforupdates', true) ? 'required' : 'optional', + 'required' => $this->config->getOptionalBoolean('admin.checkforupdates', true) ? 'required' : 'optional', 'descr' => [ 'optional' => Translate::noop( 'cURL (might be required by some modules)' @@ -366,7 +366,7 @@ class Config $cryptoUtils = new Utils\Crypto(); // perform some sanity checks on the configured certificates - if ($this->config->getBoolean('enable.saml20-idp', false) !== false) { + if ($this->config->getOptionalBoolean('enable.saml20-idp', false) !== false) { $handler = MetaDataStorageHandler::getMetadataHandler(); try { $metadata = $handler->getMetaDataCurrent('saml20-idp-hosted'); @@ -401,7 +401,7 @@ class Config } } - if ($this->config->getBoolean('metadata.sign.enable', false) !== false) { + if ($this->config->getOptionalBoolean('metadata.sign.enable', false) !== false) { $private = $cryptoUtils->loadPrivateKey($this->config, false, 'metadata.sign.'); $public = $cryptoUtils->loadPublicKey($this->config, false, 'metadata.sign.'); $matrix[] = [ @@ -455,7 +455,7 @@ class Config * Check for updates. Store the remote result in the session so we don't need to fetch it on every access to * this page. */ - if ($this->config->getBoolean('admin.checkforupdates', true) && $this->config->getVersion() !== 'master') { + if ($this->config->getOptionalBoolean('admin.checkforupdates', true) && $this->config->getVersion() !== 'master') { if (!function_exists('curl_init')) { $warnings[] = Translate::noop( 'The cURL PHP extension is missing. Cannot check for SimpleSAMLphp updates.' diff --git a/modules/admin/lib/Controller/Federation.php b/modules/admin/lib/Controller/Federation.php index cada26dd1d5bb51149d24547918235704450e78e..8387c60571460270a09e6c1282bed371da2643ed 100644 --- a/modules/admin/lib/Controller/Federation.php +++ b/modules/admin/lib/Controller/Federation.php @@ -123,9 +123,9 @@ class Federation 'remote' => [ 'saml20-idp-remote' => !empty($hostedSPs) ? $this->mdHandler->getList('saml20-idp-remote', true) : [], - 'saml20-sp-remote' => $this->config->getBoolean('enable.saml20-idp', false) === true + 'saml20-sp-remote' => $this->config->getOptionalBoolean('enable.saml20-idp', false) === true ? $this->mdHandler->getList('saml20-sp-remote', true) : [], - 'adfs-sp-remote' => ($this->config->getBoolean('enable.adfs-idp', false) === true) && + 'adfs-sp-remote' => ($this->config->getOptionalBoolean('enable.adfs-idp', false) === true) && Module::isModuleEnabled('adfs') ? $this->mdHandler->getList('adfs-sp-remote', true) : [], ], ]; @@ -190,7 +190,7 @@ class Federation $entities = []; // SAML 2 - if ($this->config->getBoolean('enable.saml20-idp', false)) { + if ($this->config->getOptionalBoolean('enable.saml20-idp', false)) { try { $idps = $this->mdHandler->getList('saml20-idp-hosted'); $saml2entities = []; @@ -230,7 +230,7 @@ class Federation } // ADFS - if ($this->config->getBoolean('enable.adfs-idp', false) && Module::isModuleEnabled('adfs')) { + if ($this->config->getOptionalBoolean('enable.adfs-idp', false) && Module::isModuleEnabled('adfs')) { try { $idps = $this->mdHandler->getList('adfs-idp-hosted'); $adfsentities = []; diff --git a/modules/core/lib/Auth/Process/ExtendIdPSession.php b/modules/core/lib/Auth/Process/ExtendIdPSession.php index 09ce3d08c3a1077cb05daf0bca7df3fc116436e0..40f43e37a02ca5f03fd69deb0baec181bd2ff2a1 100644 --- a/modules/core/lib/Auth/Process/ExtendIdPSession.php +++ b/modules/core/lib/Auth/Process/ExtendIdPSession.php @@ -46,7 +46,7 @@ class ExtendIdPSession extends Auth\ProcessingFilter if ( !empty($state['RememberMe']) && $rememberMeExpire !== null - && $globalConfig->getBoolean('session.rememberme.enable', false) + && $globalConfig->getOptionalBoolean('session.rememberme.enable', false) ) { $session->setRememberMeExpire(); return; diff --git a/modules/core/lib/Auth/Process/ScopeAttribute.php b/modules/core/lib/Auth/Process/ScopeAttribute.php index aec51485d558bab25749c58de9c564abf12e0ac4..11241324ab67eff713199622628414970d597a3b 100644 --- a/modules/core/lib/Auth/Process/ScopeAttribute.php +++ b/modules/core/lib/Auth/Process/ScopeAttribute.php @@ -60,7 +60,7 @@ class ScopeAttribute extends Auth\ProcessingFilter $this->scopeAttribute = $cfg->getString('scopeAttribute'); $this->sourceAttribute = $cfg->getString('sourceAttribute'); $this->targetAttribute = $cfg->getString('targetAttribute'); - $this->onlyIfEmpty = $cfg->getBoolean('onlyIfEmpty', false); + $this->onlyIfEmpty = $cfg->getOptionalBoolean('onlyIfEmpty', false); } diff --git a/modules/core/lib/Auth/UserPassBase.php b/modules/core/lib/Auth/UserPassBase.php index 661159d84302c6bdfb155ee483a2da0265b0e828..d596eb638db74312ffeed2102f783f3b67cffac9 100644 --- a/modules/core/lib/Auth/UserPassBase.php +++ b/modules/core/lib/Auth/UserPassBase.php @@ -120,8 +120,8 @@ abstract class UserPassBase extends Auth\Source // get the "remember me" config options $sspcnf = Configuration::getInstance(); - $this->rememberMeEnabled = $sspcnf->getBoolean('session.rememberme.enable', false); - $this->rememberMeChecked = $sspcnf->getBoolean('session.rememberme.checked', false); + $this->rememberMeEnabled = $sspcnf->getOptionalBoolean('session.rememberme.enable', false); + $this->rememberMeChecked = $sspcnf->getOptionalBoolean('session.rememberme.checked', false); } diff --git a/modules/core/www/idp/logout-iframe-post.php b/modules/core/www/idp/logout-iframe-post.php index 6dc9c8d35ddf9dbff909f717d1d2d052d0b1d4ac..31217b217fb748e372826754d8266f30fc317c70 100644 --- a/modules/core/www/idp/logout-iframe-post.php +++ b/modules/core/www/idp/logout-iframe-post.php @@ -36,9 +36,9 @@ if ($assertionLifetime === null) { } $lr->setNotOnOrAfter(time() + $assertionLifetime); -$encryptNameId = $spMetadata->getBoolean('nameid.encryption', null); +$encryptNameId = $spMetadata->getOptionalBoolean('nameid.encryption', null); if ($encryptNameId === null) { - $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', false); + $encryptNameId = $idpMetadata->getOptionalBoolean('nameid.encryption', false); } if ($encryptNameId) { $lr->encryptNameId(\SimpleSAML\Module\saml\Message::getEncryptionKey($spMetadata)); diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php index efdb5de6a59cae37183824ed16827bc6022f05a5..4b886db7ac4d35154917cce61bace0d0180735d3 100644 --- a/modules/saml/lib/Auth/Source/SP.php +++ b/modules/saml/lib/Auth/Source/SP.php @@ -96,7 +96,7 @@ class SP extends \SimpleSAML\Auth\Source $this->entityId = $this->metadata->getString('entityID'); $this->idp = $this->metadata->getString('idp', null); $this->discoURL = $this->metadata->getString('discoURL', null); - $this->disable_scoping = $this->metadata->getBoolean('disable_scoping', false); + $this->disable_scoping = $this->metadata->getOptionalBoolean('disable_scoping', false); } @@ -532,7 +532,7 @@ class SP extends \SimpleSAML\Auth\Source $requesterID = []; /* Only check for real info for Scoping element if we are going to send Scoping element */ - if ($this->disable_scoping !== true && $idpMetadata->getBoolean('disable_scoping', false) !== true) { + if ($this->disable_scoping !== true && $idpMetadata->getOptionalBoolean('disable_scoping', false) !== true) { if (isset($state['saml:IDPList'])) { $IDPList = $state['saml:IDPList']; } @@ -994,9 +994,9 @@ class SP extends \SimpleSAML\Auth\Source $lr->setExtensions($this->metadata->getArray('saml:logout:Extensions')); } - $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', null); + $encryptNameId = $idpMetadata->getOptionalBoolean('nameid.encryption', null); if ($encryptNameId === null) { - $encryptNameId = $this->metadata->getBoolean('nameid.encryption', false); + $encryptNameId = $this->metadata->getOptionalBoolean('nameid.encryption', false); } if ($encryptNameId) { $lr->encryptNameId(Module\saml\Message::getEncryptionKey($idpMetadata)); diff --git a/modules/saml/lib/IdP/SAML2.php b/modules/saml/lib/IdP/SAML2.php index cb8c5c6152e65e9ded23b70d598ff2d06ff4e6d0..4592d2059ba023f83e2c806a1b68640d50b4f94f 100644 --- a/modules/saml/lib/IdP/SAML2.php +++ b/modules/saml/lib/IdP/SAML2.php @@ -255,7 +255,7 @@ class SAML2 $skipEndpointValidation = false; if ($authnRequestSigned === true) { - $skipEndpointValidationWhenSigned = $spMetadata->getValue('skipEndpointValidationWhenSigned', false); + $skipEndpointValidationWhenSigned = $spMetadata->getOptionalValue('skipEndpointValidationWhenSigned', false); if (is_bool($skipEndpointValidationWhenSigned) === true) { $skipEndpointValidation = $skipEndpointValidationWhenSigned; } elseif (is_callable($skipEndpointValidationWhenSigned) === true) { @@ -305,13 +305,13 @@ class SAML2 $httpUtils = new Utils\HTTP(); $supportedBindings = [Constants::BINDING_HTTP_POST]; - if ($idpMetadata->getBoolean('saml20.sendartifact', false)) { + if ($idpMetadata->getOptionalBoolean('saml20.sendartifact', false)) { $supportedBindings[] = Constants::BINDING_HTTP_ARTIFACT; } - if ($idpMetadata->getBoolean('saml20.hok.assertion', false)) { + if ($idpMetadata->getOptionalBoolean('saml20.hok.assertion', false)) { $supportedBindings[] = Constants::BINDING_HOK_SSO; } - if ($idpMetadata->getBoolean('saml20.ecp', false)) { + if ($idpMetadata->getOptionalBoolean('saml20.ecp', false)) { $supportedBindings[] = Constants::BINDING_PAOS; } @@ -462,7 +462,7 @@ class SAML2 } if (!$forceAuthn) { - $forceAuthn = $spMetadata->getBoolean('ForceAuthn', false); + $forceAuthn = $spMetadata->getOptionalBoolean('ForceAuthn', false); } $sessionLostParams = [ @@ -844,7 +844,7 @@ class SAML2 $metadata['keys'] = $keys; // add ArtifactResolutionService endpoint, if enabled - if ($config->getBoolean('saml20.sendartifact', false)) { + if ($config->getOptionalBoolean('saml20.sendartifact', false)) { $metadata['ArtifactResolutionService'][] = [ 'index' => 0, 'Binding' => Constants::BINDING_SOAP, @@ -853,7 +853,7 @@ class SAML2 } // add Holder of Key, if enabled - if ($config->getBoolean('saml20.hok.assertion', false)) { + if ($config->getOptionalBoolean('saml20.hok.assertion', false)) { array_unshift( $metadata['SingleSignOnService'], [ @@ -865,7 +865,7 @@ class SAML2 } // add ECP profile, if enabled - if ($config->getBoolean('saml20.ecp', false)) { + if ($config->getOptionalBoolean('saml20.ecp', false)) { $metadata['SingleSignOnService'][] = [ 'index' => 0, 'Binding' => Constants::BINDING_SOAP, @@ -1001,9 +1001,9 @@ class SAML2 Configuration $spMetadata, array $attributes ): array { - $base64Attributes = $spMetadata->getBoolean('base64attributes', null); + $base64Attributes = $spMetadata->getOptionalBoolean('base64attributes', null); if ($base64Attributes === null) { - $base64Attributes = $idpMetadata->getBoolean('base64attributes', false); + $base64Attributes = $idpMetadata->getOptionalBoolean('base64attributes', false); } if ($base64Attributes) { @@ -1129,9 +1129,9 @@ class SAML2 $httpUtils = new Utils\HTTP(); $now = time(); - $signAssertion = $spMetadata->getBoolean('saml20.sign.assertion', null); + $signAssertion = $spMetadata->getOptionalBoolean('saml20.sign.assertion', null); if ($signAssertion === null) { - $signAssertion = $idpMetadata->getBoolean('saml20.sign.assertion', true); + $signAssertion = $idpMetadata->getOptionalBoolean('saml20.sign.assertion', true); } $config = Configuration::getInstance(); @@ -1190,7 +1190,7 @@ class SAML2 $hokAssertion = true; } if ($hokAssertion === null) { - $hokAssertion = $idpMetadata->getBoolean('saml20.hok.assertion', false); + $hokAssertion = $idpMetadata->getOptionalBoolean('saml20.hok.assertion', false); } if ($hokAssertion) { @@ -1238,7 +1238,7 @@ class SAML2 $a->setSubjectConfirmation([$sc]); // add attributes - if ($spMetadata->getBoolean('simplesaml.attributes', true)) { + if ($spMetadata->getOptionalBoolean('simplesaml.attributes', true)) { $attributeNameFormat = self::getAttributeNameFormat($idpMetadata, $spMetadata); $a->setAttributeNameFormat($attributeNameFormat); $attributes = self::encodeAttributes($idpMetadata, $spMetadata, $state['Attributes']); @@ -1293,9 +1293,9 @@ class SAML2 $a->setNameId($nameId); - $encryptNameId = $spMetadata->getBoolean('nameid.encryption', null); + $encryptNameId = $spMetadata->getOptionalBoolean('nameid.encryption', null); if ($encryptNameId === null) { - $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', false); + $encryptNameId = $idpMetadata->getOptionalBoolean('nameid.encryption', false); } if ($encryptNameId) { $a->encryptNameId(\SimpleSAML\Module\saml\Message::getEncryptionKey($spMetadata)); @@ -1324,9 +1324,9 @@ class SAML2 Configuration $spMetadata, Assertion $assertion ) { - $encryptAssertion = $spMetadata->getBoolean('assertion.encryption', null); + $encryptAssertion = $spMetadata->getOptionalBoolean('assertion.encryption', null); if ($encryptAssertion === null) { - $encryptAssertion = $idpMetadata->getBoolean('assertion.encryption', false); + $encryptAssertion = $idpMetadata->getOptionalBoolean('assertion.encryption', false); } if (!$encryptAssertion) { // we are _not_ encrypting this assertion, and are therefore done @@ -1403,9 +1403,9 @@ class SAML2 } $lr->setNotOnOrAfter(time() + $assertionLifetime); - $encryptNameId = $spMetadata->getBoolean('nameid.encryption', null); + $encryptNameId = $spMetadata->getOptionalBoolean('nameid.encryption', null); if ($encryptNameId === null) { - $encryptNameId = $idpMetadata->getBoolean('nameid.encryption', false); + $encryptNameId = $idpMetadata->getOptionalBoolean('nameid.encryption', false); } if ($encryptNameId) { $lr->encryptNameId(\SimpleSAML\Module\saml\Message::getEncryptionKey($spMetadata)); @@ -1429,9 +1429,9 @@ class SAML2 Configuration $spMetadata, string $consumerURL ): Response { - $signResponse = $spMetadata->getBoolean('saml20.sign.response', null); + $signResponse = $spMetadata->getOptionalBoolean('saml20.sign.response', null); if ($signResponse === null) { - $signResponse = $idpMetadata->getBoolean('saml20.sign.response', true); + $signResponse = $idpMetadata->getOptionalBoolean('saml20.sign.response', true); } $r = new Response(); diff --git a/modules/saml/lib/Message.php b/modules/saml/lib/Message.php index 22b3ab99daadb585a2b92480d6330ab9f3043c0f..fc2831bf3125ca154a816e34fc9d0d097ed2bb58 100644 --- a/modules/saml/lib/Message.php +++ b/modules/saml/lib/Message.php @@ -97,21 +97,21 @@ class Message ): void { $signingEnabled = null; if ($message instanceof LogoutRequest || $message instanceof LogoutResponse) { - $signingEnabled = $srcMetadata->getBoolean('sign.logout', null); + $signingEnabled = $srcMetadata->getOptionalBoolean('sign.logout', null); if ($signingEnabled === null) { - $signingEnabled = $dstMetadata->getBoolean('sign.logout', null); + $signingEnabled = $dstMetadata->getOptionalBoolean('sign.logout', null); } } elseif ($message instanceof AuthnRequest) { - $signingEnabled = $srcMetadata->getBoolean('sign.authnrequest', null); + $signingEnabled = $srcMetadata->getOptionalBoolean('sign.authnrequest', null); if ($signingEnabled === null) { - $signingEnabled = $dstMetadata->getBoolean('sign.authnrequest', null); + $signingEnabled = $dstMetadata->getOptionalBoolean('sign.authnrequest', null); } } if ($signingEnabled === null) { - $signingEnabled = $dstMetadata->getBoolean('redirect.sign', null); + $signingEnabled = $dstMetadata->getOptionalBoolean('redirect.sign', null); if ($signingEnabled === null) { - $signingEnabled = $srcMetadata->getBoolean('redirect.sign', false); + $signingEnabled = $srcMetadata->getOptionalBoolean('redirect.sign', false); } } if (!$signingEnabled) { @@ -203,14 +203,14 @@ class Message ): bool { $enabled = null; if ($message instanceof LogoutRequest || $message instanceof LogoutResponse) { - $enabled = $srcMetadata->getBoolean('validate.logout', null); + $enabled = $srcMetadata->getOptionalBoolean('validate.logout', null); if ($enabled === null) { - $enabled = $dstMetadata->getBoolean('validate.logout', null); + $enabled = $dstMetadata->getOptionalBoolean('validate.logout', null); } } elseif ($message instanceof AuthnRequest) { - $enabled = $srcMetadata->getBoolean('validate.authnrequest', null); + $enabled = $srcMetadata->getOptionalBoolean('validate.authnrequest', null); if ($enabled === null) { - $enabled = $dstMetadata->getBoolean('validate.authnrequest', null); + $enabled = $dstMetadata->getOptionalBoolean('validate.authnrequest', null); } } @@ -222,9 +222,9 @@ class Message ) { $enabled = true; } elseif ($enabled === null) { - $enabled = $srcMetadata->getBoolean('redirect.validate', null); + $enabled = $srcMetadata->getOptionalBoolean('redirect.validate', null); if ($enabled === null) { - $enabled = $dstMetadata->getBoolean('redirect.validate', false); + $enabled = $dstMetadata->getOptionalBoolean('redirect.validate', false); } } @@ -349,9 +349,9 @@ class Message Assert::isInstanceOfAny($assertion, [Assertion::class, EncryptedAssertion::class]); if ($assertion instanceof Assertion) { - $encryptAssertion = $srcMetadata->getBoolean('assertion.encryption', null); + $encryptAssertion = $srcMetadata->getOptionalBoolean('assertion.encryption', null); if ($encryptAssertion === null) { - $encryptAssertion = $dstMetadata->getBoolean('assertion.encryption', false); + $encryptAssertion = $dstMetadata->getOptionalBoolean('assertion.encryption', false); } if ($encryptAssertion) { /* The assertion was unencrypted, but we have encryption enabled. */ @@ -480,8 +480,8 @@ class Message $ar->setNameIdPolicy($policy); } - $ar->setForceAuthn($spMetadata->getBoolean('ForceAuthn', false)); - $ar->setIsPassive($spMetadata->getBoolean('IsPassive', false)); + $ar->setForceAuthn($spMetadata->getOptionalBoolean('ForceAuthn', false)); + $ar->setIsPassive($spMetadata->getOptionalBoolean('IsPassive', false)); $protbind = $spMetadata->getValueValidate('ProtocolBinding', [ Constants::BINDING_HTTP_POST, @@ -702,9 +702,9 @@ class Message } // is SSO with HoK enabled? IdP remote metadata overwrites SP metadata configuration - $hok = $idpMetadata->getBoolean('saml20.hok.assertion', null); + $hok = $idpMetadata->getOptionalBoolean('saml20.hok.assertion', null); if ($hok === null) { - $hok = $spMetadata->getBoolean('saml20.hok.assertion', false); + $hok = $spMetadata->getOptionalBoolean('saml20.hok.assertion', false); } if ($method === Constants::CM_BEARER && $hok) { $lastError = 'Bearer SubjectConfirmation received, but Holder-of-Key SubjectConfirmation needed'; @@ -824,7 +824,7 @@ class Message // as far as we can tell, the assertion is valid // maybe we need to base64 decode the attributes in the assertion? - if ($idpMetadata->getBoolean('base64attributes', false)) { + if ($idpMetadata->getOptionalBoolean('base64attributes', false)) { $attributes = $assertion->getAttributes(); $newAttributes = []; foreach ($attributes as $name => $values) { diff --git a/modules/saml/www/sp/metadata.php b/modules/saml/www/sp/metadata.php index f330dd7c9266e7219e4f021bc1d8fec238acb817..454883978e1b7e57c984f7006a4f7e3ec5e1b2b7 100644 --- a/modules/saml/www/sp/metadata.php +++ b/modules/saml/www/sp/metadata.php @@ -13,7 +13,7 @@ if (!array_key_exists('PATH_INFO', $_SERVER)) { } $config = Configuration::getInstance(); -if ($config->getBoolean('admin.protectmetadata', false)) { +if ($config->getOptionalBoolean('admin.protectmetadata', false)) { $authUtils = new Utils\Auth(); $authUtils->requireAdmin(); } diff --git a/tests/lib/SimpleSAML/ConfigurationTest.php b/tests/lib/SimpleSAML/ConfigurationTest.php index cee693667784ea6917e28cc359e11d3618e9fb39..c77c650ffefee6be1ad95697101e1e33bcb385f1 100644 --- a/tests/lib/SimpleSAML/ConfigurationTest.php +++ b/tests/lib/SimpleSAML/ConfigurationTest.php @@ -256,34 +256,48 @@ class ConfigurationTest extends ClearStateTestCase $c = Configuration::loadFromArray([ 'true_opt' => true, 'false_opt' => false, + 'wrong_opt' => 'true', ]); - $this->assertEquals($c->getBoolean('missing_opt', '--missing--'), '--missing--'); - $this->assertEquals($c->getBoolean('true_opt', '--missing--'), true); - $this->assertEquals($c->getBoolean('false_opt', '--missing--'), false); - } + // Normal use + $this->assertTrue($c->getBoolean('true_opt')); + $this->assertFalse($c->getBoolean('false_opt')); - /** - * Test \SimpleSAML\Configuration::getBoolean() missing option - */ - public function testGetBooleanMissing(): void - { - $this->expectException(Exception::class); - $c = Configuration::loadFromArray([]); + // Missing option + $this->expectException(AssertionFailedException::class); $c->getBoolean('missing_opt'); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getBoolean('wrong_opt'); } /** - * Test \SimpleSAML\Configuration::getBoolean() wrong option + * Test \SimpleSAML\Configuration::getOptionalBoolean() */ - public function testGetBooleanWrong(): void + public function testGetOptionalBoolean(): void { - $this->expectException(Exception::class); $c = Configuration::loadFromArray([ - 'wrong' => 'true', + 'true_opt' => true, + 'false_opt' => false, + 'wrong_opt' => 'true', ]); - $c->getBoolean('wrong'); + + // Normal use + $this->assertTrue($c->getOptionalBoolean('true_opt', true)); + $this->assertTrue($c->getOptionalBoolean('true_opt', false)); + $this->assertFalse($c->getOptionalBoolean('false_opt', false)); + $this->assertFalse($c->getOptionalBoolean('false_opt', true)); + + // Missing option + $this->assertEquals($c->getOptionalBoolean('missing_opt', null), null); + $this->assertEquals($c->getOptionalBoolean('missing_opt', false), false); + $this->assertEquals($c->getOptionalBoolean('missing_opt', true), true); + + // Invalid option type + $this->expectException(AssertionFailedException::class); + $c->getOptionalBoolean('wrong_opt', null); } diff --git a/www/errorreport.php b/www/errorreport.php index 4af111475ab3a28e0dcdb8fa36e94166e60d1387..5200c8dc301bc5506040a42e28a3b374dbb513fa 100644 --- a/www/errorreport.php +++ b/www/errorreport.php @@ -48,7 +48,7 @@ $data['version'] = $config->getVersion(); $data['hostname'] = php_uname('n'); $data['directory'] = dirname(dirname(__FILE__)); -if ($config->getBoolean('errorreporting', true)) { +if ($config->getOptionalBoolean('errorreporting', true)) { $mail = new SimpleSAML\Utils\EMail('SimpleSAMLphp error report from ' . $email); $mail->setData($data); if ($email) { diff --git a/www/saml2/idp/ArtifactResolutionService.php b/www/saml2/idp/ArtifactResolutionService.php index 30b3652acc772e7bbaf33b3e1ed87e71b2e432d8..4532c72d805ad9b50e63850d7c266f8072d5250c 100644 --- a/www/saml2/idp/ArtifactResolutionService.php +++ b/www/saml2/idp/ArtifactResolutionService.php @@ -23,7 +23,7 @@ use SimpleSAML\Metadata; use SimpleSAML\Store\StoreFactory; $config = Configuration::getInstance(); -if (!$config->getBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { +if (!$config->getOptionalBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { throw new Error\Error('NOACCESS', null, 403); } @@ -31,7 +31,7 @@ $metadata = Metadata\MetaDataStorageHandler::getMetadataHandler(); $idpEntityId = $metadata->getMetaDataCurrentEntityID('saml20-idp-hosted'); $idpMetadata = $metadata->getMetaDataConfig($idpEntityId, 'saml20-idp-hosted'); -if (!$idpMetadata->getBoolean('saml20.sendartifact', false)) { +if (!$idpMetadata->getOptionalBoolean('saml20.sendartifact', false)) { throw new Error\Error('NOACCESS'); } diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php index f139b2db3a8a60edfe3fedc8b12412533ebfbf1f..ac617b94c95fbc35bc4cade0aae5dd4bb88deb97 100644 --- a/www/saml2/idp/SSOService.php +++ b/www/saml2/idp/SSOService.php @@ -22,7 +22,7 @@ use SimpleSAML\Module; Logger::info('SAML2.0 - IdP.SSOService: Accessing SAML 2.0 IdP endpoint SSOService'); $config = Configuration::getInstance(); -if (!$config->getBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { +if (!$config->getOptionalBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { throw new Error\Error('NOACCESS', null, 403); } diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php index 2a617332f0e0bf42e72cd311ac68e31b9b8aa9ec..df1d597b63e0cdd3f92af2507e92312204103430 100644 --- a/www/saml2/idp/SingleLogoutService.php +++ b/www/saml2/idp/SingleLogoutService.php @@ -22,7 +22,7 @@ use SimpleSAML\Utils; Logger::info('SAML2.0 - IdP.SingleLogoutService: Accessing SAML 2.0 IdP endpoint SingleLogoutService'); $config = Configuration::getInstance(); -if (!$config->getBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { +if (!$config->getOptionalBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { throw new Error\Error('NOACCESS', null, 403); } diff --git a/www/saml2/idp/initSLO.php b/www/saml2/idp/initSLO.php index 11961711827be96764b280b0a47d9e686c5d8f3d..5f49209038299ebebc998533a2361ffbaaefede9 100644 --- a/www/saml2/idp/initSLO.php +++ b/www/saml2/idp/initSLO.php @@ -14,7 +14,7 @@ use SimpleSAML\Utils; Logger::info('SAML2.0 - IdP.initSLO: Accessing SAML 2.0 IdP endpoint init Single Logout'); $config = Configuration::getInstance(); -if (!$config->getBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { +if (!$config->getOptionalBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { throw new Error\Error('NOACCESS', null, 403); } diff --git a/www/saml2/idp/metadata.php b/www/saml2/idp/metadata.php index 31d3d53f66c8d44a3513df9655e60da9bc25bf3c..2ef9f313864d3dc89f8d3df61b72090467dc985c 100644 --- a/www/saml2/idp/metadata.php +++ b/www/saml2/idp/metadata.php @@ -9,12 +9,12 @@ use SimpleSAML\Module\saml\IdP\SAML2 as SAML2_IdP; use SimpleSAML\Utils; $config = Configuration::getInstance(); -if (!$config->getBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { +if (!$config->getOptionalBoolean('enable.saml20-idp', false) || !Module::isModuleEnabled('saml')) { throw new Error\Error('NOACCESS', null, 403); } // check if valid local session exists -if ($config->getBoolean('admin.protectmetadata', false)) { +if ($config->getOptionalBoolean('admin.protectmetadata', false)) { $authUtils = new Utils\Auth(); $authUtils->requireAdmin(); }