From 50cada35e7fb0f880e4996ad308797dd34f60782 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Thu, 2 Aug 2012 10:48:45 +0000
Subject: [PATCH] saml: Add "encryption.blacklisted-algorithms"-option.

This option allows us to disable some encryption algorithms.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3139 44740490-163a-0410-bde0-09ae8108e29a
---
 docs/simplesamlphp-reference-idp-hosted.txt |  5 ++++
 docs/simplesamlphp-reference-idp-remote.txt |  7 ++++++
 docs/simplesamlphp-reference-sp-remote.txt  |  7 ++++++
 modules/saml/docs/sp.txt                    |  6 +++++
 modules/saml/lib/Message.php                | 28 +++++++++++++++++++--
 modules/saml/www/sp/saml2-logout.php        |  4 ++-
 6 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/docs/simplesamlphp-reference-idp-hosted.txt b/docs/simplesamlphp-reference-idp-hosted.txt
index e0b9a21bb..b2d14bab0 100644
--- a/docs/simplesamlphp-reference-idp-hosted.txt
+++ b/docs/simplesamlphp-reference-idp-hosted.txt
@@ -165,6 +165,11 @@ The following SAML 2.0 options are available:
 
 :   (This option was previously named `AttributeNameFormat`.)
 
+`encryption.blacklisted-algorithms`
+:   Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
+
+:   Note that this option can be set for each SP in the [SP-remote metadata](./simplesamlphp-reference-sp-remote).
+
 `https.certificate`
 :   The certificate used by the webserver when handling connections.
     This certificate will be added to the generated metadata of the IdP,
diff --git a/docs/simplesamlphp-reference-idp-remote.txt b/docs/simplesamlphp-reference-idp-remote.txt
index d39812cce..e8af4109a 100644
--- a/docs/simplesamlphp-reference-idp-remote.txt
+++ b/docs/simplesamlphp-reference-idp-remote.txt
@@ -98,6 +98,13 @@ SAML 2.0 options
 
 The following SAML 2.0 options are available:
 
+`encryption.blacklisted-algorithms`
+:   Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
+
+:   Note that this option also exists in the SP configuration. This
+    entry in the IdP-remote metadata overrides the option in the
+    [SP configuration](./saml:sp).
+
 `nameid.encryption`
 :   Whether NameIDs sent to this IdP should be encrypted. The default
     value is `FALSE`.
diff --git a/docs/simplesamlphp-reference-sp-remote.txt b/docs/simplesamlphp-reference-sp-remote.txt
index 16b54b358..73eca20c8 100644
--- a/docs/simplesamlphp-reference-sp-remote.txt
+++ b/docs/simplesamlphp-reference-sp-remote.txt
@@ -155,6 +155,13 @@ The following SAML 2.0 options are available:
 
 :   (This option was previously named `AttributeNameFormat`.)
 
+`encryption.blacklisted-algorithms`
+:   Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
+
+:   Note that this option also exists in the IdP-hosted metadata. This
+    entry in the SP-remote metadata overrides the option in the
+    [IdP-hosted metadata](./simplesamlphp-reference-idp-hosted).
+
 `ForceAuthn`
 :   Set this `TRUE` to force the user to reauthenticate when the IdP
     receives authentication requests from this SP. The default is
diff --git a/modules/saml/docs/sp.txt b/modules/saml/docs/sp.txt
index 673d69ca9..e536aac29 100644
--- a/modules/saml/docs/sp.txt
+++ b/modules/saml/docs/sp.txt
@@ -227,6 +227,12 @@ Options
     If this is unset, the IdP discovery service specified in the global option `idpdisco.url.{saml20|shib13}` in `config/config.php` will be used.
     If that one is also unset, the builtin default discovery service will be used.
 
+`encryption.blacklisted-algorithms`
+:   Blacklisted encryption algorithms. This is an array containing the algorithm identifiers.
+
+:   Note that this option can be set for each IdP in the [IdP-remote metadata](./simplesamlphp-reference-idp-remote).
+
+:   *Note*: SAML 2 specific.
 
 `entityID`
 :   The entity ID this SP should use.
diff --git a/modules/saml/lib/Message.php b/modules/saml/lib/Message.php
index c5ad1b5b1..02eca94cc 100644
--- a/modules/saml/lib/Message.php
+++ b/modules/saml/lib/Message.php
@@ -287,6 +287,26 @@ class sspmod_saml_Message {
 	}
 
 
+	/**
+	 * Retrieve blacklisted algorithms.
+	 *
+	 * Remote configuration overrides local configuration.
+	 *
+	 * @param SimpleSAML_Configuration $srcMetadata  The metadata of the sender.
+	 * @param SimpleSAML_Configuration $dstMetadata  The metadata of the recipient.
+	 * @return array  Array of blacklisted algorithms.
+	 */
+	public static function getBlacklistedAlgorithms(SimpleSAML_Configuration $srcMetadata,
+		SimpleSAML_Configuration $dstMetadata) {
+
+		$blacklist = $srcMetadata->getArray('encryption.blacklisted-algorithms', NULL);
+		if ($blacklist === NULL) {
+			$blacklist = $dstMetadata->getArray('encryption.blacklisted-algorithms', array());
+		}
+		return $blacklist;
+	}
+
+
 	/**
 	 * Decrypt an assertion.
 	 *
@@ -322,10 +342,12 @@ class sspmod_saml_Message {
 			throw new SimpleSAML_Error_Exception('Error decrypting assertion: ' . $e->getMessage());
 		}
 
+		$blacklist = self::getBlacklistedAlgorithms($srcMetadata, $dstMetadata);
+
 		$lastException = NULL;
 		foreach ($keys as $i => $key) {
 			try {
-				$ret = $assertion->getAssertion($key);
+				$ret = $assertion->getAssertion($key, $blacklist);
 				SimpleSAML_Logger::debug('Decryption with key #' . $i . ' succeeded.');
 				return $ret;
 			} catch (Exception $e) {
@@ -695,10 +717,12 @@ class sspmod_saml_Message {
 				throw new SimpleSAML_Error_Exception('Error decrypting NameID: ' . $e->getMessage());
 			}
 
+			$blacklist = self::getBlacklistedAlgorithms($idpMetadata, $spMetadata);
+
 			$lastException = NULL;
 			foreach ($keys as $i => $key) {
 				try {
-					$assertion->decryptNameId($key);
+					$assertion->decryptNameId($key, $blacklist);
 					SimpleSAML_Logger::debug('Decryption with key #' . $i . ' succeeded.');
 					$lastException = NULL;
 					break;
diff --git a/modules/saml/www/sp/saml2-logout.php b/modules/saml/www/sp/saml2-logout.php
index c2e17b0f9..caf09b046 100644
--- a/modules/saml/www/sp/saml2-logout.php
+++ b/modules/saml/www/sp/saml2-logout.php
@@ -70,10 +70,12 @@ if ($message instanceof SAML2_LogoutResponse) {
 			throw new SimpleSAML_Error_Exception('Error decrypting NameID: ' . $e->getMessage());
 		}
 
+		$blacklist = sspmod_saml_Message::getBlacklistedAlgorithms($idpMetadata, $spMetadata);
+
 		$lastException = NULL;
 		foreach ($keys as $i => $key) {
 			try {
-				$message->decryptNameId($key);
+				$message->decryptNameId($key, $blacklist);
 				SimpleSAML_Logger::debug('Decryption with key #' . $i . ' succeeded.');
 				$lastException = NULL;
 				break;
-- 
GitLab