From c015b70b01971c959ee2d0f87d9310392b1732cd Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Fri, 6 Jun 2008 11:57:47 +0000
Subject: [PATCH] Add support for using a custom url for IdP discovery.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@615 44740490-163a-0410-bde0-09ae8108e29a
---
 config-templates/config.php      | 10 ++++++++++
 docs/source/simplesamlphp-sp.xml | 26 ++++++++++++++++++++++++++
 www/admin/metadata.php           |  4 ++--
 www/saml2/sp/initSSO.php         | 18 +++++++++++++++++-
 www/shib13/sp/initSSO.php        | 29 +++++++++++++++++++++++------
 5 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/config-templates/config.php b/config-templates/config.php
index 812e93985..386d58f61 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -172,6 +172,16 @@ $config = array (
 	'default-saml20-idp' => 'https://openidp.feide.no',
 	'default-shib13-idp' => NULL,
 	'default-wsfed-idp'	=> 'urn:federation:pingfederate:localhost',
+
+	/*
+	 * Default IdP discovery service urls.
+	 * This option sets the default IdP discovery service URLs for the SPs in this installation. These
+	 * URLs can be overridden on a per SP basis by setting this option in the metadata for the SP.
+	 *
+	 * By default simpleSAMLphp will use its builtin IdP discovery service.
+	 */
+	'idpdisco.url.shib13' => NULL,
+	'idpdisco.url.saml2' => NULL,
 	
 	/*
 	 * IdP Discovery service look configuration. 
diff --git a/docs/source/simplesamlphp-sp.xml b/docs/source/simplesamlphp-sp.xml
index 51d272805..bfb6d04ca 100644
--- a/docs/source/simplesamlphp-sp.xml
+++ b/docs/source/simplesamlphp-sp.xml
@@ -286,6 +286,19 @@
               PHP page.</para>
             </glossdef>
           </glossentry>
+
+          <glossentry>
+            <glossterm>idpdisco.url</glossterm>
+
+            <glossdef>
+              <para>Set which IdP discovery service this SP should use. If
+              this is unset, the IdP discovery service specified in the global
+              option <literal>idpdisco.url.saml2</literal> in
+              <filename>config/config.php</filename> will be used. If that one
+              is also unset, the builtin default discovery service will be
+              used.</para>
+            </glossdef>
+          </glossentry>
         </glosslist>
       </section>
 
@@ -704,6 +717,19 @@
               PHP page.</para>
             </glossdef>
           </glossentry>
+
+          <glossentry>
+            <glossterm>idpdisco.url</glossterm>
+
+            <glossdef>
+              <para>Set which IdP discovery service this SP should use. If
+              this is unset, the IdP discovery service specified in the global
+              option <literal>idpdisco.url.shib13</literal> in
+              <filename>config/config.php</filename> will be used. If that one
+              is also unset, the builtin default discovery service will be
+              used.</para>
+            </glossdef>
+          </glossentry>
         </glosslist>
       </section>
     </section>
diff --git a/www/admin/metadata.php b/www/admin/metadata.php
index 610d6f1e6..298496dc1 100644
--- a/www/admin/metadata.php
+++ b/www/admin/metadata.php
@@ -29,7 +29,7 @@ try {
 		foreach ($metalist AS $entityid => $mentry) {
 			$results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry,
 				array('entityid', 'host'),
-				array('request.signing','certificate','privatekey', 'privatekey_pass', 'NameIDFormat', 'ForceAuthn', 'AuthnContextClassRef', 'SPNameQualifier', 'attributemap', 'attributealter', 'attributes', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate')
+				array('request.signing','certificate','privatekey', 'privatekey_pass', 'NameIDFormat', 'ForceAuthn', 'AuthnContextClassRef', 'SPNameQualifier', 'attributemap', 'attributealter', 'attributes', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate', 'idpdisco.url')
 			);
 		}
 		$et->data['metadata.saml20-sp-hosted'] = $results;
@@ -79,7 +79,7 @@ try {
 		foreach ($metalist AS $entityid => $mentry) {
 			$results[$entityid] = SimpleSAML_Utilities::checkAssocArrayRules($mentry,
 				array('entityid', 'host'),
-				array('NameIDFormat', 'ForceAuthn', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate')
+				array('NameIDFormat', 'ForceAuthn', 'metadata.sign.enable', 'metadata.sign.privatekey', 'metadata.sign.privatekey_pass', 'metadata.sign.certificate', 'idpdisco.url')
 			);
 		}
 		$et->data['metadata.shib13-sp-hosted'] = $results;
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
index d2de59f32..1e0a77f5a 100644
--- a/www/saml2/sp/initSSO.php
+++ b/www/saml2/sp/initSSO.php
@@ -29,6 +29,11 @@ try {
 	$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-saml20-idp') ;
 	$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID();
 
+	if($idpentityid === NULL) {
+		/* We are going to need the SP metadata to determine which IdP discovery service we should use. */
+		$spmetadata = $metadata->getMetaData($spentityid);
+	}
+
 } catch (Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
 }
@@ -41,7 +46,18 @@ if ($idpentityid == null) {
 
 	SimpleSAML_Logger::info('SAML2.0 - SP.initSSO: No chosen or default IdP, go to SAML2disco');
 
-	SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'saml2/sp/idpdisco.php', array(
+	/* Which IdP discovery service should we use? Can be set in SP metadata or in global configuration.
+	 * Falling back to builtin discovery service.
+	 */
+	if(array_key_exists('idpdisco.url', $spmetadata)) {
+		$discourl = $spmetadata['idpdisco.url'];
+	} elseif($config->getValue('idpdisco.url.saml2', NULL) !== NULL) {
+		$discourl = $config->getValue('idpdisco.url.saml2', NULL);
+	} else {
+		$discourl = '/' . $config->getBaseURL() . 'saml2/sp/idpdisco.php';
+	}
+
+	SimpleSAML_Utilities::redirect($discourl, array(
 		'entityID' => $spentityid,
 		'return' => SimpleSAML_Utilities::selfURL(),
 		'returnIDParam' => 'idpentityid')
diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php
index 6cb61bc05..00bc56846 100644
--- a/www/shib13/sp/initSSO.php
+++ b/www/shib13/sp/initSSO.php
@@ -29,6 +29,12 @@ try {
 	$idpentityid = isset($_GET['idpentityid']) ? $_GET['idpentityid'] : $config->getValue('default-shib13-idp') ;
 	$spentityid = isset($_GET['spentityid']) ? $_GET['spentityid'] : $metadata->getMetaDataCurrentEntityID('shib13-sp-hosted');
 
+	if($idpentityid === NULL) {
+		/* We are going to need the SP metadata to determine which IdP discovery service we should use. */
+		$spmetadata = $metadata->getMetaDataCurrent('shib13-sp-hosted');
+	}
+
+
 } catch (Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
 }
@@ -40,12 +46,23 @@ if (!isset($session) || !$session->isValid('shib13') ) {
 	if ($idpentityid == null) {
 	
 		SimpleSAML_Logger::info('Shib1.3 - SP.initSSO: No chosen or default IdP, go to Shib13disco');
-	
-		$returnURL = urlencode(SimpleSAML_Utilities::selfURL());
-		$discservice = '/' . $config->getBaseURL() . 'shib13/sp/idpdisco.php?entityID=' . $spentityid . 
-			'&return=' . $returnURL . '&returnIDParam=idpentityid';
-		SimpleSAML_Utilities::redirect($discservice);
-		
+
+		/* Which IdP discovery service should we use? Can be set in SP metadata or in global configuration.
+		 * Falling back to builtin discovery service.
+		 */
+		if(array_key_exists('idpdisco.url', $spmetadata)) {
+			$discservice = $spmetadata['idpdisco.url'];
+		} elseif($config->getValue('idpdisco.url.shib13', NULL) !== NULL) {
+			$discservice = $config->getValue('idpdisco.url.shib13', NULL);
+		} else {
+			$discservice = '/' . $config->getBaseURL() . 'shib13/sp/idpdisco.php';
+		}
+
+		SimpleSAML_Utilities::redirect($discservice, array(
+			'entityID' => $spentityid,
+			'return' => SimpleSAML_Utilities::selfURL(),
+			'returnIDParam' => 'idpentityid',
+			));
 	}
 	
 	
-- 
GitLab