From 510ba780c77228649c87fe2ef8f9860113af64d1 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Tue, 1 Jul 2008 11:33:36 +0000
Subject: [PATCH] SAML2: Validate signature om samlp:Response before decrypting
 Assertions.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@736 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/XML/SAML20/AuthnResponse.php | 32 ++++++++++++++-------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
index 26847784a..b963b8a6a 100644
--- a/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
+++ b/lib/SimpleSAML/XML/SAML20/AuthnResponse.php
@@ -98,6 +98,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 		$xPath = new DOMXpath($dom);
 		$xPath->registerNamespace("saml", self::SAML2_ASSERT_NS);
 		$xPath->registerNamespace("samlp", self::SAML2_PROTOCOL_NS);
+		$xPath->registerNamespace("ds", 'http://www.w3.org/2000/09/xmldsig#');
 
 		return $xPath->query($query, $node);
 	}
@@ -233,12 +234,14 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 	}
 
 	/**
-	 * This function validates the signature element of this response. It will throw an exception
-	 * if it is unable to validate the signature.
+	 * Validate the signature in the given node.
+	 *
+	 * The node should either be a samlp:Response node, or a saml:Assertion node.
+	 * An exception will be thrown if an error occurs during validation.
+	 *
+	 * @param $node  The node which contains the ds:Signature element.
 	 */
-	private function validateSignature() {
-	
-		$dom = $this->getDOM();
+	private function validateSignature($node) {
 
 		/* Get the metadata of the issuer. */
 		$md = $this->metadata->getMetaData($this->issuer, 'saml20-idp-remote');
@@ -251,7 +254,7 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 			}
 		}
 		/* Validate the signature. */
-		$this->validator = new SimpleSAML_XML_Validator($dom, 'ID', $publickey);
+		$this->validator = new SimpleSAML_XML_Validator($node, 'ID', $publickey);
 		
 		if (!$publickey) {
 			/* Get fingerprint for the certificate of the issuer. */
@@ -489,12 +492,21 @@ class SimpleSAML_XML_SAML20_AuthnResponse extends SimpleSAML_XML_AuthnResponse {
 		if ($status == 'urn:oasis:names:tc:SAML:2.0:status:Success' ) {
 			/* Find the issuer of this response. */
 			$this->issuer = $this->findIssuer();
+
+			/* Check for signature in the saml:Response-element, and validate it if present. */
+			$signature = $this->doXPathQuery('/samlp:Response/ds:Signature');
+			if($signature->length > 0) {
+				$this->validateSignature($signature->item(0)->parentNode);
+			}
 	
 			$this->decryptAssertion();
-	
-			/* Validate the signature element. */
-			$this->validateSignature();
-	
+
+			/* Check for signature in the saml:Assertion-element(s), and validate it if present. */
+			$signature = $this->doXPathQuery('/samlp:Response/saml:Assertion/ds:Signature');
+			if($signature->length > 0) {
+				$this->validateSignature($signature->item(0)->parentNode);
+			}
+
 			/* Process all assertions. */
 			$assertions = $this->doXPathQuery('/samlp:Response/saml:Assertion');
 			foreach($assertions as $assertion) {
-- 
GitLab