From d7a762a5bf43c4d93402b3bd27148d26c76c8d3b Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Mon, 30 Jun 2008 11:31:57 +0000
Subject: [PATCH] login-feide: Added support for limiting which organizations a
 user can log in from.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@722 44740490-163a-0410-bde0-09ae8108e29a
---
 attributealter/feideaccess.php    | 32 +++++++++++++++++++++++
 templates/default/login-feide.php |  3 ++-
 www/auth/login-feide.php          | 43 +++++++++++++++++++++++++++----
 3 files changed, 72 insertions(+), 6 deletions(-)
 create mode 100644 attributealter/feideaccess.php

diff --git a/attributealter/feideaccess.php b/attributealter/feideaccess.php
new file mode 100644
index 000000000..92132294e
--- /dev/null
+++ b/attributealter/feideaccess.php
@@ -0,0 +1,32 @@
+<?php
+function attributealter_feideaccess(&$attributes, $spEntityId = null, $idpEntityId = null) {
+	assert('$spEntityId !== NULL');
+	assert('$idpEntityId !== NULL');
+
+	$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
+	$spMetadata = $metadata->getMetadata($spEntityId, 'saml20-sp-remote');
+	if(!array_key_exists('feide.allowedorgs', $spMetadata)) {
+		SimpleSAML_Logger::info('FEIDE access control: No limits set for SP: ' . $spEntityId);
+		return;
+	}
+	$allowedOrgs = $spMetadata['feide.allowedorgs'];
+
+	if(!array_key_exists('eduPersonPrincipalName', $attributes)) {
+		throw new Exception('FEIDE access control requires the eduPersonPrincipalName to be present.');
+	}
+
+	$eppn = $attributes['eduPersonPrincipalName'][0];
+	$org = explode('@', $eppn);
+	$org = $org[1];
+
+	if(!in_array($org, $allowedOrgs, TRUE)) {
+		$session = SimpleSAML_Session::getInstance();
+		SimpleSAML_Logger::error('FEIDE access control: Organization "' . $org .
+			'" not in list of allowed organization for SP "' . $spEntityId . '".');
+		SimpleSAML_Utilities::fatalError($session->getTrackId(), 'NOACCESS');
+	}
+
+	SimpleSAML_Logger::info('FEIDE access control: Organization "' . $org .
+		'" is allowed for SP "' . $spEntityId . '".');
+}
+?>
\ No newline at end of file
diff --git a/templates/default/login-feide.php b/templates/default/login-feide.php
index 9f301a80c..6d71242bf 100644
--- a/templates/default/login-feide.php
+++ b/templates/default/login-feide.php
@@ -19,7 +19,8 @@ $this->includeAtTemplateBase('includes/header.php');
 			<legend>Choose your home organization</legend>
 				<select name="org" tabindex="1">
 				<?php
-					foreach ($this->data['ldapconfig'] AS $key => $entry) {
+					foreach ($this->data['allowedorgs'] AS $key) {
+						$entry = $this->data['ldapconfig'][$key];
 						echo '<option ' 
 						. ($key == $this->data['org'] ? 'selected="selected" ' : '')
 						. 'value="' . htmlspecialchars($key) . '">' . htmlspecialchars($entry['description']) . '</option>';
diff --git a/www/auth/login-feide.php b/www/auth/login-feide.php
index b5bf2c304..739fbd274 100644
--- a/www/auth/login-feide.php
+++ b/www/auth/login-feide.php
@@ -63,6 +63,16 @@ try {
 $spentityid = $authrequestcache['Issuer'];
 $spmetadata = $metadata->getMetadata($spentityid, 'saml20-sp-remote');
 
+/*
+ * Find the list of allowed organizations.
+ */
+$allowedOrgs = array_keys($ldaporgconfig);
+if(array_key_exists('feide.allowedorgs', $spmetadata)) {
+	assert('is_array($spmetadata["feide.allowedorgs"])');
+	$allowedOrgs = array_intersect($spmetadata['feide.allowedorgs'], $allowedOrgs);
+}
+
+
 $error = null;
 $attributes = array();
 
@@ -95,7 +105,12 @@ if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'change_org') {
 	$selectorg = true;
 }
 
-
+/*
+ * The user may have previously selected an organization which the SP doesn't allow. Correct this.
+ */
+if ($selectorg === FALSE && !in_array($org, $allowedOrgs, TRUE)) {
+	$selectorg = TRUE;
+}
 
 
 if (isset($_REQUEST['username'])) {	
@@ -260,13 +275,31 @@ $t->data['relaystate'] = $_REQUEST['RelayState'];
 $t->data['ldapconfig'] = $ldaporgconfig;
 $t->data['protocol'] = $protocol;
 $t->data['authid'] = $authid;
-$t->data['splogo'] = $spmetadata['logo'];
-$t->data['spdesc'] = $spmetadata['description'];
-$t->data['spname'] = $spmetadata['name'];
-$t->data['contact'] = $spmetadata['contact'];
+
+if(array_key_exists('logo', $spmetadata)) {
+	$t->data['splogo'] = $spmetadata['logo'];
+} else {
+	$t->data['splogo'] = NULL;
+}
+if(array_key_exists('description', $spmetadata)) {
+	$t->data['spdesc'] = $spmetadata['description'];
+} else {
+	$t->data['spdesc'] = NULL;
+}
+if(array_key_exists('name', $spmetadata)) {
+	$t->data['spname'] = $spmetadata['name'];
+} else {
+	$t->data['spname'] = NULL;
+}
+if(array_key_exists('contact', $spmetadata)) {
+	$t->data['contact'] = $spmetadata['contact'];
+} else {
+	$t->data['contact'] = NULL;
+}
 
 $t->data['selectorg'] = $selectorg;
 $t->data['org'] = $org;
+$t->data['allowedorgs'] = $allowedOrgs;
 $t->data['error'] = $error;
 if (isset($error)) {
 	$t->data['username'] = $_POST['username'];
-- 
GitLab