diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php index 1a234ed4ed4eab0b2473a6deacfddf3c8be0bc6a..b26bc16ada402106ae910aaf79947ea40ed0c503 100644 --- a/lib/SimpleSAML/SessionHandler.php +++ b/lib/SimpleSAML/SessionHandler.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace SimpleSAML; +use SimpleSAML\Store\StoreFactory; + abstract class SessionHandler { /** @@ -133,7 +135,7 @@ abstract class SessionHandler */ private static function createSessionHandler(): void { - $store = Store::getInstance(); + $store = StoreFactory::getInstance(); if ($store === false) { self::$sessionHandler = new SessionHandlerPHP(); } else { diff --git a/lib/SimpleSAML/SessionHandlerStore.php b/lib/SimpleSAML/SessionHandlerStore.php index ec7cbfe1a20b6491bc85043709a5f980abcd16f0..f4f89e71068def0cc4206318dfd850ce233394d5 100644 --- a/lib/SimpleSAML/SessionHandlerStore.php +++ b/lib/SimpleSAML/SessionHandlerStore.php @@ -11,23 +11,24 @@ declare(strict_types=1); namespace SimpleSAML; use SimpleSAML\Assert\Assert; +use SimpleSAML\Store\StoreInterface; class SessionHandlerStore extends SessionHandlerCookie { /** * The data store we save the session to. * - * @var \SimpleSAML\Store + * @var \SimpleSAML\Store\StoreInterface */ - private Store $store; + private StoreInterface $store; /** * Initialize the session. * - * @param \SimpleSAML\Store $store The store to use. + * @param \SimpleSAML\Store\StoreInterface $store The store to use. */ - protected function __construct(Store $store) + protected function __construct(StoreInterface $store) { parent::__construct(); diff --git a/lib/SimpleSAML/Store/Memcache.php b/lib/SimpleSAML/Store/MemcacheStore.php similarity index 82% rename from lib/SimpleSAML/Store/Memcache.php rename to lib/SimpleSAML/Store/MemcacheStore.php index 230a3ca752cf7d66e35ccb0ec53f203505638fe9..8a248fb6ab86b705ea5c2dbe761de1761f7c6d6b 100644 --- a/lib/SimpleSAML/Store/Memcache.php +++ b/lib/SimpleSAML/Store/MemcacheStore.php @@ -6,14 +6,14 @@ namespace SimpleSAML\Store; use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; -use SimpleSAML\Store; +use SimpleSAML\Memcache; /** * A memcache based data store. * - * @package SimpleSAMLphp + * @package simplesamlphp/simplesamlphp */ -class Memcache extends Store +class MemcacheStore implements StoreInterface { /** * This variable contains the session name prefix. @@ -42,7 +42,7 @@ class Memcache extends Store */ public function get(string $type, string $key) { - return \SimpleSAML\Memcache::get($this->prefix . '.' . $type . '.' . $key); + return Memcache::get($this->prefix . '.' . $type . '.' . $key); } @@ -62,7 +62,7 @@ class Memcache extends Store $expire = 0; } - \SimpleSAML\Memcache::set($this->prefix . '.' . $type . '.' . $key, $value, $expire); + Memcache::set($this->prefix . '.' . $type . '.' . $key, $value, $expire); } @@ -74,6 +74,6 @@ class Memcache extends Store */ public function delete(string $type, string $key): void { - \SimpleSAML\Memcache::delete($this->prefix . '.' . $type . '.' . $key); + Memcache::delete($this->prefix . '.' . $type . '.' . $key); } } diff --git a/lib/SimpleSAML/Store/Redis.php b/lib/SimpleSAML/Store/RedisStore.php similarity index 94% rename from lib/SimpleSAML/Store/Redis.php rename to lib/SimpleSAML/Store/RedisStore.php index 6a6aec8b404640066972717b7b02009b01c5ffdb..c2ddb6eb03418c8a684abee2e85b3ffbaae1fef2 100644 --- a/lib/SimpleSAML/Store/Redis.php +++ b/lib/SimpleSAML/Store/RedisStore.php @@ -8,14 +8,13 @@ use Predis\Client; use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; use SimpleSAML\Error; -use SimpleSAML\Store; /** * A data store using Redis to keep the data. * - * @package SimpleSAMLphp + * @package simplesamlphp/simplesamlphp */ -class Redis extends Store +class RedisStore extends StoreInterface { /** @var \Predis\Client */ public Client $redis; @@ -64,9 +63,7 @@ class Redis extends Store */ public function __destruct() { - if (method_exists($this->redis, 'disconnect')) { - $this->redis->disconnect(); - } + $this->redis->disconnect(); } diff --git a/lib/SimpleSAML/Store/SQL.php b/lib/SimpleSAML/Store/SQLStore.php similarity index 98% rename from lib/SimpleSAML/Store/SQL.php rename to lib/SimpleSAML/Store/SQLStore.php index e5bcd6fb51a4c9096374043dc34bff24044486b2..19df280d792e63d2006bcea2501a660da05532f4 100644 --- a/lib/SimpleSAML/Store/SQL.php +++ b/lib/SimpleSAML/Store/SQLStore.php @@ -4,19 +4,19 @@ declare(strict_types=1); namespace SimpleSAML\Store; +use Exception; use PDO; use PDOException; use SimpleSAML\Assert\Assert; use SimpleSAML\Configuration; use SimpleSAML\Logger; -use SimpleSAML\Store; /** * A data store using a RDBMS to keep the data. * - * @package SimpleSAMLphp + * @package simplesamlphp/simplesamlphp */ -class SQL extends Store +class SQLStore implements StoreInterface { /** * The PDO object for our database. @@ -62,7 +62,7 @@ class SQL extends Store try { $this->pdo = new PDO($dsn, $username, $password, $options); } catch (PDOException $e) { - throw new \Exception("Database error: " . $e->getMessage()); + throw new Exception("Database error: " . $e->getMessage()); } $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); diff --git a/lib/SimpleSAML/Store.php b/lib/SimpleSAML/Store/StoreFactory.php similarity index 59% rename from lib/SimpleSAML/Store.php rename to lib/SimpleSAML/Store/StoreFactory.php index 12e856f03dfd70f0781686fbc57d35177fef5b26..847e3122e67e76130a670b753b0cef42719dfce5 100644 --- a/lib/SimpleSAML/Store.php +++ b/lib/SimpleSAML/Store/StoreFactory.php @@ -2,24 +2,26 @@ declare(strict_types=1); -namespace SimpleSAML; +namespace SimpleSAML\Store; use Exception; +use SimpleSAML\Configuration; use SimpleSAML\Error; +use SimpleSAML\Module; /** * Base class for data stores. * - * @package SimpleSAMLphp + * @package simplesamlphp/simplesamlphp */ -abstract class Store implements Utils\ClearableState +abstract class StoreFactory { /** * Our singleton instance. * * This is false if the data store isn't enabled, and null if we haven't attempted to initialize it. * - * @var \SimpleSAML\Store|false|null + * @var \SimpleSAML\Store\StoreInterface|false|null */ private static $instance = null; @@ -27,11 +29,11 @@ abstract class Store implements Utils\ClearableState /** * Retrieve our singleton instance. * - * @return \SimpleSAML\Store|false The data store, or false if it isn't enabled. + * @return \SimpleSAML\Store\StoreInterface|false The data store, or false if it isn't enabled. * * @throws \SimpleSAML\Error\CriticalConfigurationError */ - public static function getInstance() + public static function getInstance(): StoreInterface { if (self::$instance !== null) { return self::$instance; @@ -57,7 +59,7 @@ abstract class Store implements Utils\ClearableState default: // datastore from module try { - $className = Module::resolveClass($storeType, 'Store', '\SimpleSAML\Store'); + $className = Module::resolveClass($storeType, 'StoreInterface'); } catch (Exception $e) { $c = $config->toArray(); $c['store.type'] = 'phpsession'; @@ -73,44 +75,4 @@ abstract class Store implements Utils\ClearableState return self::$instance; } - - - /** - * Retrieve a value from the data store. - * - * @param string $type The data type. - * @param string $key The key. - * - * @return mixed|null The value. - */ - abstract public function get(string $type, string $key); - - - /** - * Save a value to the data store. - * - * @param string $type The data type. - * @param string $key The key. - * @param mixed $value The value. - * @param int|null $expire The expiration time (unix timestamp), or null if it never expires. - */ - abstract public function set(string $type, string $key, $value, ?int $expire = null): void; - - - /** - * Delete a value from the data store. - * - * @param string $type The data type. - * @param string $key The key. - */ - abstract public function delete(string $type, string $key): void; - - - /** - * Clear any SSP specific state, such as SSP environmental variables or cached internals. - */ - public static function clearInternalState(): void - { - self::$instance = null; - } } diff --git a/lib/SimpleSAML/Store/StoreInterface.php b/lib/SimpleSAML/Store/StoreInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7111eb341cbda79e42874fe08370064c2dffb792 --- /dev/null +++ b/lib/SimpleSAML/Store/StoreInterface.php @@ -0,0 +1,43 @@ +<?php + +declare(strict_types=1); + +namespace SimpleSAML\Store; + +/** + * An interface describing data stores. + * + * @package simplesamlphp/simplesamlphp + */ +interface StoreInterface +{ + /** + * Retrieve a value from the data store. + * + * @param string $type The data type. + * @param string $key The key. + * + * @return mixed|null The value. + */ + public function get(string $type, string $key); + + + /** + * Save a value to the data store. + * + * @param string $type The data type. + * @param string $key The key. + * @param mixed $value The value. + * @param int|null $expire The expiration time (unix timestamp), or null if it never expires. + */ + public function set(string $type, string $key, $value, ?int $expire = null): void; + + + /** + * Delete a value from the data store. + * + * @param string $type The data type. + * @param string $key The key. + */ + public function delete(string $type, string $key): void; +} diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php index 1a6f8db57369e11c51f3f82b5b31fb8136471f99..0bfb57c54a00420040a0995d7589ef1d00afda9e 100644 --- a/modules/saml/lib/Auth/Source/SP.php +++ b/modules/saml/lib/Auth/Source/SP.php @@ -18,6 +18,7 @@ use SimpleSAML\Metadata\MetaDataStorageHandler; use SimpleSAML\Module; use SimpleSAML\Session; use SimpleSAML\Store; +use SimpleSAML\Store\StoreFactory; use SimpleSAML\Utils; class SP extends \SimpleSAML\Auth\Source @@ -385,7 +386,7 @@ class SP extends \SimpleSAML\Auth\Source */ private function getSLOEndpoints(): array { - $store = Store::getInstance(); + $store = StoreFactory::getInstance(); $bindings = $this->metadata->getArray( 'SingleLogoutServiceBinding', [ @@ -398,7 +399,7 @@ class SP extends \SimpleSAML\Auth\Source $endpoints = []; foreach ($bindings as $binding) { - if ($binding == Constants::BINDING_SOAP && !($store instanceof Store\SQL)) { + if ($binding == Constants::BINDING_SOAP && !($store instanceof Store\SQLStore)) { // we cannot properly support SOAP logout continue; } diff --git a/modules/saml/lib/IdP/SQLNameID.php b/modules/saml/lib/IdP/SQLNameID.php index 45623212a50115cd13011b476c71bdc2aefd775f..604da6d2075afe75a072cdddf847e5de7bcc07d0 100644 --- a/modules/saml/lib/IdP/SQLNameID.php +++ b/modules/saml/lib/IdP/SQLNameID.php @@ -4,13 +4,16 @@ declare(strict_types=1); namespace SimpleSAML\Module\saml\IdP; +use Exception; use PDO; use PDOStatement; use SimpleSAML\Assert\Assert; use SimpleSAML\Error; use SimpleSAML\Store; +use SimpleSAML\Store\StoreFactory; use SimpleSAML\Database; use SimpleSAML\Configuration; +use SimpleSAML\Logger; /** * Helper class for working with persistent NameIDs stored in SQL datastore. @@ -89,8 +92,8 @@ class SQLNameID if ($store === null) { try { self::createTable($table, $config); - } catch (\Exception $e) { - \SimpleSAML\Logger::debug('SQL persistent NameID table already exists.'); + } catch (Exception $e) { + Logger::debug('SQL persistent NameID table already exists.'); } } elseif ($store->getTableVersion('saml_PersistentNameID') !== self::TABLE_VERSION) { self::createTable($table); @@ -151,12 +154,12 @@ class SQLNameID /** * Retrieve the SQL datastore. * - * @return \SimpleSAML\Store\SQL SQL datastore. + * @return \SimpleSAML\Store\SQLStore SQL datastore. */ - private static function getStore(): Store\SQL + private static function getStore(): Store\SQLStore { - $store = Store::getInstance(); - if (!($store instanceof Store\SQL)) { + $store = StoreFactory::getInstance(); + if (!($store instanceof Store\SQLStore)) { throw new Error\Exception( 'SQL NameID store requires SimpleSAMLphp to be configured with a SQL datastore.' ); diff --git a/modules/saml/lib/SP/LogoutStore.php b/modules/saml/lib/SP/LogoutStore.php index 13922d1309358b1c9cf76ee000d43cb078b8cf40..ba1a3a4a8f4b70068b5e67434bb56a46a8c5fd6b 100644 --- a/modules/saml/lib/SP/LogoutStore.php +++ b/modules/saml/lib/SP/LogoutStore.php @@ -9,7 +9,7 @@ use SAML2\XML\saml\NameID; use SimpleSAML\Assert\Assert; use SimpleSAML\Logger; use SimpleSAML\Session; -use SimpleSAML\Store; +use SimpleSAML\Store;; use SimpleSAML\Utils; /** @@ -23,9 +23,9 @@ class LogoutStore /** * Create logout table in SQL, if it is missing. * - * @param \SimpleSAML\Store\SQL $store The datastore. + * @param \SimpleSAML\Store\SQLSTore $store The datastore. */ - private static function createLogoutTable(Store\SQL $store): void + private static function createLogoutTable(Store\SQLStore $store): void { $tableVer = $store->getTableVersion('saml_LogoutStore'); if ($tableVer === 4) { @@ -208,9 +208,9 @@ class LogoutStore /** * Clean the logout table of expired entries. * - * @param \SimpleSAML\Store\SQL $store The datastore. + * @param \SimpleSAML\Store\SQLStore $store The datastore. */ - private static function cleanLogoutStore(Store\SQL $store): void + private static function cleanLogoutStore(Store\SQLStore $store): void { Logger::debug('saml.LogoutStore: Cleaning logout store.'); @@ -225,7 +225,7 @@ class LogoutStore /** * Register a session in the SQL datastore. * - * @param \SimpleSAML\Store\SQL $store The datastore. + * @param \SimpleSAML\Store\SQLStore $store The datastore. * @param string $authId The authsource ID. * @param string $nameId The hash of the users NameID. * @param string $sessionIndex The SessionIndex of the user. @@ -233,7 +233,7 @@ class LogoutStore * @param string $sessionId */ private static function addSessionSQL( - Store\SQL $store, + Store\SQLStore $store, string $authId, string $nameId, string $sessionIndex, @@ -264,12 +264,12 @@ class LogoutStore /** * Retrieve sessions from the SQL datastore. * - * @param \SimpleSAML\Store\SQL $store The datastore. + * @param \SimpleSAML\Store\SQLStore $store The datastore. * @param string $authId The authsource ID. * @param string $nameId The hash of the users NameID. * @return array Associative array of SessionIndex => SessionId. */ - private static function getSessionsSQL(Store\SQL $store, string $authId, string $nameId): array + private static function getSessionsSQL(Store\SQLStore $store, string $authId, string $nameId): array { self::createLogoutTable($store); @@ -298,13 +298,13 @@ class LogoutStore /** * Retrieve all session IDs from a key-value store. * - * @param \SimpleSAML\Store $store The datastore. + * @param \SimpleSAML\Store\StoreInterface $store The datastore. * @param string $nameId The hash of the users NameID. * @param array $sessionIndexes The session indexes. * @return array Associative array of SessionIndex => SessionId. */ private static function getSessionsStore( - Store $store, + StoreInterface $store, string $nameId, array $sessionIndexes ): array { @@ -372,7 +372,7 @@ class LogoutStore /** @var string $sessionId */ $sessionId = $session->getSessionId(); - if ($store instanceof Store\SQL) { + if ($store instanceof Store\SQLStore) { self::addSessionSQL($store, $authId, $strNameId, $sessionIndex, $expire, $sessionId); } else { $store->set('saml.LogoutStore', $strNameId . ':' . $sessionIndex, $sessionId, $expire); @@ -411,7 +411,7 @@ class LogoutStore // Remove reference unset($sessionIndex); - if ($store instanceof Store\SQL) { + if ($store instanceof Store\SQLStore) { $sessions = self::getSessionsSQL($store, $authId, $strNameId); } else { if (empty($sessionIndexes)) { diff --git a/modules/saml/www/sp/metadata.php b/modules/saml/www/sp/metadata.php index 603209c53301c7b4ed03a3a40c3e211ffcee43fc..473117602124c0a4dccc86ae930d444e0e40a79e 100644 --- a/modules/saml/www/sp/metadata.php +++ b/modules/saml/www/sp/metadata.php @@ -7,7 +7,7 @@ use SimpleSAML\Error; use SimpleSAML\Locale\Translate; use SimpleSAML\Metadata; use SimpleSAML\Module; -use SimpleSAML\Store; +use SimpleSAML\Store\StoreFactory; use SimpleSAML\Utils; use SimpleSAML\XHTML\Template; use Symfony\Component\VarExporter\VarExporter; @@ -37,7 +37,7 @@ if (!($source instanceof Module\saml\Auth\Source\SP)) { $entityId = $source->getEntityId(); $spconfig = $source->getMetadata(); $metaArray20 = $source->getHostedMetadata(); -$store = Store::getInstance(); +$store = StoreFactory::getInstance(); $metaBuilder = new Metadata\SAMLBuilder($entityId); $metaBuilder->addMetadataSP20($metaArray20, $source->getSupportedProtocols()); diff --git a/modules/saml/www/sp/saml2-acs.php b/modules/saml/www/sp/saml2-acs.php index 585705c6ef64d9acf93e37518a52060347ef747f..56bc5eedbabc810f7793feeffcc83e25d87ad433 100644 --- a/modules/saml/www/sp/saml2-acs.php +++ b/modules/saml/www/sp/saml2-acs.php @@ -14,7 +14,7 @@ use SimpleSAML\Error; use SimpleSAML\Module; use SimpleSAML\Logger; use SimpleSAML\Session; -use SimpleSAML\Store; +use SimpleSAML\Store\StoreFactory; use SimpleSAML\Utils; if (!array_key_exists('PATH_INFO', $_SERVER)) { @@ -159,7 +159,7 @@ $foundAuthnStatement = false; foreach ($assertions as $assertion) { // check for duplicate assertion (replay attack) - $store = Store::getInstance(); + $store = StoreFactory::getInstance(); if ($store !== false) { $aID = $assertion->getId(); if ($store->get('saml.AssertionReceived', $aID) !== null) {