From 8173dc603e40e84de4139c03e31af2082b037941 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20=C3=85kre=20Solberg?= <andreas.solberg@uninett.no>
Date: Wed, 27 Feb 2008 16:27:55 +0000
Subject: [PATCH] ADding support for multiple IdP hosted on the same hostname
 using an astrix in the basenamedir

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@324 44740490-163a-0410-bde0-09ae8108e29a
---
 docs/source/simplesamlphp-sp.xml              |  2 +-
 lib/SimpleSAML/Configuration.php              |  7 ++
 .../Metadata/MetaDataStorageHandler.php       | 17 ++---
 lib/SimpleSAML/Utilities.php                  | 64 +++++++++++++++++--
 lib/SimpleSAML/XHTML/Template.php             |  2 +-
 www/admin/memcachestat.php                    |  2 +-
 www/admin/metadata.php                        |  2 +-
 www/admin/test.php                            |  6 +-
 www/aselect/handler.php                       | 10 +--
 www/example-simple/hostnames.php              |  3 +-
 www/example-simple/saml2-example.php          |  8 +--
 www/example-simple/shib13-example.php         |  2 +-
 www/index.php                                 |  2 +-
 www/openid/provider/server.php                |  4 +-
 www/saml2/idp/SSOService.php                  |  2 +-
 www/saml2/idp/SingleLogoutService.php         |  2 +-
 www/saml2/sp/initSSO.php                      |  2 +-
 www/shib13/idp/SSOService.php                 |  2 +-
 www/shib13/sp/initSSO.php                     |  2 +-
 19 files changed, 101 insertions(+), 40 deletions(-)

diff --git a/docs/source/simplesamlphp-sp.xml b/docs/source/simplesamlphp-sp.xml
index fc578b10c..bdf9f1645 100644
--- a/docs/source/simplesamlphp-sp.xml
+++ b/docs/source/simplesamlphp-sp.xml
@@ -644,7 +644,7 @@ $session = SimpleSAML_Session::getInstance(true);</programlisting>
     <programlisting>/* Check if valid local session exists.. */
 if (!isset($session) || !$session-&gt;isValid('saml2') ) {
 	SimpleSAML_Utilities::redirect(
-		'/' . $config-&gt;getValue('baseurlpath') .
+		'/' . $config-&gt;getBaseURL() .
 		'saml2/sp/initSSO.php',
 		array('RelayState' =&gt; SimpleSAML_Utilities::selfURL())
 		);
diff --git a/lib/SimpleSAML/Configuration.php b/lib/SimpleSAML/Configuration.php
index 713a79737..7178606ec 100644
--- a/lib/SimpleSAML/Configuration.php
+++ b/lib/SimpleSAML/Configuration.php
@@ -58,6 +58,13 @@ class SimpleSAML_Configuration {
 
 		return $this->configuration[$name];
 	}
+	
+	public function getBaseURL() {
+		if (preg_match('/^\*(.*)$/', $this->getValue('baseurlpath', ''), $matches)) {
+			return SimpleSAML_Utilities::getFirstPathElement(false) . $matches[1];
+		}
+		return $this->getValue('baseurlpath', '');
+	}
 
 
 	/* Retrieve the base directory for this simpleSAMLphp installation.
diff --git a/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php b/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
index e80ca42bf..001aecd91 100644
--- a/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
+++ b/lib/SimpleSAML/Metadata/MetaDataStorageHandler.php
@@ -109,8 +109,7 @@ abstract class SimpleSAML_Metadata_MetaDataStorageHandler {
 		assert($config instanceof SimpleSAML_Configuration);
 		
 		$baseurl = SimpleSAML_Utilities::selfURLhost() . '/' . 
-			$config->getValue('baseurlpath');
-		
+			$config->getBaseURL();
 		
 		if ($set == 'saml20-sp-hosted') {
 			switch ($property) {				
@@ -164,7 +163,8 @@ abstract class SimpleSAML_Metadata_MetaDataStorageHandler {
 		if (!isset($this->metadata[$set])) {
 			$this->load($set);
 		}
-		$currenthost = $_SERVER['HTTP_HOST'];
+		$currenthost         = SimpleSAML_Utilities::getSelfHost(); 			// sp.example.org
+		$currenthostwithpath = SimpleSAML_Utilities::getSelfHostWithPath(); 	// sp.example.org/university
 		
 		if(strstr($currenthost, ":")) {
 				$currenthostdecomposed = explode(":", $currenthost);
@@ -177,11 +177,12 @@ abstract class SimpleSAML_Metadata_MetaDataStorageHandler {
 		if (!isset($currenthost)) {
 			throw new Exception('Could not get HTTP_HOST, in order to resolve default entity ID');
 		}
-		if (!isset($this->hostmap[$set][$currenthost])) {
-			throw new Exception('Could not find any default metadata entities in set [' . $set . '] for host [' . $currenthost . ']');
-		}
-		if (!$this->hostmap[$set][$currenthost]) throw new Exception('Could not find default metadata for current host');
-		return $this->hostmap[$set][$currenthost];
+		
+		
+		if (isset($this->hostmap[$set][$currenthostwithpath])) return $this->hostmap[$set][$currenthostwithpath];
+		if (isset($this->hostmap[$set][$currenthost])) return $this->hostmap[$set][$currenthost];
+		
+		throw new Exception('Could not find any default metadata entities in set [' . $set . '] for host [' . $currenthost . ' : ' . $currenthostwithpath . ']');
 	}
 
 	abstract public function load($set);
diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index 7762f9f9b..a1aaf897f 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -14,7 +14,9 @@ require_once('SimpleSAML/Logger.php');
 class SimpleSAML_Utilities {
 
 
-
+	/**
+	 * Will return sp.example.org
+	 */
 	public static function getSelfHost() {
 	
 		$currenthost = $_SERVER['HTTP_HOST'];
@@ -22,9 +24,12 @@ class SimpleSAML_Utilities {
 				$currenthostdecomposed = explode(":", $currenthost);
 				$currenthost = $currenthostdecomposed[0];
 		}
-		return $currenthost;
+		return $currenthost;# . self::getFirstPathElement() ;
 	}
 
+	/**
+	 * Will return https
+	 */
 	public static function getSelfProtocol() {
 		$s = empty($_SERVER["HTTPS"]) ? ''
 			: ($_SERVER["HTTPS"] == "on") ? "s"
@@ -33,6 +38,9 @@ class SimpleSAML_Utilities {
 		return $protocol;
 	}
 
+	/**
+	 * Will return https://sp.example.org
+	 */
 	public static function selfURLhost() {
 	
 		$currenthost = self::getSelfHost();
@@ -52,18 +60,62 @@ class SimpleSAML_Utilities {
 	
 	}
 	
-
-
+	/**
+	 * Will return https://sp.example.org/universities/ruc/baz/simplesaml/saml2/SSOService.php
+	 */
 	public static function selfURLNoQuery() {
 	
 		$selfURLhost = self::selfURLhost();
-		return $selfURLhost . $_SERVER['SCRIPT_NAME'];
+		return $selfURLhost . self::getScriptName();
+	
+	}
 	
+	public static function getScriptName() {
+		$scriptname = $_SERVER['SCRIPT_NAME'];
+		if (preg_match('|^/.*?(/.*)$|', $_SERVER['SCRIPT_NAME'], $matches)) {
+			#$scriptname = $matches[1];
+		}
+		return $scriptname;
 	}
+	
+	
+	/**
+	 * Will return sp.example.org/foo
+	 */
+	public static function getSelfHostWithPath() {
+	
+		$selfhostwithpath = self::getSelfHost();
+		if (preg_match('|^(/.*?)/|', $_SERVER['SCRIPT_NAME'], $matches)) {
+			$selfhostwithpath .= $matches[1];
+		}
+		return $selfhostwithpath;
+	
+	}
+	
+	/**
+	 * Will return foo
+	 */
+	public static function getFirstPathElement($trailingslash = true) {
+	
+		if (preg_match('|^/(.*?)/|', $_SERVER['SCRIPT_NAME'], $matches)) {
+			return ($trailingslash ? '/' : '') . $matches[1];
+		}
+		return '';
+	}
+	
 
 	public static function selfURL() {
 		$selfURLhost = self::selfURLhost();
-		return $selfURLhost . $_SERVER['REQUEST_URI'];	
+		return $selfURLhost . self::getRequestURI();	
+	}
+	
+	public static function getRequestURI() {
+		
+		$requesturi = $_SERVER['REQUEST_URI'];
+		if (preg_match('|^/.*?(/.*)$|', $_SERVER['REQUEST_URI'], $matches)) {
+		#$requesturi = $matches[1];
+		}
+		return $requesturi;
 	}
 	
 	public static function addURLparameter($url, $parameter) {
diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php
index 742882de3..d4acfa022 100644
--- a/lib/SimpleSAML/XHTML/Template.php
+++ b/lib/SimpleSAML/XHTML/Template.php
@@ -24,7 +24,7 @@ class SimpleSAML_XHTML_Template {
 		$this->configuration = $configuration;
 		$this->template = $template;
 		
-		$this->data['baseurlpath'] = $this->configuration->getValue('baseurlpath');
+		$this->data['baseurlpath'] = $this->configuration->getBaseURL();
 		
 		if (!empty($languagefile)) $this->includeLanguageFile($languagefile);
 	}
diff --git a/www/admin/memcachestat.php b/www/admin/memcachestat.php
index c13653857..bbe1441ed 100644
--- a/www/admin/memcachestat.php
+++ b/www/admin/memcachestat.php
@@ -15,7 +15,7 @@ try {
 
 	/* Make sure that the user has admin access rights. */
 	if (!isset($session) || !$session->isValid('login-admin') ) {
-		SimpleSAML_Utilities::redirect('/' . $config->getValue('baseurlpath') . 'auth/login-admin.php',
+		SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'auth/login-admin.php',
 		                               array('RelayState' => SimpleSAML_Utilities::selfURL())
 		                               );
 	}
diff --git a/www/admin/metadata.php b/www/admin/metadata.php
index d6f1761ea..a40491f2c 100644
--- a/www/admin/metadata.php
+++ b/www/admin/metadata.php
@@ -14,7 +14,7 @@ $session = SimpleSAML_Session::getInstance(true);
 
 /* Check if valid local session exists.. */
 if (!isset($session) || !$session->isValid('login-admin') ) {
-	SimpleSAML_Utilities::redirect('/' . $config->getValue('baseurlpath') . 'auth/login-admin.php',
+	SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'auth/login-admin.php',
 		array('RelayState' => SimpleSAML_Utilities::selfURL())
 	);
 }
diff --git a/www/admin/test.php b/www/admin/test.php
index 285236d6d..bbdde5f57 100644
--- a/www/admin/test.php
+++ b/www/admin/test.php
@@ -94,9 +94,9 @@ if ($op === 'login') {
 		}
 
 		if($protocol === 'saml2') {
-			$url = '/' . $config->getValue('baseurlpath') . 'saml2/sp/initSSO.php';
+			$url = '/' . $config->getBaseURL() . 'saml2/sp/initSSO.php';
 		} elseif($protocol === 'shib13') {
-			$url = '/' . $config->getValue('baseurlpath') . 'shib13/sp/initSSO.php';
+			$url = '/' . $config->getBaseURL() . 'shib13/sp/initSSO.php';
 		} else {
 			error('Unable to log in with protocol "' . $protocol . '".');
 		}
@@ -133,7 +133,7 @@ if ($op === 'login') {
 	}
 
 	if ($protocol === 'saml2') {
-		$url = '/' . $config->getValue('baseurlpath') . 'saml2/sp/initSLO.php';
+		$url = '/' . $config->getBaseURL() . 'saml2/sp/initSLO.php';
 	} else {
 		error('Logout unsupported for protocol "' . $protocol . '".');
 	}
diff --git a/www/aselect/handler.php b/www/aselect/handler.php
index 795456eed..448bec0d0 100644
--- a/www/aselect/handler.php
+++ b/www/aselect/handler.php
@@ -71,11 +71,11 @@ $as_metadata = array(
 			'authsp' => 'simpleSAMLphp',
 			'app_level' => '10',
 			'tgt_exp_time' => '1194590521000',
-#			'auth' => '/' . $config->getValue('baseurlpath') . '/auth/login.php',
-#			'logout' => '/' . $config->getValue('baseurlpath') . 'logout.html',
-			'auth' => '/' . $config->getValue('baseurlpath') . '/saml2/sp/initSSO.php',
-			'logout' => '/' . $config->getValue('baseurlpath') . '/saml2/sp/initSLO.php',
-			'loggedout_url' => '/' . $config->getValue('baseurlpath') . 'logout.html',
+#			'auth' => '/' . $config->getBaseURL() . '/auth/login.php',
+#			'logout' => '/' . $config->getBaseURL() . 'logout.html',
+			'auth' => '/' . $config->getBaseURL() . '/saml2/sp/initSSO.php',
+			'logout' => '/' . $config->getBaseURL() . '/saml2/sp/initSLO.php',
+			'loggedout_url' => '/' . $config->getBaseURL() . 'logout.html',
 		),
 		'remote' => array(
 			// so far the IDP bridging is statically configured to the first one in
diff --git a/www/example-simple/hostnames.php b/www/example-simple/hostnames.php
index ca049c204..325314f6a 100644
--- a/www/example-simple/hostnames.php
+++ b/www/example-simple/hostnames.php
@@ -17,7 +17,7 @@ $session = SimpleSAML_Session::getInstance(true);
 
 /* Check if valid local session exists.. */
 if (!isset($session) || !$session->isValid('login-admin') ) {
-	SimpleSAML_Utilities::redirect('/' . $config->getValue('baseurlpath') . 'auth/login-admin.php',
+	SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'auth/login-admin.php',
 		array('RelayState' => SimpleSAML_Utilities::selfURL())
 	);
 }
@@ -31,6 +31,7 @@ $attributes = array();
 $attributes['selfURLhost'] = array(SimpleSAML_Utilities::selfURLhost());
 $attributes['selfURLNoQuery'] = array(SimpleSAML_Utilities::selfURLNoQuery());
 $attributes['selfURL'] = array(SimpleSAML_Utilities::selfURL());
+$attributes['selfHostWithPath'] = array(SimpleSAML_Utilities::getSelfHostWithPath());
 
 $attributes['HTTP_HOST'] = array($_SERVER['HTTP_HOST']);
 $attributes['HTTPS'] = array($_SERVER['HTTPS']);
diff --git a/www/example-simple/saml2-example.php b/www/example-simple/saml2-example.php
index c483c0eb1..de07c4c4c 100644
--- a/www/example-simple/saml2-example.php
+++ b/www/example-simple/saml2-example.php
@@ -40,7 +40,7 @@ $session = SimpleSAML_Session::getInstance(TRUE);
  */
 if (!$session->isValid('saml2') ) {
 	SimpleSAML_Utilities::redirect(
-		'/' . $config->getValue('baseurlpath') . 'saml2/sp/initSSO.php',
+		'/' . $config->getBaseURL() . 'saml2/sp/initSSO.php',
 		array('RelayState' => SimpleSAML_Utilities::selfURL())
 	);
 }
@@ -57,15 +57,15 @@ $attributes = $session->getAttributes();
  *
  */
 
-$t = new SimpleSAML_XHTML_Template($config, 'status.php');
+$t = new SimpleSAML_XHTML_Template($config, 'status.php', 'attributes.php');
 
 $t->data['header'] = 'SAML 2.0 SP Demo Example';
 $t->data['remaining'] = $session->remainingTime();
 $t->data['sessionsize'] = $session->getSize();
 $t->data['attributes'] = $attributes;
 $t->data['icon'] = 'bino.png';
-$t->data['logout'] = '<p>[ <a href="/' . $config->getValue('baseurlpath') . 'saml2/sp/initSLO.php?RelayState=/' . 
-	$config->getValue('baseurlpath') . 'logout.html">Logout</a> ]';
+$t->data['logout'] = '<p>[ <a href="/' . $config->getBaseURL() . 'saml2/sp/initSLO.php?RelayState=/' . 
+	$config->getBaseURL() . 'logout.html">Logout</a> ]';
 $t->show();
 
 
diff --git a/www/example-simple/shib13-example.php b/www/example-simple/shib13-example.php
index d70950f47..c9876c696 100644
--- a/www/example-simple/shib13-example.php
+++ b/www/example-simple/shib13-example.php
@@ -40,7 +40,7 @@ $session = SimpleSAML_Session::getInstance(TRUE);
  */
 if (!isset($session) || !$session->isValid('shib13') ) {	
 	SimpleSAML_Utilities::redirect(
-		'/' . $config->getValue('baseurlpath') . 'shib13/sp/initSSO.php',
+		'/' . $config->getBaseURL() . 'shib13/sp/initSSO.php',
 		array('RelayState' => SimpleSAML_Utilities::selfURL())
 	);
 }
diff --git a/www/index.php b/www/index.php
index ef77bc18e..e86224236 100644
--- a/www/index.php
+++ b/www/index.php
@@ -15,7 +15,7 @@ $session = SimpleSAML_Session::getInstance(true);
 /* Check if valid local session exists.. */
 if ($config->getValue('admin.protectindexpage', false)) {
 	if (!isset($session) || !$session->isValid('login-admin') ) {
-		SimpleSAML_Utilities::redirect('/' . $config->getValue('baseurlpath') . 'auth/login-admin.php',
+		SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'auth/login-admin.php',
 			array('RelayState' => SimpleSAML_Utilities::selfURL())
 		);
 	}
diff --git a/www/openid/provider/server.php b/www/openid/provider/server.php
index bf5e40534..0a16ab51b 100644
--- a/www/openid/provider/server.php
+++ b/www/openid/provider/server.php
@@ -112,7 +112,7 @@ function action_default()
 		
 		$relaystate = SimpleSAML_Utilities::selfURLNoQuery() . '?RelayState=' . urlencode($_GET['RelayState']) .
 			'&RequestID=' . urlencode($requestid);
-		$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getValue('baseurlpath') . $idpmeta['auth'], 
+		$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getBaseURL() . $idpmeta['auth'], 
 			'RelayState=' . urlencode($relaystate));
 		
 		$t->data['initssourl'] 			= $authurl;
@@ -230,7 +230,7 @@ function check_authenticated_user() {
 		
 		
 		$relaystate = SimpleSAML_Utilities::selfURLNoQuery() . '/login';
-		$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getValue('baseurlpath') . $idpmeta['auth'], 
+		$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getBaseURL() . $idpmeta['auth'], 
 			'RelayState=' . urlencode($relaystate));
 		
 		SimpleSAML_Utilities::redirect($authurl);
diff --git a/www/saml2/idp/SSOService.php b/www/saml2/idp/SSOService.php
index e5e5dd04f..8515634a6 100644
--- a/www/saml2/idp/SSOService.php
+++ b/www/saml2/idp/SSOService.php
@@ -132,7 +132,7 @@ if (!isset($session) || !$session->isValid($authority) ) {
 
 	$relaystate = SimpleSAML_Utilities::selfURLNoQuery() .
 		'?RequestID=' . urlencode($requestid);
-	$authurl = '/' . $config->getValue('baseurlpath') . $idpmetadata['auth'];
+	$authurl = '/' . $config->getBaseURL() . $idpmetadata['auth'];
 
 	SimpleSAML_Utilities::redirect($authurl,
 		array('RelayState' => $relaystate));
diff --git a/www/saml2/idp/SingleLogoutService.php b/www/saml2/idp/SingleLogoutService.php
index 05ff903c7..bdf02af69 100644
--- a/www/saml2/idp/SingleLogoutService.php
+++ b/www/saml2/idp/SingleLogoutService.php
@@ -222,7 +222,7 @@ if ($config->getValue('debug', false))
  * initiate SAML 2.0 SP Single LogOut, with the RelayState equal this URL.
  */
 if ($session->getAuthority() == 'saml2') {
-	SimpleSAML_Utilities::redirect('/' . $config->getValue('baseurlpath') . 'saml2/sp/initSLO.php',
+	SimpleSAML_Utilities::redirect('/' . $config->getBaseURL() . 'saml2/sp/initSLO.php',
 		array('RelayState' => SimpleSAML_Utilities::selfURLNoQuery())
 	);
 }
diff --git a/www/saml2/sp/initSSO.php b/www/saml2/sp/initSSO.php
index c26210b16..b8716f84f 100644
--- a/www/saml2/sp/initSSO.php
+++ b/www/saml2/sp/initSSO.php
@@ -47,7 +47,7 @@ if (!isset($session) || !$session->isValid('saml2') ) {
 		SimpleSAML_Logger::info('SAML2.0 - SP.initSSO: No chosen or default IdP, go to SAML2disco');
 		
 		$returnURL = urlencode(SimpleSAML_Utilities::selfURL());
-		$discservice = '/' . $config->getValue('baseurlpath') . 'saml2/sp/idpdisco.php?entityID=' . $spentityid . 
+		$discservice = '/' . $config->getBaseURL() . 'saml2/sp/idpdisco.php?entityID=' . $spentityid . 
 			'&return=' . $returnURL . '&returnIDParam=idpentityid';
 		SimpleSAML_Utilities::redirect($discservice);
 	}
diff --git a/www/shib13/idp/SSOService.php b/www/shib13/idp/SSOService.php
index db38d9d01..15216908a 100644
--- a/www/shib13/idp/SSOService.php
+++ b/www/shib13/idp/SSOService.php
@@ -122,7 +122,7 @@ $authority = isset($idpmetadata['authority']) ? $idpmetadata['authority'] : null
 if (!$session->isAuthenticated($authority) ) {
 
 	$relaystate = SimpleSAML_Utilities::selfURLNoQuery() . '?RequestID=' . urlencode($requestid);
-	$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getValue('baseurlpath') . $idpmetadata['auth'], 
+	$authurl = SimpleSAML_Utilities::addURLparameter('/' . $config->getBaseURL() . $idpmetadata['auth'], 
 		'RelayState=' . urlencode($relaystate));
 	SimpleSAML_Utilities::redirect($authurl);
 	
diff --git a/www/shib13/sp/initSSO.php b/www/shib13/sp/initSSO.php
index bc7ec229d..6b3dba0c7 100644
--- a/www/shib13/sp/initSSO.php
+++ b/www/shib13/sp/initSSO.php
@@ -49,7 +49,7 @@ if (!isset($session) || !$session->isValid('shib13') ) {
 		SimpleSAML_Logger::info('Shib1.3 - SP.initSSO: No chosen or default IdP, go to Shib13disco');
 	
 		$returnURL = urlencode(SimpleSAML_Utilities::selfURL());
-		$discservice = '/' . $config->getValue('baseurlpath') . 'shib13/sp/idpdisco.php?entityID=' . $spentityid . 
+		$discservice = '/' . $config->getBaseURL() . 'shib13/sp/idpdisco.php?entityID=' . $spentityid . 
 			'&return=' . $returnURL . '&returnIDParam=idpentityid';
 		SimpleSAML_Utilities::redirect($discservice);
 		
-- 
GitLab