mirror of
				https://github.com/Icinga/icingaweb2.git
				synced 2025-10-31 03:14:31 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			800 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			800 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| /**
 | |
|  * Zend Framework
 | |
|  *
 | |
|  * LICENSE
 | |
|  *
 | |
|  * This source file is subject to the new BSD license that is bundled
 | |
|  * with this package in the file LICENSE.txt.
 | |
|  * It is also available through the world-wide-web at this URL:
 | |
|  * http://framework.zend.com/license/new-bsd
 | |
|  * If you did not receive a copy of the license and are unable to
 | |
|  * obtain it through the world-wide-web, please send an email
 | |
|  * to license@zend.com so we can send you a copy immediately.
 | |
|  *
 | |
|  * @category   Zend
 | |
|  * @package    Zend_OpenId
 | |
|  * @subpackage Zend_OpenId_Provider
 | |
|  * @copyright  Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  * @version    $Id$
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @see Zend_OpenId
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @see Zend_OpenId_Extension
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * OpenID provider (server) implementation
 | |
|  *
 | |
|  * @category   Zend
 | |
|  * @package    Zend_OpenId
 | |
|  * @subpackage Zend_OpenId_Provider
 | |
|  * @copyright  Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  */
 | |
| class Zend_OpenId_Provider
 | |
| {
 | |
| 
 | |
|     /**
 | |
|      * Reference to an implementation of storage object
 | |
|      *
 | |
|      * @var Zend_OpenId_Provider_Storage $_storage
 | |
|      */
 | |
|     private $_storage;
 | |
| 
 | |
|     /**
 | |
|      * Reference to an implementation of user object
 | |
|      *
 | |
|      * @var Zend_OpenId_Provider_User $_user
 | |
|      */
 | |
|     private $_user;
 | |
| 
 | |
|     /**
 | |
|      * Time to live of association session in secconds
 | |
|      *
 | |
|      * @var integer $_sessionTtl
 | |
|      */
 | |
|     private $_sessionTtl;
 | |
| 
 | |
|     /**
 | |
|      * URL to peform interactive user login
 | |
|      *
 | |
|      * @var string $_loginUrl
 | |
|      */
 | |
|     private $_loginUrl;
 | |
| 
 | |
|     /**
 | |
|      * URL to peform interactive validation of consumer by user
 | |
|      *
 | |
|      * @var string $_trustUrl
 | |
|      */
 | |
|     private $_trustUrl;
 | |
| 
 | |
|     /**
 | |
|      * The OP Endpoint URL
 | |
|      *
 | |
|      * @var string $_opEndpoint
 | |
|      */
 | |
|     private $_opEndpoint;
 | |
| 
 | |
|     /**
 | |
|      * Constructs a Zend_OpenId_Provider object with given parameters.
 | |
|      *
 | |
|      * @param string $loginUrl is an URL that provides login screen for
 | |
|      *  end-user (by default it is the same URL with additional GET variable
 | |
|      *  openid.action=login)
 | |
|      * @param string $trustUrl is an URL that shows a question if end-user
 | |
|      *  trust to given consumer (by default it is the same URL with additional
 | |
|      *  GET variable openid.action=trust)
 | |
|      * @param Zend_OpenId_Provider_User $user is an object for communication
 | |
|      *  with User-Agent and store information about logged-in user (it is a
 | |
|      *  Zend_OpenId_Provider_User_Session object by default)
 | |
|      * @param Zend_OpenId_Provider_Storage $storage is an object for keeping
 | |
|      *  persistent database (it is a Zend_OpenId_Provider_Storage_File object
 | |
|      *  by default)
 | |
|      * @param integer $sessionTtl is a default time to live for association
 | |
|      *   session in seconds (1 hour by default). Consumer must reestablish
 | |
|      *   association after that time.
 | |
|      */
 | |
|     public function __construct($loginUrl = null,
 | |
|                                 $trustUrl = null,
 | |
|                                 Zend_OpenId_Provider_User $user = null,
 | |
|                                 Zend_OpenId_Provider_Storage $storage = null,
 | |
|                                 $sessionTtl = 3600)
 | |
|     {
 | |
|         if ($loginUrl === null) {
 | |
|             $loginUrl = Zend_OpenId::selfUrl() . '?openid.action=login';
 | |
|         } else {
 | |
|             $loginUrl = Zend_OpenId::absoluteUrl($loginUrl);
 | |
|         }
 | |
|         $this->_loginUrl = $loginUrl;
 | |
|         if ($trustUrl === null) {
 | |
|             $trustUrl = Zend_OpenId::selfUrl() . '?openid.action=trust';
 | |
|         } else {
 | |
|             $trustUrl = Zend_OpenId::absoluteUrl($trustUrl);
 | |
|         }
 | |
|         $this->_trustUrl = $trustUrl;
 | |
|         if ($user === null) {
 | |
|             $this->_user = new Zend_OpenId_Provider_User_Session();
 | |
|         } else {
 | |
|             $this->_user = $user;
 | |
|         }
 | |
|         if ($storage === null) {
 | |
|             $this->_storage = new Zend_OpenId_Provider_Storage_File();
 | |
|         } else {
 | |
|             $this->_storage = $storage;
 | |
|         }
 | |
|         $this->_sessionTtl = $sessionTtl;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the OP Endpoint URL
 | |
|      *
 | |
|      * @param string $url the OP Endpoint URL
 | |
|      * @return null
 | |
|      */
 | |
|     public function setOpEndpoint($url)
 | |
|     {
 | |
|         $this->_opEndpoint = $url;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Registers a new user with given $id and $password
 | |
|      * Returns true in case of success and false if user with given $id already
 | |
|      * exists
 | |
|      *
 | |
|      * @param string $id user identity URL
 | |
|      * @param string $password encoded user password
 | |
|      * @return bool
 | |
|      */
 | |
|     public function register($id, $password)
 | |
|     {
 | |
|         if (!Zend_OpenId::normalize($id) || empty($id)) {
 | |
|             return false;
 | |
|         }
 | |
|         return $this->_storage->addUser($id, md5($id.$password));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns true if user with given $id exists and false otherwise
 | |
|      *
 | |
|      * @param string $id user identity URL
 | |
|      * @return bool
 | |
|      */
 | |
|     public function hasUser($id) {
 | |
|         if (!Zend_OpenId::normalize($id)) {
 | |
|             return false;
 | |
|         }
 | |
|         return $this->_storage->hasUser($id);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs login of user with given $id and $password
 | |
|      * Returns true in case of success and false otherwise
 | |
|      *
 | |
|      * @param string $id user identity URL
 | |
|      * @param string $password user password
 | |
|      * @return bool
 | |
|      */
 | |
|     public function login($id, $password)
 | |
|     {
 | |
|         if (!Zend_OpenId::normalize($id)) {
 | |
|             return false;
 | |
|         }
 | |
|         if (!$this->_storage->checkUser($id, md5($id.$password))) {
 | |
|             return false;
 | |
|         }
 | |
|         $this->_user->setLoggedInUser($id);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs logout. Clears information about logged in user.
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function logout()
 | |
|     {
 | |
|         $this->_user->delLoggedInUser();
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns identity URL of current logged in user or false
 | |
|      *
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function getLoggedInUser() {
 | |
|         return $this->_user->getLoggedInUser();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Retrieve consumer's root URL from request query.
 | |
|      * Returns URL or false in case of failure
 | |
|      *
 | |
|      * @param array $params query arguments
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function getSiteRoot($params)
 | |
|     {
 | |
|         $version = 1.1;
 | |
|         if (isset($params['openid_ns']) &&
 | |
|             $params['openid_ns'] == Zend_OpenId::NS_2_0) {
 | |
|             $version = 2.0;
 | |
|         }
 | |
|         if ($version >= 2.0 && isset($params['openid_realm'])) {
 | |
|             $root = $params['openid_realm'];
 | |
|         } else if ($version < 2.0 && isset($params['openid_trust_root'])) {
 | |
|             $root = $params['openid_trust_root'];
 | |
|         } else if (isset($params['openid_return_to'])) {
 | |
|             $root = $params['openid_return_to'];
 | |
|         } else {
 | |
|             return false;
 | |
|         }
 | |
|         if (Zend_OpenId::normalizeUrl($root) && !empty($root)) {
 | |
|             return $root;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Allows consumer with given root URL to authenticate current logged
 | |
|      * in user. Returns true on success and false on error.
 | |
|      *
 | |
|      * @param string $root root URL
 | |
|      * @param mixed $extensions extension object or array of extensions objects
 | |
|      * @return bool
 | |
|      */
 | |
|     public function allowSite($root, $extensions=null)
 | |
|     {
 | |
|         $id = $this->getLoggedInUser();
 | |
|         if ($id === false) {
 | |
|             return false;
 | |
|         }
 | |
|         if ($extensions !== null) {
 | |
|             $data = array();
 | |
|             Zend_OpenId_Extension::forAll($extensions, 'getTrustData', $data);
 | |
|         } else {
 | |
|             $data = true;
 | |
|         }
 | |
|         $this->_storage->addSite($id, $root, $data);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Prohibit consumer with given root URL to authenticate current logged
 | |
|      * in user. Returns true on success and false on error.
 | |
|      *
 | |
|      * @param string $root root URL
 | |
|      * @return bool
 | |
|      */
 | |
|     public function denySite($root)
 | |
|     {
 | |
|         $id = $this->getLoggedInUser();
 | |
|         if ($id === false) {
 | |
|             return false;
 | |
|         }
 | |
|         $this->_storage->addSite($id, $root, false);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Delete consumer with given root URL from known sites of current logged
 | |
|      * in user. Next time this consumer will try to authenticate the user,
 | |
|      * Provider will ask user's confirmation.
 | |
|      * Returns true on success and false on error.
 | |
|      *
 | |
|      * @param string $root root URL
 | |
|      * @return bool
 | |
|      */
 | |
|     public function delSite($root)
 | |
|     {
 | |
|         $id = $this->getLoggedInUser();
 | |
|         if ($id === false) {
 | |
|             return false;
 | |
|         }
 | |
|         $this->_storage->addSite($id, $root, null);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns list of known consumers for current logged in user or false
 | |
|      * if he is not logged in.
 | |
|      *
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function getTrustedSites()
 | |
|     {
 | |
|         $id = $this->getLoggedInUser();
 | |
|         if ($id === false) {
 | |
|             return false;
 | |
|         }
 | |
|         return $this->_storage->getTrustedSites($id);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Handles HTTP request from consumer
 | |
|      *
 | |
|      * @param array $params GET or POST variables. If this parameter is omited
 | |
|      *  or set to null, then $_GET or $_POST superglobal variable is used
 | |
|      *  according to REQUEST_METHOD.
 | |
|      * @param mixed $extensions extension object or array of extensions objects
 | |
|      * @param Zend_Controller_Response_Abstract $response an optional response
 | |
|      *  object to perform HTTP or HTML form redirection
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function handle($params=null, $extensions=null,
 | |
|                            Zend_Controller_Response_Abstract $response = null)
 | |
|     {
 | |
|         if ($params === null) {
 | |
|             if ($_SERVER["REQUEST_METHOD"] == "GET") {
 | |
|                 $params = $_GET;
 | |
|             } else if ($_SERVER["REQUEST_METHOD"] == "POST") {
 | |
|                 $params = $_POST;
 | |
|             } else {
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
|         $version = 1.1;
 | |
|         if (isset($params['openid_ns']) &&
 | |
|             $params['openid_ns'] == Zend_OpenId::NS_2_0) {
 | |
|             $version = 2.0;
 | |
|         }
 | |
|         if (isset($params['openid_mode'])) {
 | |
|             if ($params['openid_mode'] == 'associate') {
 | |
|                 $response = $this->_associate($version, $params);
 | |
|                 $ret = '';
 | |
|                 foreach ($response as $key => $val) {
 | |
|                     $ret .= $key . ':' . $val . "\n";
 | |
|                 }
 | |
|                 return $ret;
 | |
|             } else if ($params['openid_mode'] == 'checkid_immediate') {
 | |
|                 $ret = $this->_checkId($version, $params, 1, $extensions, $response);
 | |
|                 if (is_bool($ret)) return $ret;
 | |
|                 if (!empty($params['openid_return_to'])) {
 | |
|                     Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
 | |
|                 }
 | |
|                 return true;
 | |
|             } else if ($params['openid_mode'] == 'checkid_setup') {
 | |
|                 $ret = $this->_checkId($version, $params, 0, $extensions, $response);
 | |
|                 if (is_bool($ret)) return $ret;
 | |
|                 if (!empty($params['openid_return_to'])) {
 | |
|                     Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
 | |
|                 }
 | |
|                 return true;
 | |
|             } else if ($params['openid_mode'] == 'check_authentication') {
 | |
|                 $response = $this->_checkAuthentication($version, $params);
 | |
|                 $ret = '';
 | |
|                 foreach ($response as $key => $val) {
 | |
|                     $ret .= $key . ':' . $val . "\n";
 | |
|                 }
 | |
|                 return $ret;
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Generates a secret key for given hash function, returns RAW key or false
 | |
|      * if function is not supported
 | |
|      *
 | |
|      * @param string $func hash function (sha1 or sha256)
 | |
|      * @return mixed
 | |
|      */
 | |
|     protected function _genSecret($func)
 | |
|     {
 | |
|         if ($func == 'sha1') {
 | |
|             $macLen = 20; /* 160 bit */
 | |
|         } else if ($func == 'sha256') {
 | |
|             $macLen = 32; /* 256 bit */
 | |
|         } else {
 | |
|             return false;
 | |
|         }
 | |
|         return Zend_OpenId::randomBytes($macLen);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Processes association request from OpenID consumerm generates secret
 | |
|      * shared key and send it back using Diffie-Hellman encruption.
 | |
|      * Returns array of variables to push back to consumer.
 | |
|      *
 | |
|      * @param float $version OpenID version
 | |
|      * @param array $params GET or POST request variables
 | |
|      * @return array
 | |
|      */
 | |
|     protected function _associate($version, $params)
 | |
|     {
 | |
|         $ret = array();
 | |
| 
 | |
|         if ($version >= 2.0) {
 | |
|             $ret['ns'] = Zend_OpenId::NS_2_0;
 | |
|         }
 | |
| 
 | |
|         if (isset($params['openid_assoc_type']) &&
 | |
|             $params['openid_assoc_type'] == 'HMAC-SHA1') {
 | |
|             $macFunc = 'sha1';
 | |
|         } else if (isset($params['openid_assoc_type']) &&
 | |
|             $params['openid_assoc_type'] == 'HMAC-SHA256' &&
 | |
|             $version >= 2.0) {
 | |
|             $macFunc = 'sha256';
 | |
|         } else {
 | |
|             $ret['error'] = 'Wrong "openid.assoc_type"';
 | |
|             $ret['error-code'] = 'unsupported-type';
 | |
|             return $ret;
 | |
|         }
 | |
| 
 | |
|         $ret['assoc_type'] = $params['openid_assoc_type'];
 | |
| 
 | |
|         $secret = $this->_genSecret($macFunc);
 | |
| 
 | |
|         if (empty($params['openid_session_type']) ||
 | |
|             $params['openid_session_type'] == 'no-encryption') {
 | |
|             $ret['mac_key'] = base64_encode($secret);
 | |
|         } else if (isset($params['openid_session_type']) &&
 | |
|             $params['openid_session_type'] == 'DH-SHA1') {
 | |
|             $dhFunc = 'sha1';
 | |
|         } else if (isset($params['openid_session_type']) &&
 | |
|             $params['openid_session_type'] == 'DH-SHA256' &&
 | |
|             $version >= 2.0) {
 | |
|             $dhFunc = 'sha256';
 | |
|         } else {
 | |
|             $ret['error'] = 'Wrong "openid.session_type"';
 | |
|             $ret['error-code'] = 'unsupported-type';
 | |
|             return $ret;
 | |
|         }
 | |
| 
 | |
|         if (isset($params['openid_session_type'])) {
 | |
|             $ret['session_type'] = $params['openid_session_type'];
 | |
|         }
 | |
| 
 | |
|         if (isset($dhFunc)) {
 | |
|             if (empty($params['openid_dh_consumer_public'])) {
 | |
|                 $ret['error'] = 'Wrong "openid.dh_consumer_public"';
 | |
|                 return $ret;
 | |
|             }
 | |
|             if (empty($params['openid_dh_gen'])) {
 | |
|                 $g = pack('H*', Zend_OpenId::DH_G);
 | |
|             } else {
 | |
|                 $g = base64_decode($params['openid_dh_gen']);
 | |
|             }
 | |
|             if (empty($params['openid_dh_modulus'])) {
 | |
|                 $p = pack('H*', Zend_OpenId::DH_P);
 | |
|             } else {
 | |
|                 $p = base64_decode($params['openid_dh_modulus']);
 | |
|             }
 | |
| 
 | |
|             $dh = Zend_OpenId::createDhKey($p, $g);
 | |
|             $dh_details = Zend_OpenId::getDhKeyDetails($dh);
 | |
| 
 | |
|             $sec = Zend_OpenId::computeDhSecret(
 | |
|                 base64_decode($params['openid_dh_consumer_public']), $dh);
 | |
|             if ($sec === false) {
 | |
|                 $ret['error'] = 'Wrong "openid.session_type"';
 | |
|                 $ret['error-code'] = 'unsupported-type';
 | |
|                 return $ret;
 | |
|             }
 | |
|             $sec = Zend_OpenId::digest($dhFunc, $sec);
 | |
|             $ret['dh_server_public'] = base64_encode(
 | |
|                 Zend_OpenId::btwoc($dh_details['pub_key']));
 | |
|             $ret['enc_mac_key']      = base64_encode($secret ^ $sec);
 | |
|         }
 | |
| 
 | |
|         $handle = uniqid();
 | |
|         $expiresIn = $this->_sessionTtl;
 | |
| 
 | |
|         $ret['assoc_handle'] = $handle;
 | |
|         $ret['expires_in'] = $expiresIn;
 | |
| 
 | |
|         $this->_storage->addAssociation($handle,
 | |
|             $macFunc, $secret, time() + $expiresIn);
 | |
| 
 | |
|         return $ret;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs authentication (or authentication check).
 | |
|      *
 | |
|      * @param float $version OpenID version
 | |
|      * @param array $params GET or POST request variables
 | |
|      * @param bool $immediate enables or disables interaction with user
 | |
|      * @param mixed $extensions extension object or array of extensions objects
 | |
|      * @param Zend_Controller_Response_Abstract $response
 | |
|      * @return array
 | |
|      */
 | |
|     protected function _checkId($version, $params, $immediate, $extensions=null,
 | |
|         Zend_Controller_Response_Abstract $response = null)
 | |
|     {
 | |
|         $ret = array();
 | |
| 
 | |
|         if ($version >= 2.0) {
 | |
|             $ret['openid.ns'] = Zend_OpenId::NS_2_0;
 | |
|         }
 | |
|         $root = $this->getSiteRoot($params);
 | |
|         if ($root === false) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         if (isset($params['openid_identity']) &&
 | |
|             !$this->_storage->hasUser($params['openid_identity'])) {
 | |
|             $ret['openid.mode'] = ($immediate && $version >= 2.0) ? 'setup_needed': 'cancel';
 | |
|             return $ret;
 | |
|         }
 | |
| 
 | |
|         /* Check if user already logged in into the server */
 | |
|         if (!isset($params['openid_identity']) ||
 | |
|             $this->_user->getLoggedInUser() !== $params['openid_identity']) {
 | |
|             $params2 = array();
 | |
|             foreach ($params as $key => $val) {
 | |
|                 if (strpos($key, 'openid_ns_') === 0) {
 | |
|                     $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
 | |
|                 } else if (strpos($key, 'openid_sreg_') === 0) {
 | |
|                     $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
 | |
|                 } else if (strpos($key, 'openid_') === 0) {
 | |
|                     $key = 'openid.' . substr($key, strlen('openid_'));
 | |
|                 }
 | |
|                 $params2[$key] = $val;
 | |
|             }
 | |
|             if ($immediate) {
 | |
|                 $params2['openid.mode'] = 'checkid_setup';
 | |
|                 $ret['openid.mode'] = ($version >= 2.0) ? 'setup_needed': 'id_res';
 | |
|                 $ret['openid.user_setup_url'] = $this->_loginUrl
 | |
|                     . (strpos($this->_loginUrl, '?') === false ? '?' : '&')
 | |
|                     . Zend_OpenId::paramsToQuery($params2);
 | |
|                 return $ret;
 | |
|             } else {
 | |
|                 /* Redirect to Server Login Screen */
 | |
|                 Zend_OpenId::redirect($this->_loginUrl, $params2, $response);
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!Zend_OpenId_Extension::forAll($extensions, 'parseRequest', $params)) {
 | |
|             $ret['openid.mode'] = ($immediate && $version >= 2.0) ? 'setup_needed': 'cancel';
 | |
|             return $ret;
 | |
|         }
 | |
| 
 | |
|         /* Check if user trusts to the consumer */
 | |
|         $trusted = null;
 | |
|         $sites = $this->_storage->getTrustedSites($params['openid_identity']);
 | |
|         if (isset($params['openid_return_to'])) {
 | |
|             $root = $params['openid_return_to'];
 | |
|         }
 | |
|         if (isset($sites[$root])) {
 | |
|             $trusted = $sites[$root];
 | |
|         } else {
 | |
|             foreach ($sites as $site => $t) {
 | |
|                 if (strpos($root, $site) === 0) {
 | |
|                     $trusted = $t;
 | |
|                     break;
 | |
|                 } else {
 | |
|                     /* OpenID 2.0 (9.2) check for realm wild-card matching */
 | |
|                     $n = strpos($site, '://*.');
 | |
|                     if ($n != false) {
 | |
|                         $regex = '/^'
 | |
|                                . preg_quote(substr($site, 0, $n+3), '/')
 | |
|                                . '[A-Za-z1-9_\.]+?'
 | |
|                                . preg_quote(substr($site, $n+4), '/')
 | |
|                                . '/';
 | |
|                         if (preg_match($regex, $root)) {
 | |
|                             $trusted = $t;
 | |
|                             break;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (is_array($trusted)) {
 | |
|             if (!Zend_OpenId_Extension::forAll($extensions, 'checkTrustData', $trusted)) {
 | |
|                 $trusted = null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ($trusted === false) {
 | |
|             $ret['openid.mode'] = 'cancel';
 | |
|             return $ret;
 | |
|         } else if ($trusted === null) {
 | |
|             /* Redirect to Server Trust Screen */
 | |
|             $params2 = array();
 | |
|             foreach ($params as $key => $val) {
 | |
|                 if (strpos($key, 'openid_ns_') === 0) {
 | |
|                     $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
 | |
|                 } else if (strpos($key, 'openid_sreg_') === 0) {
 | |
|                     $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
 | |
|                 } else if (strpos($key, 'openid_') === 0) {
 | |
|                     $key = 'openid.' . substr($key, strlen('openid_'));
 | |
|                 }
 | |
|                 $params2[$key] = $val;
 | |
|             }
 | |
|             if ($immediate) {
 | |
|                 $params2['openid.mode'] = 'checkid_setup';
 | |
|                 $ret['openid.mode'] = ($version >= 2.0) ? 'setup_needed': 'id_res';
 | |
|                 $ret['openid.user_setup_url'] = $this->_trustUrl
 | |
|                     . (strpos($this->_trustUrl, '?') === false ? '?' : '&')
 | |
|                     . Zend_OpenId::paramsToQuery($params2);
 | |
|                 return $ret;
 | |
|             } else {
 | |
|                 Zend_OpenId::redirect($this->_trustUrl, $params2, $response);
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $this->_respond($version, $ret, $params, $extensions);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Perepares information to send back to consumer's authentication request,
 | |
|      * signs it using shared secret and send back through HTTP redirection
 | |
|      *
 | |
|      * @param array $params GET or POST request variables
 | |
|      * @param mixed $extensions extension object or array of extensions objects
 | |
|      * @param Zend_Controller_Response_Abstract $response an optional response
 | |
|      *  object to perform HTTP or HTML form redirection
 | |
|      * @return bool
 | |
|      */
 | |
|     public function respondToConsumer($params, $extensions=null,
 | |
|                            Zend_Controller_Response_Abstract $response = null)
 | |
|     {
 | |
|         $version = 1.1;
 | |
|         if (isset($params['openid_ns']) &&
 | |
|             $params['openid_ns'] == Zend_OpenId::NS_2_0) {
 | |
|             $version = 2.0;
 | |
|         }
 | |
|         $ret = array();
 | |
|         if ($version >= 2.0) {
 | |
|             $ret['openid.ns'] = Zend_OpenId::NS_2_0;
 | |
|         }
 | |
|         $ret = $this->_respond($version, $ret, $params, $extensions);
 | |
|         if (!empty($params['openid_return_to'])) {
 | |
|             Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Perepares information to send back to consumer's authentication request
 | |
|      * and signs it using shared secret.
 | |
|      *
 | |
|      * @param float $version OpenID protcol version
 | |
|      * @param array $ret arguments to be send back to consumer
 | |
|      * @param array $params GET or POST request variables
 | |
|      * @param mixed $extensions extension object or array of extensions objects
 | |
|      * @return array
 | |
|      */
 | |
|     protected function _respond($version, $ret, $params, $extensions=null)
 | |
|     {
 | |
|         if (empty($params['openid_assoc_handle']) ||
 | |
|             !$this->_storage->getAssociation($params['openid_assoc_handle'],
 | |
|                 $macFunc, $secret, $expires)) {
 | |
|             /* Use dumb mode */
 | |
|             if (!empty($params['openid_assoc_handle'])) {
 | |
|                 $ret['openid.invalidate_handle'] = $params['openid_assoc_handle'];
 | |
|             }
 | |
|             $macFunc = $version >= 2.0 ? 'sha256' : 'sha1';
 | |
|             $secret = $this->_genSecret($macFunc);
 | |
|             $handle = uniqid();
 | |
|             $expiresIn = $this->_sessionTtl;
 | |
|             $this->_storage->addAssociation($handle,
 | |
|                 $macFunc, $secret, time() + $expiresIn);
 | |
|             $ret['openid.assoc_handle'] = $handle;
 | |
|         } else {
 | |
|             $ret['openid.assoc_handle'] = $params['openid_assoc_handle'];
 | |
|         }
 | |
|         if (isset($params['openid_return_to'])) {
 | |
|             $ret['openid.return_to'] = $params['openid_return_to'];
 | |
|         }
 | |
|         if (isset($params['openid_claimed_id'])) {
 | |
|             $ret['openid.claimed_id'] = $params['openid_claimed_id'];
 | |
|         }
 | |
|         if (isset($params['openid_identity'])) {
 | |
|             $ret['openid.identity'] = $params['openid_identity'];
 | |
|         }
 | |
| 
 | |
|         if ($version >= 2.0) {
 | |
|             if (!empty($this->_opEndpoint)) {
 | |
|                 $ret['openid.op_endpoint'] = $this->_opEndpoint;
 | |
|             } else {
 | |
|                 $ret['openid.op_endpoint'] = Zend_OpenId::selfUrl();
 | |
|             }
 | |
|         }
 | |
|         $ret['openid.response_nonce'] = gmdate('Y-m-d\TH:i:s\Z') . uniqid();
 | |
|         $ret['openid.mode'] = 'id_res';
 | |
| 
 | |
|         Zend_OpenId_Extension::forAll($extensions, 'prepareResponse', $ret);
 | |
| 
 | |
|         $signed = '';
 | |
|         $data = '';
 | |
|         foreach ($ret as $key => $val) {
 | |
|             if (strpos($key, 'openid.') === 0) {
 | |
|                 $key = substr($key, strlen('openid.'));
 | |
|                 if (!empty($signed)) {
 | |
|                     $signed .= ',';
 | |
|                 }
 | |
|                 $signed .= $key;
 | |
|                 $data .= $key . ':' . $val . "\n";
 | |
|             }
 | |
|         }
 | |
|         $signed .= ',signed';
 | |
|         $data .= 'signed:' . $signed . "\n";
 | |
|         $ret['openid.signed'] = $signed;
 | |
| 
 | |
|         $ret['openid.sig'] = base64_encode(
 | |
|             Zend_OpenId::hashHmac($macFunc, $data, $secret));
 | |
| 
 | |
|         return $ret;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs authentication validation for dumb consumers
 | |
|      * Returns array of variables to push back to consumer.
 | |
|      * It MUST contain 'is_valid' variable with value 'true' or 'false'.
 | |
|      *
 | |
|      * @param float $version OpenID version
 | |
|      * @param array $params GET or POST request variables
 | |
|      * @return array
 | |
|      */
 | |
|     protected function _checkAuthentication($version, $params)
 | |
|     {
 | |
|         $ret = array();
 | |
|         if ($version >= 2.0) {
 | |
|             $ret['ns'] = Zend_OpenId::NS_2_0;
 | |
|         }
 | |
|         $ret['openid.mode'] = 'id_res';
 | |
| 
 | |
|         if (empty($params['openid_assoc_handle']) ||
 | |
|             empty($params['openid_signed']) ||
 | |
|             empty($params['openid_sig']) ||
 | |
|             !$this->_storage->getAssociation($params['openid_assoc_handle'],
 | |
|                 $macFunc, $secret, $expires)) {
 | |
|             $ret['is_valid'] = 'false';
 | |
|             return $ret;
 | |
|         }
 | |
| 
 | |
|         $signed = explode(',', $params['openid_signed']);
 | |
|         $data = '';
 | |
|         foreach ($signed as $key) {
 | |
|             $data .= $key . ':';
 | |
|             if ($key == 'mode') {
 | |
|                 $data .= "id_res\n";
 | |
|             } else {
 | |
|                 $data .= $params['openid_' . strtr($key,'.','_')]."\n";
 | |
|             }
 | |
|         }
 | |
|         if ($this->_secureStringCompare(base64_decode($params['openid_sig']),
 | |
|             Zend_OpenId::hashHmac($macFunc, $data, $secret))) {
 | |
|             $ret['is_valid'] = 'true';
 | |
|         } else {
 | |
|             $ret['is_valid'] = 'false';
 | |
|         }
 | |
|         return $ret;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Securely compare two strings for equality while avoided C level memcmp()
 | |
|      * optimisations capable of leaking timing information useful to an attacker
 | |
|      * attempting to iteratively guess the unknown string (e.g. password) being
 | |
|      * compared against.
 | |
|      *
 | |
|      * @param string $a
 | |
|      * @param string $b
 | |
|      * @return bool
 | |
|      */
 | |
|     protected function _secureStringCompare($a, $b)
 | |
|     {
 | |
|         if (strlen($a) !== strlen($b)) {
 | |
|             return false;
 | |
|         }
 | |
|         $result = 0;
 | |
|         for ($i = 0; $i < strlen($a); $i++) {
 | |
|             $result |= ord($a[$i]) ^ ord($b[$i]);
 | |
|         }
 | |
|         return $result == 0;
 | |
|     }
 | |
| }
 |