diff --git a/modules/openid/lib/StateStore.php b/modules/openid/lib/StateStore.php new file mode 100644 index 0000000000000000000000000000000000000000..e11ede26d090dd7f653402bc992dd58b11de6151 --- /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 ca427d5a0578f13b3c02a8f43c4d35a77f1b053b..7dedf50b4759e7e01f2b955b7e0a6b3925c098d6 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() {