From 4e155f938333a7bf27992671d8e40bedb4909bd0 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Fri, 8 May 2009 05:39:23 +0000
Subject: [PATCH] openid: Store associations in authentication state array.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1494 44740490-163a-0410-bde0-09ae8108e29a
---
 modules/openid/lib/StateStore.php | 187 ++++++++++++++++++++++++++++++
 modules/openid/www/consumer.php   |  29 +----
 2 files changed, 191 insertions(+), 25 deletions(-)
 create mode 100644 modules/openid/lib/StateStore.php

diff --git a/modules/openid/lib/StateStore.php b/modules/openid/lib/StateStore.php
new file mode 100644
index 000000000..e11ede26d
--- /dev/null
+++ b/modules/openid/lib/StateStore.php
@@ -0,0 +1,187 @@
+<?php
+
+/* The OpenID library relies on manual loading of classes. */
+require_once('Auth/OpenID/Interface.php');
+require_once('Auth/OpenID/Association.php');
+
+/**
+ * Implementation of Auth_OpenID_OpenIDStore which saves the state in
+ * an state-array.
+ *
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_openid_StateStore extends Auth_OpenID_OpenIDStore{
+
+
+	/**
+	 * Reference to the state array.
+	 */
+	private $state;
+
+
+	/**
+	 * Reference to the array with associations in the state array.
+	 */
+	private $associations;
+
+
+	/**
+	 * Initializes the store object.
+	 *
+	 * @param array &$state  Reference to the state array.
+	 */
+	public function __construct(&$state) {
+		assert('is_array($state)');
+
+		$this->state =& $state;
+
+		if (!array_key_exists('openid:Assocs', $state)) {
+			$state['openid:Assocs'] = array();
+		}
+
+		$this->associations =& $state['openid:Assocs'];
+	}
+
+
+	/**
+	 * Determine whether a given nonce can be used.
+	 *
+	 * This implementation accepts all nonces, and relies on the state array
+	 * being invalidated when login completes to prevent replay attacks.
+	 *
+	 * @return bool  This function always returns TRUE.
+	 */
+	public function useNonce($server_url, $timestamp, $salt) {
+		return TRUE;
+	}
+
+
+	/**
+	 * Retrieve all associations for a given server.
+	 *
+	 * The associations are returned as an associative array with the
+	 * association handle as the index and the association object as
+	 * the value.
+	 *
+	 * @param string $server_url  The server.
+	 * @return array  Associative array with associations.
+	 */
+	private function getServerAssociations($server_url) {
+		assert('is_string($server_url)');
+
+		if (!array_key_exists($server_url, $this->associations)) {
+			return array();
+		}
+
+		$ret = array();
+		foreach ($this->associations[$server_url] as $handle => $association) {
+
+			$association = Auth_OpenID_Association::deserialize(
+				'Auth_OpenID_Association', $association);
+			if ($association === NULL) {
+				continue;
+			}
+
+			if ($association->getExpiresIn() == 0) {
+				continue;
+			}
+
+			$ret[$handle] = $association;
+		}
+
+		return $ret;
+	}
+
+
+	/**
+	 * Retrieve an association with the given handle.
+	 *
+	 * @param string $server_url  The server.
+	 * @param string $handle  The handle of the association.
+	 * @return Auth_OpenID_Association|NULL  The association object, if it is found.
+	 */
+	private function readAssociation($server_url, $handle) {
+		assert('is_string($server_url)');
+		assert('is_string($handle)');
+
+		$sassoc = $this->getServerAssociations($server_url);
+		if (!array_key_exists($handle, $sassoc)) {
+			return NULL;
+		}
+
+		return $sassoc[$handle];
+	}
+
+
+	/**
+	 * Retrieve an association.
+	 *
+	 * This function retrieves an association with the given handle, or the most
+	 * recent association if no handle is given.
+	 *
+	 * @param string $server_url  The server.
+	 * @param string|NULL $handle  The association handle.
+	 * @return Auth_OpenID_Association|NULL  The association object, if it is found.
+	 */
+	public function getAssociation($server_url, $handle = NULL) {
+		assert('is_string($server_url)');
+		assert('is_null($handle) || is_string($handle)');
+
+		if ($handle !== NULL) {
+			return $this->readAssociation($server_url, $handle);
+		}
+
+
+		/* $handle is NULL - we should retrieve the most recent association. */
+
+		$sassoc = $this->getServerAssociations($server_url);
+
+		$recentAssoc = NULL;
+		foreach ($sassoc as $handle => $association) {
+			if ($recentAssoc === NULL) {
+				/* No $recentAssoc - this is the most recent association. */
+				$recentAssoc = $association;
+				continue;
+			}
+
+			if ($association->issued > $recentAssoc->issued) {
+				/* More recently issued than $recentAssoc. */
+				$recentAssoc = $association;
+			}
+		}
+
+		return $recentAssoc;
+	}
+
+
+	/**
+	 * Store an association.
+	 *
+	 * This function stores an association.
+
+	 * @param string $server_url  The server.
+	 * @param Auth_OpenID_Association $association  The association which should be stored.
+	 * @return bool  TRUE if the association is stored, FALSE if not.
+	 */
+	public function storeAssociation($server_url, Auth_OpenID_Association $association) {
+		assert('is_string($server_url)');
+
+		if (!array_key_exists($server_url, $this->associations)) {
+			$this->associations[$server_url] = array();
+		}
+
+		$handle = $association->handle;
+		assert('is_string($handle)');
+
+		$this->associations[$server_url][$handle] = $association->serialize();
+
+		/* We rely on saveState saving with the same id as before. */
+		SimpleSAML_Auth_State::saveState($this->state, 'openid:state');
+
+		return TRUE;
+	}
+
+}
+
+?>
\ No newline at end of file
diff --git a/modules/openid/www/consumer.php b/modules/openid/www/consumer.php
index ca427d5a0..7dedf50b4 100644
--- a/modules/openid/www/consumer.php
+++ b/modules/openid/www/consumer.php
@@ -39,32 +39,11 @@ function displayError($message) {
 }
 
 
-function &getStore() {
-    /**
-     * This is where the example will store its OpenID information.
-     * You should change this path if you want the example store to be
-     * created elsewhere.  After you're done playing with the example
-     * script, you'll have to remove this directory manually.
-     */
-    $store_path = "/tmp/_php_consumer_test";
-
-    if (!file_exists($store_path) &&
-        !mkdir($store_path)) {
-        print "Could not create the FileStore directory '$store_path'. ".
-            " Please check the effective permissions.";
-        exit(0);
-    }
-
-    return new Auth_OpenID_FileStore($store_path);
-}
 
-function &getConsumer() {
-    /**
-     * Create a consumer object using the store object created
-     * earlier.
-     */
-    $store = getStore();
-    return new Auth_OpenID_Consumer($store);
+function getConsumer() {
+	global $state;
+	$store = new sspmod_openid_StateStore($state);
+	return new Auth_OpenID_Consumer($store);
 }
 
 function getOpenIDURL() {
-- 
GitLab