From 1630c55e2b93ca3aeb7d7c45ef7c017a81c890c6 Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tvdijen@gmail.com>
Date: Mon, 30 Aug 2021 23:50:37 +0200
Subject: [PATCH] Pull configuration out of factory

---
 lib/SimpleSAML/SessionHandler.php             |  5 ++-
 lib/SimpleSAML/Store/StoreFactory.php         |  7 ++-
 modules/saml/lib/Auth/Source/SP.php           |  5 ++-
 modules/saml/lib/IdP/SQLNameID.php            | 16 ++++---
 modules/saml/lib/SP/LogoutStore.php           | 11 ++++-
 modules/saml/www/sp/metadata.php              |  4 +-
 modules/saml/www/sp/saml2-acs.php             |  6 ++-
 .../lib/SimpleSAML/Store/StoreFactoryTest.php | 43 +++++++++++++++----
 tests/modules/saml/lib/IdP/SQLNameIDTest.php  | 10 +++--
 www/saml2/idp/ArtifactResolutionService.php   |  3 +-
 10 files changed, 81 insertions(+), 29 deletions(-)

diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php
index b26bc16ad..c69e8f233 100644
--- a/lib/SimpleSAML/SessionHandler.php
+++ b/lib/SimpleSAML/SessionHandler.php
@@ -135,7 +135,10 @@ abstract class SessionHandler
      */
     private static function createSessionHandler(): void
     {
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
+        $store = StoreFactory::getInstance($storeType);
         if ($store === false) {
             self::$sessionHandler = new SessionHandlerPHP();
         } else {
diff --git a/lib/SimpleSAML/Store/StoreFactory.php b/lib/SimpleSAML/Store/StoreFactory.php
index f3aa7ea76..9f3c93f49 100644
--- a/lib/SimpleSAML/Store/StoreFactory.php
+++ b/lib/SimpleSAML/Store/StoreFactory.php
@@ -30,19 +30,17 @@ abstract class StoreFactory implements Utils\ClearableState
     /**
      * Retrieve our singleton instance.
      *
+     * @param string $storeType The type of store we need to instantiate
      * @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(string $storeType)
     {
         if (self::$instance !== null) {
             return self::$instance;
         }
 
-        $config = Configuration::getInstance();
-        $storeType = $config->getString('store.type', 'phpsession');
-
         switch ($storeType) {
             case 'phpsession':
                 // we cannot support advanced features with the PHP session store
@@ -62,6 +60,7 @@ abstract class StoreFactory implements Utils\ClearableState
                 try {
                     $className = Module::resolveClass($storeType, 'StoreInterface');
                 } catch (Exception $e) {
+                    $config = Configuration::getInstance();
                     $c = $config->toArray();
                     $c['store.type'] = 'phpsession';
                     throw new Error\CriticalConfigurationError(
diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index 0bfb57c54..93e40e922 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -386,7 +386,10 @@ class SP extends \SimpleSAML\Auth\Source
      */
     private function getSLOEndpoints(): array
     {
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
+        $store = StoreFactory::getInstance($storeType);
         $bindings = $this->metadata->getArray(
             'SingleLogoutServiceBinding',
             [
diff --git a/modules/saml/lib/IdP/SQLNameID.php b/modules/saml/lib/IdP/SQLNameID.php
index 604da6d20..7a43e1016 100644
--- a/modules/saml/lib/IdP/SQLNameID.php
+++ b/modules/saml/lib/IdP/SQLNameID.php
@@ -158,12 +158,16 @@ class SQLNameID
      */
     private static function getStore(): Store\SQLStore
     {
-        $store = StoreFactory::getInstance();
-        if (!($store instanceof Store\SQLStore)) {
-            throw new Error\Exception(
-                'SQL NameID store requires SimpleSAMLphp to be configured with a SQL datastore.'
-            );
-        }
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
+        $store = StoreFactory::getInstance($storeType);
+        Assert::isInstanceOf(
+            $store,
+            Store\SQLStore::class,
+            'SQL NameID store requires SimpleSAMLphp to be configured with a SQL datastore.',
+            Error\Exception::class
+        );
 
         return $store;
     }
diff --git a/modules/saml/lib/SP/LogoutStore.php b/modules/saml/lib/SP/LogoutStore.php
index b021f2420..e6205ce6e 100644
--- a/modules/saml/lib/SP/LogoutStore.php
+++ b/modules/saml/lib/SP/LogoutStore.php
@@ -8,6 +8,7 @@ use Exception;
 use PDO;
 use SAML2\XML\saml\NameID;
 use SimpleSAML\Assert\Assert;
+use SimpleSAML\Configuration;
 use SimpleSAML\Logger;
 use SimpleSAML\Session;
 use SimpleSAML\Store;
@@ -209,7 +210,10 @@ class LogoutStore
             $sessionIndex = $randomUtils->generateID();
         }
 
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
+        $store = StoreFactory::getInstance($storeType);
         if ($store === false) {
             // We don't have a datastore.
             return;
@@ -245,7 +249,10 @@ class LogoutStore
      */
     public static function logoutSessions(string $authId, NameID $nameId, array $sessionIndexes)
     {
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
+        $store = StoreFactory::getInstance($storeType);
         if ($store === false) {
             // We don't have a datastore
             return false;
diff --git a/modules/saml/www/sp/metadata.php b/modules/saml/www/sp/metadata.php
index 473117602..4a9fabcb5 100644
--- a/modules/saml/www/sp/metadata.php
+++ b/modules/saml/www/sp/metadata.php
@@ -37,7 +37,9 @@ if (!($source instanceof Module\saml\Auth\Source\SP)) {
 $entityId = $source->getEntityId();
 $spconfig = $source->getMetadata();
 $metaArray20 = $source->getHostedMetadata();
-$store = StoreFactory::getInstance();
+
+$storeType = $config->getString('store.type', 'phpsession');
+$store = StoreFactory::getInstance($storeType);
 
 $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 56bc5eedb..23aad3391 100644
--- a/modules/saml/www/sp/saml2-acs.php
+++ b/modules/saml/www/sp/saml2-acs.php
@@ -10,6 +10,7 @@ use SAML2\HTTPArtifact;
 use SAML2\Response;
 use SimpleSAML\Assert\Assert;
 use SimpleSAML\Auth;
+use SimpleSAML\Configuration;
 use SimpleSAML\Error;
 use SimpleSAML\Module;
 use SimpleSAML\Logger;
@@ -159,7 +160,10 @@ $foundAuthnStatement = false;
 
 foreach ($assertions as $assertion) {
     // check for duplicate assertion (replay attack)
-    $store = StoreFactory::getInstance();
+    $config = Configuration::getInstance();
+    $storeType = $config->getString('store.type', 'phpsession');
+
+    $store = StoreFactory::getInstance($storeType);
     if ($store !== false) {
         $aID = $assertion->getId();
         if ($store->get('saml.AssertionReceived', $aID) !== null) {
diff --git a/tests/lib/SimpleSAML/Store/StoreFactoryTest.php b/tests/lib/SimpleSAML/Store/StoreFactoryTest.php
index 347cf3992..3164d5f1c 100644
--- a/tests/lib/SimpleSAML/Store/StoreFactoryTest.php
+++ b/tests/lib/SimpleSAML/Store/StoreFactoryTest.php
@@ -31,8 +31,11 @@ class StoreFactoryTest extends TestCase
     {
         Configuration::loadFromArray([], '[ARRAY]', 'simplesaml');
 
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
         /** @var false $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
 
         $this->assertFalse($store);
     }
@@ -43,10 +46,15 @@ class StoreFactoryTest extends TestCase
      */
     public function phpSessionStore(): void
     {
-        Configuration::loadFromArray([], '[ARRAY]', 'simplesaml');
+        Configuration::loadFromArray([
+            'store.type' => 'phpsession',
+        ], '[ARRAY]', 'simplesaml');
+
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
 
         /** @var false $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
 
         $this->assertFalse($store);
     }
@@ -61,7 +69,10 @@ class StoreFactoryTest extends TestCase
             'store.type'                    => 'memcache',
         ], '[ARRAY]', 'simplesaml');
 
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+
+        $store = StoreFactory::getInstance($storeType);
 
         $this->assertInstanceOf(Store\MemcacheStore::class, $store);
     }
@@ -77,8 +88,11 @@ class StoreFactoryTest extends TestCase
             'store.redis.prefix'            => 'phpunit_',
         ], '[ARRAY]', 'simplesaml');
 
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+
         /** @psalm-var \SimpleSAML\Store\RedisStore $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
         $store->redis = $this->getMockBuilder(Client::class)
                                    ->setMethods(['get', 'set', 'setex', 'del', 'disconnect', '__destruct'])
                                    ->disableOriginalConstructor()
@@ -99,7 +113,10 @@ class StoreFactoryTest extends TestCase
             'store.sql.prefix'              => 'phpunit_',
         ], '[ARRAY]', 'simplesaml');
 
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+
+        $store = StoreFactory::getInstance($storeType);
 
         $this->assertInstanceOf(Store\SQLStore::class, $store);
     }
@@ -116,7 +133,10 @@ class StoreFactoryTest extends TestCase
             'store.sql.prefix'              => 'phpunit_',
         ], '[ARRAY]', 'simplesaml');
 
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+
+        $store = StoreFactory::getInstance($storeType);
 
         $this->assertInstanceOf(Store\SQLStore::class, $store);
     }
@@ -134,7 +154,10 @@ class StoreFactoryTest extends TestCase
             'store.sql.prefix'              => 'phpunit_',
         ], '[ARRAY]', 'simplesaml');
 
-        StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+
+        StoreFactory::getInstance($storeType);
     }
 
 
@@ -143,8 +166,10 @@ class StoreFactoryTest extends TestCase
     protected function tearDown(): void
     {
         $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type', 'phpsession');
+
         /** @var \SimpleSAML\Store\StoreInterface $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
 
         $this->clearInstance($config, Configuration::class);
         $this->clearInstance($store, StoreFactory::class);
diff --git a/tests/modules/saml/lib/IdP/SQLNameIDTest.php b/tests/modules/saml/lib/IdP/SQLNameIDTest.php
index 098a68702..e12629ae7 100644
--- a/tests/modules/saml/lib/IdP/SQLNameIDTest.php
+++ b/tests/modules/saml/lib/IdP/SQLNameIDTest.php
@@ -46,8 +46,9 @@ class SQLNameIDTest extends TestCase
         ], '[ARRAY]', 'simplesaml');
         $this->addGetDelete();
         $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
         /** @var \SimpleSAML\Store\StoreInterface $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
         $this->clearInstance($config, Configuration::class);
         $this->clearInstance($store, StoreFactory::class);
     }
@@ -62,13 +63,16 @@ class SQLNameIDTest extends TestCase
         Configuration::loadFromArray([
             'store.type'                    => 'memcache',
         ], '[ARRAY]', 'simplesaml');
-        $store = StoreFactory::getInstance();
+        $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
+        $store = StoreFactory::getInstance($storeType);
         $this->assertInstanceOf(Store\MemcacheStore::class, $store);
         $this->expectException(Error\Exception::class);
         $this->addGetDelete();
         $config = Configuration::getInstance();
+        $storeType = $config->getString('store.type');
         /** @var \SimpleSAML\Store\StoreInterface $store */
-        $store = StoreFactory::getInstance();
+        $store = StoreFactory::getInstance($storeType);
         $this->clearInstance($config, Configuration::class);
         $this->clearInstance($store, StoreFactory::class);
     }
diff --git a/www/saml2/idp/ArtifactResolutionService.php b/www/saml2/idp/ArtifactResolutionService.php
index be3d121db..5e91f3fc3 100644
--- a/www/saml2/idp/ArtifactResolutionService.php
+++ b/www/saml2/idp/ArtifactResolutionService.php
@@ -35,7 +35,8 @@ if (!$idpMetadata->getBoolean('saml20.sendartifact', false)) {
     throw new Error\Error('NOACCESS');
 }
 
-$store = StoreFactory::getInstance();
+$storeType = $config->getString('store.type', 'phpsession');
+$store = StoreFactory::getInstance($storeType);
 if ($store === false) {
     throw new Exception('Unable to send artifact without a datastore configured.');
 }
-- 
GitLab