613 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			613 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
|  | <?php | ||
|  | 
 | ||
|  | /** | ||
|  |  * This module contains code for dealing with associations between | ||
|  |  * consumers and servers. | ||
|  |  * | ||
|  |  * PHP versions 4 and 5 | ||
|  |  * | ||
|  |  * LICENSE: See the COPYING file included in this distribution. | ||
|  |  * | ||
|  |  * @package OpenID | ||
|  |  * @author JanRain, Inc. <openid@janrain.com> | ||
|  |  * @copyright 2005-2008 Janrain, Inc. | ||
|  |  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * @access private | ||
|  |  */ | ||
|  | require_once 'Auth/OpenID/CryptUtil.php'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @access private | ||
|  |  */ | ||
|  | require_once 'Auth/OpenID/KVForm.php'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * @access private | ||
|  |  */ | ||
|  | require_once 'Auth/OpenID/HMAC.php'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * This class represents an association between a server and a | ||
|  |  * consumer.  In general, users of this library will never see | ||
|  |  * instances of this object.  The only exception is if you implement a | ||
|  |  * custom {@link Auth_OpenID_OpenIDStore}. | ||
|  |  * | ||
|  |  * If you do implement such a store, it will need to store the values | ||
|  |  * of the handle, secret, issued, lifetime, and assoc_type instance | ||
|  |  * variables. | ||
|  |  * | ||
|  |  * @package OpenID | ||
|  |  */ | ||
|  | class Auth_OpenID_Association { | ||
|  | 
 | ||
|  |     /** | ||
|  |      * This is a HMAC-SHA1 specific value. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     var $SIG_LENGTH = 20; | ||
|  | 
 | ||
|  |     /** | ||
|  |      * The ordering and name of keys as stored by serialize. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     var $assoc_keys = array( | ||
|  |                             'version', | ||
|  |                             'handle', | ||
|  |                             'secret', | ||
|  |                             'issued', | ||
|  |                             'lifetime', | ||
|  |                             'assoc_type' | ||
|  |                             ); | ||
|  | 
 | ||
|  |     var $_macs = array( | ||
|  |                        'HMAC-SHA1' => 'Auth_OpenID_HMACSHA1', | ||
|  |                        'HMAC-SHA256' => 'Auth_OpenID_HMACSHA256' | ||
|  |                        ); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * This is an alternate constructor (factory method) used by the | ||
|  |      * OpenID consumer library to create associations.  OpenID store | ||
|  |      * implementations shouldn't use this constructor. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      * | ||
|  |      * @param integer $expires_in This is the amount of time this | ||
|  |      * association is good for, measured in seconds since the | ||
|  |      * association was issued. | ||
|  |      * | ||
|  |      * @param string $handle This is the handle the server gave this | ||
|  |      * association. | ||
|  |      * | ||
|  |      * @param string secret This is the shared secret the server | ||
|  |      * generated for this association. | ||
|  |      * | ||
|  |      * @param assoc_type This is the type of association this | ||
|  |      * instance represents.  The only valid values of this field at | ||
|  |      * this time is 'HMAC-SHA1' and 'HMAC-SHA256', but new types may | ||
|  |      * be defined in the future. | ||
|  |      * | ||
|  |      * @return association An {@link Auth_OpenID_Association} | ||
|  |      * instance. | ||
|  |      */ | ||
|  |     function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) | ||
|  |     { | ||
|  |         $issued = time(); | ||
|  |         $lifetime = $expires_in; | ||
|  |         return new Auth_OpenID_Association($handle, $secret, | ||
|  |                                            $issued, $lifetime, $assoc_type); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * This is the standard constructor for creating an association. | ||
|  |      * The library should create all of the necessary associations, so | ||
|  |      * this constructor is not part of the external API. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      * | ||
|  |      * @param string $handle This is the handle the server gave this | ||
|  |      * association. | ||
|  |      * | ||
|  |      * @param string $secret This is the shared secret the server | ||
|  |      * generated for this association. | ||
|  |      * | ||
|  |      * @param integer $issued This is the time this association was | ||
|  |      * issued, in seconds since 00:00 GMT, January 1, 1970.  (ie, a | ||
|  |      * unix timestamp) | ||
|  |      * | ||
|  |      * @param integer $lifetime This is the amount of time this | ||
|  |      * association is good for, measured in seconds since the | ||
|  |      * association was issued. | ||
|  |      * | ||
|  |      * @param string $assoc_type This is the type of association this | ||
|  |      * instance represents.  The only valid values of this field at | ||
|  |      * this time is 'HMAC-SHA1' and 'HMAC-SHA256', but new types may | ||
|  |      * be defined in the future. | ||
|  |      */ | ||
|  |     function Auth_OpenID_Association( | ||
|  |         $handle, $secret, $issued, $lifetime, $assoc_type) | ||
|  |     { | ||
|  |         if (!in_array($assoc_type, | ||
|  |                       Auth_OpenID_getSupportedAssociationTypes())) { | ||
|  |             $fmt = 'Unsupported association type (%s)'; | ||
|  |             trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR); | ||
|  |         } | ||
|  | 
 | ||
|  |         $this->handle = $handle; | ||
|  |         $this->secret = $secret; | ||
|  |         $this->issued = $issued; | ||
|  |         $this->lifetime = $lifetime; | ||
|  |         $this->assoc_type = $assoc_type; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * This returns the number of seconds this association is still | ||
|  |      * valid for, or 0 if the association is no longer valid. | ||
|  |      * | ||
|  |      * @return integer $seconds The number of seconds this association | ||
|  |      * is still valid for, or 0 if the association is no longer valid. | ||
|  |      */ | ||
|  |     function getExpiresIn($now = null) | ||
|  |     { | ||
|  |         if ($now == null) { | ||
|  |             $now = time(); | ||
|  |         } | ||
|  | 
 | ||
|  |         return max(0, $this->issued + $this->lifetime - $now); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * This checks to see if two {@link Auth_OpenID_Association} | ||
|  |      * instances represent the same association. | ||
|  |      * | ||
|  |      * @return bool $result true if the two instances represent the | ||
|  |      * same association, false otherwise. | ||
|  |      */ | ||
|  |     function equal($other) | ||
|  |     { | ||
|  |         return ((gettype($this) == gettype($other)) | ||
|  |                 && ($this->handle == $other->handle) | ||
|  |                 && ($this->secret == $other->secret) | ||
|  |                 && ($this->issued == $other->issued) | ||
|  |                 && ($this->lifetime == $other->lifetime) | ||
|  |                 && ($this->assoc_type == $other->assoc_type)); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Convert an association to KV form. | ||
|  |      * | ||
|  |      * @return string $result String in KV form suitable for | ||
|  |      * deserialization by deserialize. | ||
|  |      */ | ||
|  |     function serialize() | ||
|  |     { | ||
|  |         $data = array( | ||
|  |                      'version' => '2', | ||
|  |                      'handle' => $this->handle, | ||
|  |                      'secret' => base64_encode($this->secret), | ||
|  |                      'issued' => strval(intval($this->issued)), | ||
|  |                      'lifetime' => strval(intval($this->lifetime)), | ||
|  |                      'assoc_type' => $this->assoc_type | ||
|  |                      ); | ||
|  | 
 | ||
|  |         assert(array_keys($data) == $this->assoc_keys); | ||
|  | 
 | ||
|  |         return Auth_OpenID_KVForm::fromArray($data, $strict = true); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Parse an association as stored by serialize().  This is the | ||
|  |      * inverse of serialize. | ||
|  |      * | ||
|  |      * @param string $assoc_s Association as serialized by serialize() | ||
|  |      * @return Auth_OpenID_Association $result instance of this class | ||
|  |      */ | ||
|  |     function deserialize($class_name, $assoc_s) | ||
|  |     { | ||
|  |         $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true); | ||
|  |         $keys = array(); | ||
|  |         $values = array(); | ||
|  |         foreach ($pairs as $key => $value) { | ||
|  |             if (is_array($value)) { | ||
|  |                 list($key, $value) = $value; | ||
|  |             } | ||
|  |             $keys[] = $key; | ||
|  |             $values[] = $value; | ||
|  |         } | ||
|  | 
 | ||
|  |         $class_vars = get_class_vars($class_name); | ||
|  |         $class_assoc_keys = $class_vars['assoc_keys']; | ||
|  | 
 | ||
|  |         sort($keys); | ||
|  |         sort($class_assoc_keys); | ||
|  | 
 | ||
|  |         if ($keys != $class_assoc_keys) { | ||
|  |             trigger_error('Unexpected key values: ' . var_export($keys, true), | ||
|  |                           E_USER_WARNING); | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         $version = $pairs['version']; | ||
|  |         $handle = $pairs['handle']; | ||
|  |         $secret = $pairs['secret']; | ||
|  |         $issued = $pairs['issued']; | ||
|  |         $lifetime = $pairs['lifetime']; | ||
|  |         $assoc_type = $pairs['assoc_type']; | ||
|  | 
 | ||
|  |         if ($version != '2') { | ||
|  |             trigger_error('Unknown version: ' . $version, E_USER_WARNING); | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         $issued = intval($issued); | ||
|  |         $lifetime = intval($lifetime); | ||
|  |         $secret = base64_decode($secret); | ||
|  | 
 | ||
|  |         return new $class_name( | ||
|  |             $handle, $secret, $issued, $lifetime, $assoc_type); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Generate a signature for a sequence of (key, value) pairs | ||
|  |      * | ||
|  |      * @access private | ||
|  |      * @param array $pairs The pairs to sign, in order.  This is an | ||
|  |      * array of two-tuples. | ||
|  |      * @return string $signature The binary signature of this sequence | ||
|  |      * of pairs | ||
|  |      */ | ||
|  |     function sign($pairs) | ||
|  |     { | ||
|  |         $kv = Auth_OpenID_KVForm::fromArray($pairs); | ||
|  | 
 | ||
|  |         /* Invalid association types should be caught at constructor */ | ||
|  |         $callback = $this->_macs[$this->assoc_type]; | ||
|  | 
 | ||
|  |         return call_user_func_array($callback, array($this->secret, $kv)); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Generate a signature for some fields in a dictionary | ||
|  |      * | ||
|  |      * @access private | ||
|  |      * @param array $fields The fields to sign, in order; this is an | ||
|  |      * array of strings. | ||
|  |      * @param array $data Dictionary of values to sign (an array of | ||
|  |      * string => string pairs). | ||
|  |      * @return string $signature The signature, base64 encoded | ||
|  |      */ | ||
|  |     function signMessage($message) | ||
|  |     { | ||
|  |         if ($message->hasKey(Auth_OpenID_OPENID_NS, 'sig') || | ||
|  |             $message->hasKey(Auth_OpenID_OPENID_NS, 'signed')) { | ||
|  |             // Already has a sig
 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         $extant_handle = $message->getArg(Auth_OpenID_OPENID_NS, | ||
|  |                                           'assoc_handle'); | ||
|  | 
 | ||
|  |         if ($extant_handle && ($extant_handle != $this->handle)) { | ||
|  |             // raise ValueError("Message has a different association handle")
 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         $signed_message = $message; | ||
|  |         $signed_message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', | ||
|  |                                 $this->handle); | ||
|  | 
 | ||
|  |         $message_keys = array_keys($signed_message->toPostArgs()); | ||
|  |         $signed_list = array(); | ||
|  |         $signed_prefix = 'openid.'; | ||
|  | 
 | ||
|  |         foreach ($message_keys as $k) { | ||
|  |             if (strpos($k, $signed_prefix) === 0) { | ||
|  |                 $signed_list[] = substr($k, strlen($signed_prefix)); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         $signed_list[] = 'signed'; | ||
|  |         sort($signed_list); | ||
|  | 
 | ||
|  |         $signed_message->setArg(Auth_OpenID_OPENID_NS, 'signed', | ||
|  |                                 implode(',', $signed_list)); | ||
|  |         $sig = $this->getMessageSignature($signed_message); | ||
|  |         $signed_message->setArg(Auth_OpenID_OPENID_NS, 'sig', $sig); | ||
|  |         return $signed_message; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Given a {@link Auth_OpenID_Message}, return the key/value pairs | ||
|  |      * to be signed according to the signed list in the message.  If | ||
|  |      * the message lacks a signed list, return null. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     function _makePairs(&$message) | ||
|  |     { | ||
|  |         $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); | ||
|  |         if (!$signed || Auth_OpenID::isFailure($signed)) { | ||
|  |             // raise ValueError('Message has no signed list: %s' % (message,))
 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         $signed_list = explode(',', $signed); | ||
|  |         $pairs = array(); | ||
|  |         $data = $message->toPostArgs(); | ||
|  |         foreach ($signed_list as $field) { | ||
|  |             $pairs[] = array($field, Auth_OpenID::arrayGet($data, | ||
|  |                                                            'openid.' . | ||
|  |                                                            $field, '')); | ||
|  |         } | ||
|  |         return $pairs; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Given an {@link Auth_OpenID_Message}, return the signature for | ||
|  |      * the signed list in the message. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     function getMessageSignature(&$message) | ||
|  |     { | ||
|  |         $pairs = $this->_makePairs($message); | ||
|  |         return base64_encode($this->sign($pairs)); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Confirm that the signature of these fields matches the | ||
|  |      * signature contained in the data. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     function checkMessageSignature(&$message) | ||
|  |     { | ||
|  |         $sig = $message->getArg(Auth_OpenID_OPENID_NS, | ||
|  |                                 'sig'); | ||
|  | 
 | ||
|  |         if (!$sig || Auth_OpenID::isFailure($sig)) { | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         $calculated_sig = $this->getMessageSignature($message); | ||
|  |         return $calculated_sig == $sig; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getSecretSize($assoc_type) | ||
|  | { | ||
|  |     if ($assoc_type == 'HMAC-SHA1') { | ||
|  |         return 20; | ||
|  |     } else if ($assoc_type == 'HMAC-SHA256') { | ||
|  |         return 32; | ||
|  |     } else { | ||
|  |         return null; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getAllAssociationTypes() | ||
|  | { | ||
|  |     return array('HMAC-SHA1', 'HMAC-SHA256'); | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getSupportedAssociationTypes() | ||
|  | { | ||
|  |     $a = array('HMAC-SHA1'); | ||
|  | 
 | ||
|  |     if (Auth_OpenID_HMACSHA256_SUPPORTED) { | ||
|  |         $a[] = 'HMAC-SHA256'; | ||
|  |     } | ||
|  | 
 | ||
|  |     return $a; | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getSessionTypes($assoc_type) | ||
|  | { | ||
|  |     $assoc_to_session = array( | ||
|  |        'HMAC-SHA1' => array('DH-SHA1', 'no-encryption')); | ||
|  | 
 | ||
|  |     if (Auth_OpenID_HMACSHA256_SUPPORTED) { | ||
|  |         $assoc_to_session['HMAC-SHA256'] = | ||
|  |             array('DH-SHA256', 'no-encryption'); | ||
|  |     } | ||
|  | 
 | ||
|  |     return Auth_OpenID::arrayGet($assoc_to_session, $assoc_type, array()); | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_checkSessionType($assoc_type, $session_type) | ||
|  | { | ||
|  |     if (!in_array($session_type, | ||
|  |                   Auth_OpenID_getSessionTypes($assoc_type))) { | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     return true; | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getDefaultAssociationOrder() | ||
|  | { | ||
|  |     $order = array(); | ||
|  | 
 | ||
|  |     if (!Auth_OpenID_noMathSupport()) { | ||
|  |         $order[] = array('HMAC-SHA1', 'DH-SHA1'); | ||
|  | 
 | ||
|  |         if (Auth_OpenID_HMACSHA256_SUPPORTED) { | ||
|  |             $order[] = array('HMAC-SHA256', 'DH-SHA256'); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     $order[] = array('HMAC-SHA1', 'no-encryption'); | ||
|  | 
 | ||
|  |     if (Auth_OpenID_HMACSHA256_SUPPORTED) { | ||
|  |         $order[] = array('HMAC-SHA256', 'no-encryption'); | ||
|  |     } | ||
|  | 
 | ||
|  |     return $order; | ||
|  | } | ||
|  | 
 | ||
|  | function Auth_OpenID_getOnlyEncryptedOrder() | ||
|  | { | ||
|  |     $result = array(); | ||
|  | 
 | ||
|  |     foreach (Auth_OpenID_getDefaultAssociationOrder() as $pair) { | ||
|  |         list($assoc, $session) = $pair; | ||
|  | 
 | ||
|  |         if ($session != 'no-encryption') { | ||
|  |             if (Auth_OpenID_HMACSHA256_SUPPORTED && | ||
|  |                 ($assoc == 'HMAC-SHA256')) { | ||
|  |                 $result[] = $pair; | ||
|  |             } else if ($assoc != 'HMAC-SHA256') { | ||
|  |                 $result[] = $pair; | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     return $result; | ||
|  | } | ||
|  | 
 | ||
|  | function &Auth_OpenID_getDefaultNegotiator() | ||
|  | { | ||
|  |     $x = new Auth_OpenID_SessionNegotiator( | ||
|  |                  Auth_OpenID_getDefaultAssociationOrder()); | ||
|  |     return $x; | ||
|  | } | ||
|  | 
 | ||
|  | function &Auth_OpenID_getEncryptedNegotiator() | ||
|  | { | ||
|  |     $x = new Auth_OpenID_SessionNegotiator( | ||
|  |                  Auth_OpenID_getOnlyEncryptedOrder()); | ||
|  |     return $x; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * A session negotiator controls the allowed and preferred association | ||
|  |  * types and association session types. Both the {@link | ||
|  |  * Auth_OpenID_Consumer} and {@link Auth_OpenID_Server} use | ||
|  |  * negotiators when creating associations. | ||
|  |  * | ||
|  |  * You can create and use negotiators if you: | ||
|  | 
 | ||
|  |  * - Do not want to do Diffie-Hellman key exchange because you use | ||
|  |  * transport-layer encryption (e.g. SSL) | ||
|  |  * | ||
|  |  * - Want to use only SHA-256 associations | ||
|  |  * | ||
|  |  * - Do not want to support plain-text associations over a non-secure | ||
|  |  * channel | ||
|  |  * | ||
|  |  * It is up to you to set a policy for what kinds of associations to | ||
|  |  * accept. By default, the library will make any kind of association | ||
|  |  * that is allowed in the OpenID 2.0 specification. | ||
|  |  * | ||
|  |  * Use of negotiators in the library | ||
|  |  * ================================= | ||
|  |  * | ||
|  |  * When a consumer makes an association request, it calls {@link | ||
|  |  * getAllowedType} to get the preferred association type and | ||
|  |  * association session type. | ||
|  |  * | ||
|  |  * The server gets a request for a particular association/session type | ||
|  |  * and calls {@link isAllowed} to determine if it should create an | ||
|  |  * association. If it is supported, negotiation is complete. If it is | ||
|  |  * not, the server calls {@link getAllowedType} to get an allowed | ||
|  |  * association type to return to the consumer. | ||
|  |  * | ||
|  |  * If the consumer gets an error response indicating that the | ||
|  |  * requested association/session type is not supported by the server | ||
|  |  * that contains an assocation/session type to try, it calls {@link | ||
|  |  * isAllowed} to determine if it should try again with the given | ||
|  |  * combination of association/session type. | ||
|  |  * | ||
|  |  * @package OpenID | ||
|  |  */ | ||
|  | class Auth_OpenID_SessionNegotiator { | ||
|  |     function Auth_OpenID_SessionNegotiator($allowed_types) | ||
|  |     { | ||
|  |         $this->allowed_types = array(); | ||
|  |         $this->setAllowedTypes($allowed_types); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Set the allowed association types, checking to make sure each | ||
|  |      * combination is valid. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     function setAllowedTypes($allowed_types) | ||
|  |     { | ||
|  |         foreach ($allowed_types as $pair) { | ||
|  |             list($assoc_type, $session_type) = $pair; | ||
|  |             if (!Auth_OpenID_checkSessionType($assoc_type, $session_type)) { | ||
|  |                 return false; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         $this->allowed_types = $allowed_types; | ||
|  |         return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Add an association type and session type to the allowed types | ||
|  |      * list. The assocation/session pairs are tried in the order that | ||
|  |      * they are added. | ||
|  |      * | ||
|  |      * @access private | ||
|  |      */ | ||
|  |     function addAllowedType($assoc_type, $session_type = null) | ||
|  |     { | ||
|  |         if ($this->allowed_types === null) { | ||
|  |             $this->allowed_types = array(); | ||
|  |         } | ||
|  | 
 | ||
|  |         if ($session_type === null) { | ||
|  |             $available = Auth_OpenID_getSessionTypes($assoc_type); | ||
|  | 
 | ||
|  |             if (!$available) { | ||
|  |                 return false; | ||
|  |             } | ||
|  | 
 | ||
|  |             foreach ($available as $session_type) { | ||
|  |                 $this->addAllowedType($assoc_type, $session_type); | ||
|  |             } | ||
|  |         } else { | ||
|  |             if (Auth_OpenID_checkSessionType($assoc_type, $session_type)) { | ||
|  |                 $this->allowed_types[] = array($assoc_type, $session_type); | ||
|  |             } else { | ||
|  |                 return false; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Is this combination of association type and session type allowed?
 | ||
|  |     function isAllowed($assoc_type, $session_type) | ||
|  |     { | ||
|  |         $assoc_good = in_array(array($assoc_type, $session_type), | ||
|  |                                $this->allowed_types); | ||
|  | 
 | ||
|  |         $matches = in_array($session_type, | ||
|  |                             Auth_OpenID_getSessionTypes($assoc_type)); | ||
|  | 
 | ||
|  |         return ($assoc_good && $matches); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Get a pair of assocation type and session type that are | ||
|  |      * supported. | ||
|  |      */ | ||
|  |     function getAllowedType() | ||
|  |     { | ||
|  |         if (!$this->allowed_types) { | ||
|  |             return array(null, null); | ||
|  |         } | ||
|  | 
 | ||
|  |         return $this->allowed_types[0]; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | ?>
 |