diff options
-rw-r--r-- | Auth/OpenID/Consumer.php | 21 | ||||
-rw-r--r-- | Auth/OpenID/PredisStore.php | 208 | ||||
-rw-r--r-- | Auth/OpenID/TrustRoot.php | 4 | ||||
-rw-r--r-- | Auth/Yadis/Manager.php | 2 | ||||
-rw-r--r-- | Auth/Yadis/XML.php | 14 | ||||
-rw-r--r-- | Auth/Yadis/XRDS.php | 2 | ||||
-rw-r--r-- | Auth/Yadis/Yadis.php | 2 | ||||
-rw-r--r-- | examples/detect.php | 2 |
8 files changed, 239 insertions, 16 deletions
diff --git a/Auth/OpenID/Consumer.php b/Auth/OpenID/Consumer.php index d562e33..9ac0c50 100644 --- a/Auth/OpenID/Consumer.php +++ b/Auth/OpenID/Consumer.php @@ -29,7 +29,7 @@ * identity check. * * LIBRARY DESIGN - * + * * This consumer library is designed with that flow in mind. The goal * is to make it as easy as possible to perform the above steps * securely. @@ -427,7 +427,7 @@ class Auth_OpenID_Consumer { $loader->fromSession($endpoint_data); $message = Auth_OpenID_Message::fromPostArgs($query); - $response = $this->consumer->complete($message, $endpoint, + $response = $this->consumer->complete($message, $endpoint, $current_url); $this->session->del($this->_token_key); @@ -616,6 +616,9 @@ class Auth_OpenID_GenericConsumer { $this->store = $store; $this->negotiator = Auth_OpenID_getDefaultNegotiator(); $this->_use_assocs = (is_null($this->store) ? false : true); + if (get_class($this->store) == "Auth_OpenID_DumbStore") { + $this->_use_assocs = false; + } $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); @@ -666,7 +669,7 @@ class Auth_OpenID_GenericConsumer { '_completeInvalid'); return call_user_func_array(array($this, $method), - array($message, &$endpoint, $return_to)); + array($message, $endpoint, $return_to)); } /** @@ -1186,7 +1189,7 @@ class Auth_OpenID_GenericConsumer { list($unused, $services) = call_user_func_array($this->discoverMethod, array( $claimed_id, - &$this->fetcher, + $this->fetcher, )); if (!$services) { @@ -1202,7 +1205,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _verifyDiscoveryServices($claimed_id, + function _verifyDiscoveryServices($claimed_id, $services, $to_match_endpoints) { // Search the services resulting from discovery to find one @@ -1210,7 +1213,7 @@ class Auth_OpenID_GenericConsumer { foreach ($services as $endpoint) { foreach ($to_match_endpoints as $to_match_endpoint) { - $result = $this->_verifyDiscoverySingle($endpoint, + $result = $this->_verifyDiscoverySingle($endpoint, $to_match_endpoint); if (!Auth_OpenID::isFailure($result)) { @@ -1368,7 +1371,7 @@ class Auth_OpenID_GenericConsumer { } } $ca_message = $message->copy(); - $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode', + $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode', 'check_authentication'); return $ca_message; } @@ -1606,7 +1609,7 @@ class Auth_OpenID_GenericConsumer { $expires_in = Auth_OpenID::intval($expires_in_str); if ($expires_in === false) { - + $err = sprintf("Could not parse expires_in from association ". "response %s", print_r($assoc_response, true)); return new Auth_OpenID_FailureResponse(null, $err); @@ -1953,7 +1956,7 @@ class Auth_OpenID_AuthRequest { function htmlMarkup($realm, $return_to=null, $immediate=false, $form_tag_attrs=null) { - $form = $this->formMarkup($realm, $return_to, $immediate, + $form = $this->formMarkup($realm, $return_to, $immediate, $form_tag_attrs); if (Auth_OpenID::isFailure($form)) { diff --git a/Auth/OpenID/PredisStore.php b/Auth/OpenID/PredisStore.php new file mode 100644 index 0000000..7108c2f --- /dev/null +++ b/Auth/OpenID/PredisStore.php @@ -0,0 +1,208 @@ +<?php + +/** + * Supplies Redis server store backend for OpenID servers and consumers. + * Uses Predis library {@see https://github.com/nrk/predis}. + * Requires PHP >= 5.3. + * + * LICENSE: See the COPYING file included in this distribution. + * + * @package OpenID + * @author Ville Mattila <ville@eventio.fi> + * @copyright 2008 JanRain Inc., 2013 Eventio Oy / Ville Mattila + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache + * Contributed by Eventio Oy <http://www.eventio.fi/> + */ + +/** + * Import the interface for creating a new store class. + */ +require_once 'Auth/OpenID/Interface.php'; + +/** + * Supplies Redis server store backend for OpenID servers and consumers. + * Uses Predis library {@see https://github.com/nrk/predis}. + * Requires PHP >= 5.3. + * + * @package OpenID + */ +class Auth_OpenID_PredisStore extends Auth_OpenID_OpenIDStore { + + /** + * @var \Predis\Client + */ + protected $redis; + + /** + * Prefix for Redis keys + * @var string + */ + protected $prefix; + + /** + * Initializes a new {@link Auth_OpenID_PredisStore} instance. + * + * @param \Predis\Client $redis Predis client object + * @param string $prefix Prefix for all keys stored to the Redis + */ + function Auth_OpenID_PredisStore(\Predis\Client $redis, $prefix = '') + { + $this->prefix = $prefix; + $this->redis = $redis; + } + + /** + * Store association until its expiration time in Redis server. + * Overwrites any existing association with same server_url and + * handle. Handles list of associations for every server. + */ + function storeAssociation($server_url, $association) + { + // create Redis keys for association itself + // and list of associations for this server + $associationKey = $this->associationKey($server_url, + $association->handle); + $serverKey = $this->associationServerKey($server_url); + + // save association to server's associations' keys list + $this->redis->lpush( + $serverKey, + $associationKey + ); + + // Will touch the association list expiration, to avoid filling up + $newExpiration = ($association->issued + $association->lifetime); + + $expirationKey = $serverKey.'_expires_at'; + $expiration = $this->redis->get($expirationKey); + if (!$expiration || $newExpiration > $expiration) { + $this->redis->set($expirationKey, $newExpiration); + $this->redis->expireat($serverKey, $newExpiration); + $this->redis->expireat($expirationKey, $newExpiration); + } + + // save association itself, will automatically expire + $this->redis->setex( + $associationKey, + $newExpiration - time(), + serialize($association) + ); + } + + /** + * Read association from Redis. If no handle given + * and multiple associations found, returns latest issued + */ + function getAssociation($server_url, $handle = null) + { + // simple case: handle given + if ($handle !== null) { + return $this->getAssociationFromServer( + $this->associationKey($server_url, $handle) + ); + } + + // no handle given, receiving the latest issued + $serverKey = $this->associationServerKey($server_url); + $lastKey = $this->redis->lpop($serverKey); + if (!$lastKey) { return null; } + + // get association, return null if failed + return $this->getAssociationFromServer($lastKey); + } + + /** + * Function to actually receive and unserialize the association + * from the server. + */ + private function getAssociationFromServer($associationKey) + { + $association = $this->redis->get($associationKey); + return $association ? unserialize($association) : null; + } + + /** + * Immediately delete association from Redis. + */ + function removeAssociation($server_url, $handle) + { + // create Redis keys + $serverKey = $this->associationServerKey($server_url); + $associationKey = $this->associationKey($server_url, + $handle); + + // Removing the association from the server's association list + $removed = $this->redis->lrem($serverKey, 0, $associationKey); + if ($removed < 1) { + return false; + } + + // Delete the association itself + return $this->redis->del($associationKey); + } + + /** + * Create nonce for server and salt, expiring after + * $Auth_OpenID_SKEW seconds. + */ + function useNonce($server_url, $timestamp, $salt) + { + global $Auth_OpenID_SKEW; + + // save one request to memcache when nonce obviously expired + if (abs($timestamp - time()) > $Auth_OpenID_SKEW) { + return false; + } + + // SETNX will set the value only of the key doesn't exist yet. + $nonceKey = $this->nonceKey($server_url, $salt); + $added = $this->predis->setnx($nonceKey); + if ($added) { + // Will set expiration + $this->predis->expire($nonceKey, $Auth_OpenID_SKEW); + return true; + } else { + return false; + } + } + + /** + * Build up nonce key + */ + private function nonceKey($server_url, $salt) + { + return $this->prefix . + 'openid_nonce_' . + sha1($server_url) . '_' . sha1($salt); + } + + /** + * Key is prefixed with $prefix and 'openid_association_' string + */ + function associationKey($server_url, $handle = null) + { + return $this->prefix . + 'openid_association_' . + sha1($server_url) . '_' . sha1($handle); + } + + /** + * Key is prefixed with $prefix and 'openid_association_server_' string + */ + function associationServerKey($server_url) + { + return $this->prefix . + 'openid_association_server_' . + sha1($server_url); + } + + /** + * Report that this storage doesn't support cleanup + */ + function supportsCleanup() + { + return false; + } + +} + diff --git a/Auth/OpenID/TrustRoot.php b/Auth/OpenID/TrustRoot.php index 000440b..5e69490 100644 --- a/Auth/OpenID/TrustRoot.php +++ b/Auth/OpenID/TrustRoot.php @@ -210,7 +210,7 @@ class Auth_OpenID_TrustRoot { if ($parts['host'] == 'localhost') { return true; } - + $host_parts = explode('.', $parts['host']); if ($parts['wildcard']) { // Remove the empty string from the beginning of the array @@ -413,7 +413,7 @@ function Auth_OpenID_getAllowedReturnURLs($relying_party_url, $fetcher, } call_user_func_array($discover_function, - array($relying_party_url, &$fetcher)); + array($relying_party_url, $fetcher)); $return_to_urls = array(); $matching_endpoints = Auth_OpenID_extractReturnURL($endpoints); diff --git a/Auth/Yadis/Manager.php b/Auth/Yadis/Manager.php index 15e6907..664521c 100644 --- a/Auth/Yadis/Manager.php +++ b/Auth/Yadis/Manager.php @@ -414,7 +414,7 @@ class Auth_Yadis_Discovery { list($yadis_url, $services) = call_user_func_array($discover_cb, array( $this->url, - &$fetcher, + $fetcher, )); $manager = $this->createManager($services, $yadis_url); diff --git a/Auth/Yadis/XML.php b/Auth/Yadis/XML.php index cf1f5c4..39a9942 100644 --- a/Auth/Yadis/XML.php +++ b/Auth/Yadis/XML.php @@ -234,7 +234,19 @@ class Auth_Yadis_dom extends Auth_Yadis_XMLParser { return false; } - if (!@$this->doc->loadXML($xml_string)) { + // libxml_disable_entity_loader (PHP 5 >= 5.2.11) + if (function_exists('libxml_disable_entity_loader') && function_exists('libxml_use_internal_errors')) { + // disable external entities and libxml errors + $loader = libxml_disable_entity_loader(true); + $errors = libxml_use_internal_errors(true); + $parse_result = @$this->doc->loadXML($xml_string); + libxml_disable_entity_loader($loader); + libxml_use_internal_errors($errors); + } else { + $parse_result = @$this->doc->loadXML($xml_string); + } + + if (!$parse_result) { return false; } diff --git a/Auth/Yadis/XRDS.php b/Auth/Yadis/XRDS.php index 1f5af96..044d1e7 100644 --- a/Auth/Yadis/XRDS.php +++ b/Auth/Yadis/XRDS.php @@ -429,7 +429,7 @@ class Auth_Yadis_XRDS { foreach ($filters as $filter) { - if (call_user_func_array($filter, array(&$service))) { + if (call_user_func_array($filter, array($service))) { $matches++; if ($filter_mode == SERVICES_YADIS_MATCH_ANY) { diff --git a/Auth/Yadis/Yadis.php b/Auth/Yadis/Yadis.php index 9ea2db7..f885367 100644 --- a/Auth/Yadis/Yadis.php +++ b/Auth/Yadis/Yadis.php @@ -141,7 +141,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, } $yadis_result = call_user_func_array($discover_func, - array($input_url, &$fetcher)); + array($input_url, $fetcher)); if ($yadis_result === null) { return array($input_url, array()); diff --git a/examples/detect.php b/examples/detect.php index 90e3995..892162f 100644 --- a/examples/detect.php +++ b/examples/detect.php @@ -434,7 +434,7 @@ function detect_fetcher($r, &$out) $ok = true; $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); - $fetch_url = 'https://raw.github.com/gist/465630/c57eff55ebc0c54973903af5f72bac72762cf4f4/helloworld'; + $fetch_url = 'https://gist.github.com/chuckpearce/6810258/raw/c57eff55ebc0c54973903af5f72bac72762cf4f4/gistfile1.txt'; $expected_url = $fetch_url;// . '.txt'; $result = $fetcher->get($fetch_url); |