From b42309408c17ad2d2d6bd2a044b66d0dd4fa566e Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Wed, 11 Jun 2008 06:15:45 +0000
Subject: [PATCH] Add support for validating SAML metadata files.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@629 44740490-163a-0410-bde0-09ae8108e29a
---
 config-templates/config.php                   |  4 +-
 lib/SimpleSAML/Bindings/SAML20/HTTPPost.php   |  6 +--
 .../Bindings/SAML20/HTTPRedirect.php          |  8 ++--
 lib/SimpleSAML/Bindings/Shib13/HTTPPost.php   |  6 +--
 lib/SimpleSAML/Utilities.php                  | 40 ++++++++++++-------
 www/admin/metadata-converter.php              |  1 +
 6 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/config-templates/config.php b/config-templates/config.php
index b584d7b6a..8c4d762e7 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -41,10 +41,10 @@ $config = array (
 	'showerrors'            =>	true,
 
 	/**
-	 * This option allows you to enable validation of SAML messages against their
+	 * This option allows you to enable validation of XML data against its
 	 * schemas. A warning will be written to the log if validation fails.
 	 */
-	'debug.validatesamlmessages' => false,
+	'debug.validatexml' => false,
 
 	/**
 	 * This password must be kept secret, and modified from the default value 123.
diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
index cf7f0bbef..8a79c3ab2 100644
--- a/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
+++ b/lib/SimpleSAML/Bindings/SAML20/HTTPPost.php
@@ -20,7 +20,7 @@ class SimpleSAML_Bindings_SAML20_HTTPPost {
 	
 	public function sendResponseUnsigned($response, $idpentityid, $spentityid, $relayState = null, $endpoint = 'AssertionConsumerService') {
 
-		SimpleSAML_Utilities::validateSAMLMessage($response, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($response, 'saml20');
 
 		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
 		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
@@ -183,7 +183,7 @@ class SimpleSAML_Bindings_SAML20_HTTPPost {
 		}
 		$response = $responsedom->saveXML();
 		
-		SimpleSAML_Utilities::validateSAMLMessage($response, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($response, 'saml20');
 		
 		# openssl genrsa -des3 -out server.key 1024 
 		# openssl rsa -in server.key -out server.pem
@@ -231,7 +231,7 @@ class SimpleSAML_Bindings_SAML20_HTTPPost {
 		
 		$samlResponseXML = base64_decode( $rawResponse );
 
-		SimpleSAML_Utilities::validateSAMLMessage($samlResponseXML, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($samlResponseXML, 'saml20');
 		
 		//error_log("Response is: " . $samlResponseXML);
         
diff --git a/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php b/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php
index c9f610cfd..06065913d 100644
--- a/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php
+++ b/lib/SimpleSAML/Bindings/SAML20/HTTPRedirect.php
@@ -180,7 +180,7 @@ class SimpleSAML_Bindings_SAML20_HTTPRedirect {
 	
 	public function sendMessage($request, $localentityid, $remoteentityid, $relayState = null, $endpoint = 'SingleSignOnService', $direction = 'SAMLRequest', $mode = 'SP') {
 		
-		SimpleSAML_Utilities::validateSAMLMessage($request, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($request, 'saml20');
 
 		$redirectURL = $this->getRedirectURL($request, $localentityid, $remoteentityid, $relayState, $endpoint, $direction, $mode);
 		
@@ -234,7 +234,7 @@ class SimpleSAML_Bindings_SAML20_HTTPRedirect {
 			throw new Exception('Could not gzinflate base64 decoded SAMLRequest: ' . $error['message'] );
 		}		
 
-		SimpleSAML_Utilities::validateSAMLMessage($samlRequestXML, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($samlRequestXML, 'saml20');
 		
 		$samlRequest = new SimpleSAML_XML_SAML20_AuthnRequest($this->configuration, $this->metadata);
 	
@@ -272,7 +272,7 @@ class SimpleSAML_Bindings_SAML20_HTTPRedirect {
 			throw new Exception('Could not gzinflate base64 decoded SAMLRequest: ' . $error['message'] );
 		}		
 
-		SimpleSAML_Utilities::validateSAMLMessage($samlRequestXML, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($samlRequestXML, 'saml20');
 
 		$samlRequest = new SimpleSAML_XML_SAML20_LogoutRequest($this->configuration, $this->metadata);
 	
@@ -311,7 +311,7 @@ class SimpleSAML_Bindings_SAML20_HTTPRedirect {
 			throw new Exception('Could not gzinflate base64 decoded SAMLRequest: ' . $error['message'] );
 		}		
 
-		SimpleSAML_Utilities::validateSAMLMessage($samlRequestXML, 'saml20');
+		SimpleSAML_Utilities::validateXMLDocument($samlRequestXML, 'saml20');
 		
          
 		$samlRequest = new SimpleSAML_XML_SAML20_LogoutResponse($this->configuration, $this->metadata);
diff --git a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
index 36af8c220..49c0dd822 100644
--- a/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
+++ b/lib/SimpleSAML/Bindings/Shib13/HTTPPost.php
@@ -20,7 +20,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 	
 	public function sendResponseUnsigned($response, $idpentityid, $spentityid, $relayState = null, $endpoint = 'AssertionConsumerService') {
 
-		SimpleSAML_Utilities::validateSAMLMessage($response, 'saml11');
+		SimpleSAML_Utilities::validateXMLDocument($response, 'saml11');
 
 		$idpmd = $this->metadata->getMetaData($idpentityid, 'saml20-idp-hosted');
 		$spmd = $this->metadata->getMetaData($spentityid, 'saml20-sp-remote');
@@ -64,7 +64,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 	 */
 	public function sendResponse($response, $idpmetaindex, $spentityid, $relayState = null, $claimedacs = null) {
 
-		SimpleSAML_Utilities::validateSAMLMessage($response, 'saml11');
+		SimpleSAML_Utilities::validateXMLDocument($response, 'saml11');
 
 		$idpmd = $this->metadata->getMetaData($idpmetaindex, 'shib13-idp-hosted');
 		$spmd = $this->metadata->getMetaData($spentityid, 'shib13-sp-remote');
@@ -206,7 +206,7 @@ class SimpleSAML_Bindings_Shib13_HTTPPost {
 		
 		$samlResponseXML = base64_decode( $rawResponse );
 
-		SimpleSAML_Utilities::validateSAMLMessage($samlResponseXML, 'saml11');
+		SimpleSAML_Utilities::validateXMLDocument($samlResponseXML, 'saml11');
         
 		$samlResponse = new SimpleSAML_XML_Shib13_AuthnResponse($this->configuration, $this->metadata);
 	
diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index 474cee47a..abe0bf12a 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -793,41 +793,51 @@ class SimpleSAML_Utilities {
 
 
 	/**
-	 * This function performs some sanity checks on SAML messages, and optionally validates them
+	 * This function performs some sanity checks on XML documents, and optionally validates them
 	 * against their schema. A warning will be printed to the log if validation fails.
 	 *
-	 * @param $message  The message which should be validated.
-	 * @param $type     The type of message - can be either 'saml20' or 'saml11'.
+	 * @param $message  The message which should be validated, as a string.
+	 * @param $type     The type of document - can be either 'saml20', 'saml11' or 'saml-meta'.
 	 */
-	public static function validateSAMLMessage($message, $type) {
+	public static function validateXMLDocument($message, $type) {
 		assert('is_string($message)');
-		assert($type === 'saml11' || $type === 'saml20');
+		assert($type === 'saml11' || $type === 'saml20' || $type === 'saml-meta');
 
 		/* A SAML message should not contain a doctype-declaration. */
 		if(strpos($message, '<!DOCTYPE') !== FALSE) {
-			throw new Exception('SAML message contained a doctype declaration.');
+			throw new Exception('XML contained a doctype declaration.');
 		}
 
-		$enabled = SimpleSAML_Configuration::getInstance()->getValue('debug.validatesamlmessages', NULL);
+		$enabled = SimpleSAML_Configuration::getInstance()->getValue('debug.validatexml', NULL);
 		if($enabled === NULL) {
 			/* Fall back to old configuration option. */
-			$enabled = SimpleSAML_Configuration::getInstance()->getValue('debug.validatesaml2messages', FALSE);
-			if(!is_bool($enabled)) {
-				throw new Exception('Expected "debug.validatesaml2messages" to be set to a boolean value.');
+			$enabled = SimpleSAML_Configuration::getInstance()->getValue('debug.validatesamlmessages', NULL);
+			if($enabled === NULL) {
+				/* Fall back to even older configuration option. */
+				$enabled = SimpleSAML_Configuration::getInstance()->getValue('debug.validatesaml2messages', FALSE);
+				if(!is_bool($enabled)) {
+					throw new Exception('Expected "debug.validatesaml2messages" to be set to a boolean value.');
+				}
+			} elseif(!is_bool($enabled)) {
+				throw new Exception('Expected "debug.validatexml" to be set to a boolean value.');
 			}
-		} elseif(!is_bool($enabled)) {
-			throw new Exception('Expected "debug.validatesamlmessages" to be set to a boolean value.');
 		}
 
 		if(!$enabled) {
 			return;
 		}
 
-		if($type === 'saml11') {
+		switch($type) {
+		case 'saml11':
 			$result = self::validateXML($message, 'oasis-sstc-saml-schema-protocol-1.1.xsd');
-		} elseif($type === 'saml20') {
+			break;
+		case 'saml20':
 			$result = self::validateXML($message, 'saml-schema-protocol-2.0.xsd');
-		} else {
+			break;
+		case 'saml-meta':
+			$result = self::validateXML($message, 'saml-schema-metadata-2.0.xsd');
+			break;
+		default:
 			throw new Exception('Invalid message type.');
 		}
 
diff --git a/www/admin/metadata-converter.php b/www/admin/metadata-converter.php
index 05b60d3a7..52c77500a 100644
--- a/www/admin/metadata-converter.php
+++ b/www/admin/metadata-converter.php
@@ -9,6 +9,7 @@ try {
 	if(array_key_exists('xmldata', $_POST)) {
 		$xmldata = $_POST['xmldata'];
 
+		SimpleSAML_Utilities::validateXMLDocument($xmldata, 'saml-meta');
 		$entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($xmldata);
 
 		/* Get all metadata for the entities. */
-- 
GitLab