From 5c65b72fd76006d056cc693c993766cd66f68ede Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaime=20P=C3=A9rez=20Crespo?= <jaime.perez@uninett.no>
Date: Mon, 17 Feb 2014 14:08:07 +0000
Subject: [PATCH] Fixes to ADFS metadata to allow interoperability.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3364 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/Metadata/Signer.php   |  7 +++++-
 modules/adfs/lib/XMLSecurityDSig.php | 32 ++++++++++++++++++++++++++++
 modules/adfs/www/idp/metadata.php    | 22 +++++++++----------
 3 files changed, 49 insertions(+), 12 deletions(-)
 create mode 100644 modules/adfs/lib/XMLSecurityDSig.php

diff --git a/lib/SimpleSAML/Metadata/Signer.php b/lib/SimpleSAML/Metadata/Signer.php
index d6964690f..a04221535 100644
--- a/lib/SimpleSAML/Metadata/Signer.php
+++ b/lib/SimpleSAML/Metadata/Signer.php
@@ -173,7 +173,12 @@ class SimpleSAML_Metadata_Signer {
 		$rootNode = $xml->firstChild;
 
 		/* Sign the metadata with our private key. */
-		$objXMLSecDSig = new XMLSecurityDSig();
+		if ($type == 'ADFS IdP') {
+			$objXMLSecDSig = new sspmod_adfs_XMLSecurityDSig($metadataString);
+        } else {
+			$objXMLSecDSig = new XMLSecurityDSig();
+        }
+
 		$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
 
 		$objXMLSecDSig->addReferenceList(array($rootNode), XMLSecurityDSig::SHA1,
diff --git a/modules/adfs/lib/XMLSecurityDSig.php b/modules/adfs/lib/XMLSecurityDSig.php
new file mode 100644
index 000000000..d5ab2fd21
--- /dev/null
+++ b/modules/adfs/lib/XMLSecurityDSig.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * This class should be considered a temporary workaround to
+ * solve the lack of custom formatting in XMLSecurityDSig
+ * (xmlseclibs). It should be possible to either configure
+ * the original class to avoid formatting, or to use a custom
+ * template for the signature.
+ *
+ * @todo Move this functionality to xmlseclibs.
+ *
+ * @author Daniel Tsosie
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_adfs_XMLSecurityDSig extends XMLSecurityDSig {
+
+    function __construct($metaxml) {
+        $sigdoc = new DOMDocument();
+        $template = '';
+
+        if (strpos("\n", $metaxml) === FALSE) {
+            foreach (explode("\n", self::template) as $line)
+                $template .= trim($line);
+        } else {
+            $template = self::template;
+        }
+
+        $sigdoc->loadXML($template);
+        $this->sigNode = $sigdoc->documentElement;
+    }
+}
diff --git a/modules/adfs/www/idp/metadata.php b/modules/adfs/www/idp/metadata.php
index fd563ba40..f1a191a41 100644
--- a/modules/adfs/www/idp/metadata.php
+++ b/modules/adfs/www/idp/metadata.php
@@ -117,14 +117,16 @@ try {
 			'name' => $config->getString('technicalcontact_name', NULL),
 		));
 	}
-	$metaxml = explode("\n", $metaBuilder->getEntityDescriptorText());
-    unset($metaxml[0]);
-    $metaxml = implode("\n", $metaxml);
+	$output_xhtml = array_key_exists('output', $_GET) && $_GET['output'] == 'xhtml';
+	$metaxml = $metaBuilder->getEntityDescriptorText($output_xhtml);
+	if (!$output_xhtml) {
+        $metaxml = str_replace("\n", '', $metaxml);
+    }
 
 	/* Sign the metadata if enabled. */
 	$metaxml = SimpleSAML_Metadata_Signer::sign($metaxml, $idpmeta->toArray(), 'ADFS IdP');
 
-	if (array_key_exists('output', $_GET) && $_GET['output'] == 'xhtml') {
+	if ($output_xhtml) {
 		$defaultidp = $config->getString('default-adfs-idp', NULL);
 
 		$t = new SimpleSAML_XHTML_Template($config, 'metadata.php', 'admin');
@@ -138,19 +140,17 @@ try {
 		$t->show();
 
 	} else {
-
 		header('Content-Type: application/xml');
 
+        // make sure to export only the md:EntityDescriptor
+		$metaxml = substr($metaxml, strpos($metaxml, '<md:EntityDescriptor'));
+        // 22 = strlen('</md:EntityDescriptor>')
+		$metaxml = substr($metaxml, 0,  strrpos($metaxml, '</md:EntityDescriptor>') + 22);
 		echo $metaxml;
-		exit(0);
 
+		exit(0);
 	}
 
-
-
 } catch(Exception $exception) {
-
 	throw new SimpleSAML_Error_Error('METADATA', $exception);
-
 }
-
-- 
GitLab