From c1740438d07afb3ffa3ae9441f80bf07e4f422bf Mon Sep 17 00:00:00 2001
From: Thijs Kinkhorst <thijs@kinkhorst.com>
Date: Mon, 29 Jul 2019 13:04:46 +0000
Subject: [PATCH] Make certificate download work in admin module.

---
 modules/admin/lib/FederationController.php | 41 +++++++++++++++++++++-
 modules/admin/routes.yaml                  |  3 ++
 modules/admin/templates/federation.twig    |  2 +-
 modules/saml/lib/Auth/Source/SP.php        | 10 +++---
 4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/modules/admin/lib/FederationController.php b/modules/admin/lib/FederationController.php
index 8803ab6c9..26586b850 100644
--- a/modules/admin/lib/FederationController.php
+++ b/modules/admin/lib/FederationController.php
@@ -18,6 +18,8 @@ use SimpleSAML\Module\saml\IdP\SAML2 as SAML2_IdP;
 use SimpleSAML\Utils;
 use SimpleSAML\XHTML\Template;
 use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\ResponseHeaderBag;
 
 /**
  * Controller class for the admin module.
@@ -295,7 +297,7 @@ class FederationController
             $entities[$index]['type'] = $entity['metadata-set'];
             foreach ($entity['metadata_array']['keys'] as $kidx => $key) {
                 $key['url'] = Module::getModuleURL(
-                    'admin/cert',
+                    'admin/federation/cert',
                     [
                         'set' => $entity['metadata-set'],
                         'idp' => $entity['metadata-index'],
@@ -449,4 +451,41 @@ class FederationController
         $this->menu->addOption('logout', $t->data['logouturl'], Translate::noop('Log out'));
         return $this->menu->insert($t);
     }
+
+    /**
+     * Download a certificate for a given entity.
+     *
+     * @param Request $request The current request.
+     *
+     * @return Response PEM-encoded certificate.
+     */
+    public function downloadCert(Request $request)
+    {
+        Utils\Auth::requireAdmin();
+
+        $set = $request->get('set');
+        $prefix = $request->get('prefix');
+
+        if ($set === 'saml20-sp-hosted') {
+                $sourceID = $request->get('source');
+                $source = \SimpleSAML\Auth\Source::getById($sourceID);
+                $mdconfig = $source->getMetadata();
+        } else {
+                $entityID = $request->get('entity');
+                $mdconfig = $this->mdHandler->getMetaDataConfig($entityID, $set);
+        }
+
+        $certInfo = Utils\Crypto::loadPublicKey($mdconfig, true, $prefix);
+
+        $response = new Response($certInfo['PEM']);
+        $disposition = $response->headers->makeDisposition(
+            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
+            'cert.pem'
+        );
+
+        $response->headers->set('Content-Disposition', $disposition);
+        $response->headers->set('Content-Type', 'application/x-pem-file');
+
+        return $response;
+    }
 }
diff --git a/modules/admin/routes.yaml b/modules/admin/routes.yaml
index 672ca0f2b..ac07bacb1 100644
--- a/modules/admin/routes.yaml
+++ b/modules/admin/routes.yaml
@@ -13,6 +13,9 @@ admin-test:
 admin-fed:
     path:       /federation
     defaults:   { _controller: 'SimpleSAML\Module\admin\FederationController::main' }
+admin-fed-cert:
+    path:       /federation/cert
+    defaults:   { _controller: 'SimpleSAML\Module\admin\FederationController::downloadCert' }
 admin-fed-converter:
     path:       /federation/metadata-converter
     defaults:   { _controller: 'SimpleSAML\Module\admin\FederationController::metadataConverter' }
diff --git a/modules/admin/templates/federation.twig b/modules/admin/templates/federation.twig
index ab2921b53..44f698991 100644
--- a/modules/admin/templates/federation.twig
+++ b/modules/admin/templates/federation.twig
@@ -71,9 +71,9 @@
                 {#- #}$metadata['{{ set.entityid }}'] = {{ set.metadata_array }};{# -#}
               </div>
             </dd>
-            <dt>{% trans %}Certificates{% endtrans %}</dt>
             {%- for cert in set.certificates %}
               {%- if loop.first %}
+              <dt>{% trans %}Certificates{% endtrans %}</dt>
 
               <ul>
               {%- endif %}
diff --git a/modules/saml/lib/Auth/Source/SP.php b/modules/saml/lib/Auth/Source/SP.php
index c4b124a84..2ef32cc90 100644
--- a/modules/saml/lib/Auth/Source/SP.php
+++ b/modules/saml/lib/Auth/Source/SP.php
@@ -219,9 +219,10 @@ class SP extends \SimpleSAML\Auth\Source
                 'X509Certificate' => $certInfo['certData'],
                 'prefix' => 'new_',
                 'url' => Module::getModuleURL(
-                    'admin/cert',
+                    'admin/federation/cert',
                     [
-                        'sp' => $this->getAuthId(),
+                        'set' => 'saml20-sp-hosted',
+                        'source' => $this->getAuthId(),
                         'prefix' => 'new_'
                     ]
                 ),
@@ -238,9 +239,10 @@ class SP extends \SimpleSAML\Auth\Source
                 'X509Certificate' => $certInfo['certData'],
                 'prefix' => '',
                 'url' => Module::getModuleURL(
-                    'admin/cert',
+                    'admin/federation/cert',
                     [
-                        'sp' => $this->getAuthId(),
+                        'set' => 'saml20-sp-hosted',
+                        'source' => $this->getAuthId(),
                         'prefix' => ''
                     ]
                 ),
-- 
GitLab