diff options
Diffstat (limited to 'applications/core/lib/Zend/OpenId')
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Consumer.php | 958 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Consumer/Storage.php | 132 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Consumer/Storage/File.php | 460 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Exception.php | 58 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Extension.php | 137 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Extension/Sreg.php | 300 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Provider.php | 781 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Provider/Storage.php | 106 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Provider/Storage/File.php | 397 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Provider/User.php | 57 | ||||
| -rw-r--r-- | applications/core/lib/Zend/OpenId/Provider/User/Session.php | 104 | 
11 files changed, 3490 insertions, 0 deletions
| diff --git a/applications/core/lib/Zend/OpenId/Consumer.php b/applications/core/lib/Zend/OpenId/Consumer.php new file mode 100644 index 0000000..7b4d6dc --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Consumer.php @@ -0,0 +1,958 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Consumer.php 14674 2009-04-05 13:58:39Z [email protected] $ + */ + +/** + * @see Zend_OpenId + */ +require_once "Zend/OpenId.php"; + +/** + * @see Zend_OpenId_Extension + */ +require_once "Zend/OpenId/Extension.php"; + +/** + * @see Zend_OpenId_Consumer_Storage + */ +require_once "Zend/OpenId/Consumer/Storage.php"; + +/** + * @see Zend_Http_Client + */ +require_once 'Zend/Http/Client.php'; + +/** + * OpenID consumer implementation + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Consumer +{ + +    /** +     * Reference to an implementation of storage object +     * +     * @var Zend_OpenId_Consumer_Storage $_storage +     */ +    protected $_storage = null; + +    /** +     * Enables or disables consumer to use association with server based on +     * Diffie-Hellman key agreement +     * +     * @var Zend_OpenId_Consumer_Storage $_dumbMode +     */ +    protected $_dumbMode = false; + +    /** +     * Internal cache to prevent unnecessary access to storage +     * +     * @var array $_cache +     */ +    protected $_cache = array(); + +    /** +     * HTTP client to make HTTP requests +     * +     * @var Zend_Http_Client $_httpClient +     */ +    private $_httpClient = null; + +    /** +     * HTTP session to store climed_id between requests +     * +     * @var Zend_Session_Namespace $_session +     */ +    private $_session = null; + +    /** +     * Last error message for logi, check or verify failure +     * +     * @var string $_error +     */ +    private $_error = ''; + +    /** +     * Constructs a Zend_OpenId_Consumer object with given $storage. +     * Enables or disables future association with server based on +     * Diffie-Hellman key agreement. +     * +     * @param Zend_OpenId_Consumer_Storage $storage implementation of custom +     *  storage object +     * @param bool $dumbMode Enables or disables consumer to use association +     *  with server based on Diffie-Hellman key agreement +     */ +    public function __construct(Zend_OpenId_Consumer_Storage $storage = null, +                                $dumbMode = false) +    { +        if ($storage === null) { +            require_once "Zend/OpenId/Consumer/Storage/File.php"; +            $this->_storage = new Zend_OpenId_Consumer_Storage_File(); +        } else { +            $this->_storage = $storage; +        } +        $this->_dumbMode = $dumbMode; +    } + +    /** +     * Performs check (with possible user interaction) of OpenID identity. +     * +     * This is the first step of OpenID authentication process. +     * On success the function does not return (it does HTTP redirection to +     * server and exits). On failure it returns false. +     * +     * @param string $id OpenID identity +     * @param string $returnTo URL to redirect response from server to +     * @param string $root HTTP URL to identify consumer on server +     * @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 login($id, $returnTo = null, $root = null, $extensions = null, +                          Zend_Controller_Response_Abstract $response = null) +    { +        return $this->_checkId( +            false, +            $id, +            $returnTo, +            $root, +            $extensions, +            $response); +    } + +    /** +     * Performs immediate check (without user interaction) of OpenID identity. +     * +     * This is the first step of OpenID authentication process. +     * On success the function does not return (it does HTTP redirection to +     * server and exits). On failure it returns false. +     * +     * @param string $id OpenID identity +     * @param string $returnTo HTTP URL to redirect response from server to +     * @param string $root HTTP URL to identify consumer on server +     * @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 check($id, $returnTo=null, $root=null, $extensions = null, +                          Zend_Controller_Response_Abstract $response = null) + +    { +        return $this->_checkId( +            true, +            $id, +            $returnTo, +            $root, +            $extensions, +            $response); +    } + +    /** +     * Verifies authentication response from OpenID server. +     * +     * This is the second step of OpenID authentication process. +     * The function returns true on successful authentication and false on +     * failure. +     * +     * @param array $params HTTP query data from OpenID server +     * @param string &$identity this argument is set to end-user's claimed +     *  identifier or OpenID provider local identifier. +     * @param mixed $extensions extension object or array of extensions objects +     * @return bool +     */ +    public function verify($params, &$identity = "", $extensions = null) +    { +        $this->_setError(''); + +        $version = 1.1; +        if (isset($params['openid_ns']) && +            $params['openid_ns'] == Zend_OpenId::NS_2_0) { +            $version = 2.0; +        } + +        if (isset($params["openid_claimed_id"])) { +            $identity = $params["openid_claimed_id"]; +        } else if (isset($params["openid_identity"])){ +            $identity = $params["openid_identity"]; +        } else { +            $identity = ""; +        } + +        if ($version < 2.0 && !isset($params["openid_claimed_id"])) { +            if ($this->_session !== null) { +                if ($this->_session->identity === $identity) { +                    $identity = $this->_session->claimed_id; +                } +            } else if (defined('SID')) { +                if (isset($_SESSION["zend_openid"]["identity"]) && +                    isset($_SESSION["zend_openid"]["claimed_id"]) && +                    $_SESSION["zend_openid"]["identity"] === $identity) { +                    $identity = $_SESSION["zend_openid"]["claimed_id"]; +                } +            } else { +                require_once "Zend/Session/Namespace.php"; +                $this->_session = new Zend_Session_Namespace("zend_openid"); +                if ($this->_session->identity === $identity) { +                    $identity = $this->_session->claimed_id; +                } +            } +        } + +        if (empty($params['openid_mode'])) { +            $this->_setError("Missing openid.mode"); +            return false; +        } +        if (empty($params['openid_return_to'])) { +            $this->_setError("Missing openid.return_to"); +            return false; +        } +        if (empty($params['openid_signed'])) { +            $this->_setError("Missing openid.signed"); +            return false; +        } +        if (empty($params['openid_sig'])) { +            $this->_setError("Missing openid.sig"); +            return false; +        } +        if ($params['openid_mode'] != 'id_res') { +            $this->_setError("Wrong openid.mode '".$params['openid_mode']."' != 'id_res'"); +            return false; +        } +        if (empty($params['openid_assoc_handle'])) { +            $this->_setError("Missing openid.assoc_handle"); +            return false; +        } +        if ($params['openid_return_to'] != Zend_OpenId::selfUrl()) { +            /* Ignore query part in openid.return_to */ +            $pos = strpos($params['openid_return_to'], '?'); +            if ($pos === false || +                SUBSTR($params['openid_return_to'], 0 , $pos) != Zend_OpenId::selfUrl()) { + +                $this->_setError("Wrong openid.return_to '". +                    $params['openid_return_to']."' != '" . Zend_OpenId::selfUrl() ."'"); +                return false; +            } +        } + +        if ($version >= 2.0) { +            if (empty($params['openid_response_nonce'])) { +                $this->_setError("Missing openid.response_nonce"); +                return false; +            } +            if (empty($params['openid_op_endpoint'])) { +                $this->_setError("Missing openid.op_endpoint"); +                return false; +            /* OpenID 2.0 (11.3) Checking the Nonce */ +            } else if (!$this->_storage->isUniqueNonce($params['openid_op_endpoint'], $params['openid_response_nonce'])) { +                $this->_setError("Duplicate openid.response_nonce"); +                return false; +            } +        } + + +        if (!empty($params['openid_invalidate_handle'])) { +            if ($this->_storage->getAssociationByHandle( +                $params['openid_invalidate_handle'], +                $url, +                $macFunc, +                $secret, +                $expires)) { +                $this->_storage->delAssociation($url); +            } +        } + +        if ($this->_storage->getAssociationByHandle( +                $params['openid_assoc_handle'], +                $url, +                $macFunc, +                $secret, +                $expires)) { +            $signed = explode(',', $params['openid_signed']); +            $data = ''; +            foreach ($signed as $key) { +                $data .= $key . ':' . $params['openid_' . strtr($key,'.','_')] . "\n"; +            } +            if (base64_decode($params['openid_sig']) == +                Zend_OpenId::hashHmac($macFunc, $data, $secret)) { +                if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) { +                    $this->_setError("Extension::parseResponse failure"); +                    return false; +                } +                /* OpenID 2.0 (11.2) Verifying Discovered Information */ +                if (isset($params['openid_claimed_id'])) { +                    $id = $params['openid_claimed_id']; +                    if (!Zend_OpenId::normalize($id)) { +                        $this->_setError("Normalization failed"); +                        return false; +                    } else if (!$this->_discovery($id, $discovered_server, $discovered_version)) { +                        $this->_setError("Discovery failed: " . $this->getError()); +                        return false; +                    } else if ((!empty($params['openid_identity']) && +                                $params["openid_identity"] != $id) || +                               (!empty($params['openid_op_endpoint']) && +                                $params['openid_op_endpoint'] != $discovered_server) || +                               $discovered_version != $version) { +                        $this->_setError("Discovery information verification failed"); +                        return false; +                    } +                } +                return true; +            } +            $this->_storage->delAssociation($url); +            $this->_setError("Signature check failed"); +            return false; +        } +        else +        { +            /* Use dumb mode */ +            if (isset($params['openid_claimed_id'])) { +                $id = $params['openid_claimed_id']; +            } else if (isset($params['openid_identity'])) { +                $id = $params['openid_identity']; +            } else { +                $this->_setError("Missing openid.claimed_id and openid.identity"); +                return false; +            } + +            if (!Zend_OpenId::normalize($id)) { +                $this->_setError("Normalization failed"); +                return false; +            } else if (!$this->_discovery($id, $server, $discovered_version)) { +                $this->_setError("Discovery failed: " . $this->getError()); +                return false; +            } + +            /* OpenID 2.0 (11.2) Verifying Discovered Information */ +            if ((isset($params['openid_identity']) && +                 $params["openid_identity"] != $id) || +                (isset($params['openid_op_endpoint']) && +                 $params['openid_op_endpoint'] != $server) || +                $discovered_version != $version) { +                $this->_setError("Discovery information verification failed"); +                return false; +            } + +            $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; +            } +            $params2['openid.mode'] = 'check_authentication'; +            $ret = $this->_httpRequest($server, 'POST', $params2, $status); +            if ($status != 200) { +                $this->_setError("'Dumb' signature verification HTTP request failed"); +                return false; +            } +            $r = array(); +            if (is_string($ret)) { +                foreach(explode("\n", $ret) as $line) { +                    $line = trim($line); +                    if (!empty($line)) { +                        $x = explode(':', $line, 2); +                        if (is_array($x) && count($x) == 2) { +                            list($key, $value) = $x; +                            $r[trim($key)] = trim($value); +                        } +                    } +                } +            } +            $ret = $r; +            if (!empty($ret['invalidate_handle'])) { +                if ($this->_storage->getAssociationByHandle( +                    $ret['invalidate_handle'], +                    $url, +                    $macFunc, +                    $secret, +                    $expires)) { +                    $this->_storage->delAssociation($url); +                } +            } +            if (isset($ret['is_valid']) && $ret['is_valid'] == 'true') { +                if (!Zend_OpenId_Extension::forAll($extensions, 'parseResponse', $params)) { +                    $this->_setError("Extension::parseResponse failure"); +                    return false; +                } +                return true; +            } +            $this->_setError("'Dumb' signature verification failed"); +            return false; +        } +    } + +    /** +     * Store assiciation in internal chace and external storage +     * +     * @param string $url OpenID server url +     * @param string $handle association handle +     * @param string $macFunc HMAC function (sha1 or sha256) +     * @param string $secret shared secret +     * @param integer $expires expiration UNIX time +     * @return void +     */ +    protected function _addAssociation($url, $handle, $macFunc, $secret, $expires) +    { +        $this->_cache[$url] = array($handle, $macFunc, $secret, $expires); +        return $this->_storage->addAssociation( +            $url, +            $handle, +            $macFunc, +            $secret, +            $expires); +    } + +    /** +     * Retrive assiciation information for given $url from internal cahce or +     * external storage +     * +     * @param string $url OpenID server url +     * @param string &$handle association handle +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param integer &$expires expiration UNIX time +     * @return void +     */ +    protected function _getAssociation($url, &$handle, &$macFunc, &$secret, &$expires) +    { +        if (isset($this->_cache[$url])) { +            $handle   = $this->_cache[$url][0]; +            $macFunc = $this->_cache[$url][1]; +            $secret   = $this->_cache[$url][2]; +            $expires  = $this->_cache[$url][3]; +            return true; +        } +        if ($this->_storage->getAssociation( +                $url, +                $handle, +                $macFunc, +                $secret, +                $expires)) { +            $this->_cache[$url] = array($handle, $macFunc, $secret, $expires); +            return true; +        } +        return false; +    } + +    /** +     * Performs HTTP request to given $url using given HTTP $method. +     * Send additinal query specified by variable/value array, +     * On success returns HTTP response without headers, false on failure. +     * +     * @param string $url OpenID server url +     * @param string $method HTTP request method 'GET' or 'POST' +     * @param array $params additional qwery parameters to be passed with +     * @param int &$staus HTTP status code +     *  request +     * @return mixed +     */ +    protected function _httpRequest($url, $method = 'GET', array $params = array(), &$status = null) +    { +        $client = $this->_httpClient; +        if ($client === null) { +            $client = new Zend_Http_Client( +                    $url, +                    array( +                        'maxredirects' => 4, +                        'timeout'      => 15, +                        'useragent'    => 'Zend_OpenId' +                    ) +                ); +        } else { +            $client->setUri($url); +        } + +        $client->resetParameters(); +        if ($method == 'POST') { +            $client->setMethod(Zend_Http_Client::POST); +            $client->setParameterPost($params); +        } else { +            $client->setMethod(Zend_Http_Client::GET); +            $client->setParameterGet($params); +        } + +        try { +            $response = $client->request(); +        } catch (Exception $e) { +            $this->_setError('HTTP Request failed: ' . $e->getMessage()); +            return false; +        } +        $status = $response->getStatus(); +        $body = $response->getBody(); +        if ($status == 200 || ($status == 400 && !empty($body))) { +            return $body; +        }else{ +            $this->_setError('Bad HTTP response'); +            return false; +        } +    } + +    /** +     * Create (or reuse existing) association between OpenID consumer and +     * OpenID server based on Diffie-Hellman key agreement. Returns true +     * on success and false on failure. +     * +     * @param string $url OpenID server url +     * @param float $version OpenID protocol version +     * @param string $priv_key for testing only +     * @return bool +     */ +    protected function _associate($url, $version, $priv_key=null) +    { + +        /* Check if we already have association in chace or storage */ +        if ($this->_getAssociation( +                $url, +                $handle, +                $macFunc, +                $secret, +                $expires)) { +            return true; +        } + +        if ($this->_dumbMode) { +            /* Use dumb mode */ +            return true; +        } + +        $params = array(); + +        if ($version >= 2.0) { +            $params = array( +                'openid.ns'           => Zend_OpenId::NS_2_0, +                'openid.mode'         => 'associate', +                'openid.assoc_type'   => 'HMAC-SHA256', +                'openid.session_type' => 'DH-SHA256', +            ); +        } else { +            $params = array( +                'openid.mode'         => 'associate', +                'openid.assoc_type'   => 'HMAC-SHA1', +                'openid.session_type' => 'DH-SHA1', +            ); +        } + +        $dh = Zend_OpenId::createDhKey(pack('H*', Zend_OpenId::DH_P), +                                       pack('H*', Zend_OpenId::DH_G), +                                       $priv_key); +        $dh_details = Zend_OpenId::getDhKeyDetails($dh); + +        $params['openid.dh_modulus']         = base64_encode( +            Zend_OpenId::btwoc($dh_details['p'])); +        $params['openid.dh_gen']             = base64_encode( +            Zend_OpenId::btwoc($dh_details['g'])); +        $params['openid.dh_consumer_public'] = base64_encode( +            Zend_OpenId::btwoc($dh_details['pub_key'])); + +        while(1) { +            $ret = $this->_httpRequest($url, 'POST', $params, $status); +            if ($ret === false) { +                $this->_setError("HTTP request failed"); +                return false; +            } + +            $r = array(); +            $bad_response = false; +            foreach(explode("\n", $ret) as $line) { +                $line = trim($line); +                if (!empty($line)) { +                    $x = explode(':', $line, 2); +                    if (is_array($x) && count($x) == 2) { +                        list($key, $value) = $x; +                        $r[trim($key)] = trim($value); +                    } else { +                        $bad_response = true; +                    } +                } +            } +            if ($bad_response && strpos($ret, 'Unknown session type') !== false) { +                $r['error_code'] = 'unsupported-type'; +            } +            $ret = $r; + +            if (isset($ret['error_code']) && +                $ret['error_code'] == 'unsupported-type') { +                if ($params['openid.session_type'] == 'DH-SHA256') { +                    $params['openid.session_type'] = 'DH-SHA1'; +                    $params['openid.assoc_type'] = 'HMAC-SHA1'; +                } else if ($params['openid.session_type'] == 'DH-SHA1') { +                    $params['openid.session_type'] = 'no-encryption'; +                } else { +                    $this->_setError("The OpenID service responded with: " . $ret['error_code']); +                    return false; +                } +            } else { +                break; +            } +        } + +        if ($status != 200) { +            $this->_setError("The server responded with status code: " . $status); +            return false; +        } + +        if ($version >= 2.0 && +            isset($ret['ns']) && +            $ret['ns'] != Zend_OpenId::NS_2_0) { +            $this->_setError("Wrong namespace definition in the server response"); +            return false; +        } + +        if (!isset($ret['assoc_handle']) || +            !isset($ret['expires_in']) || +            !isset($ret['assoc_type']) || +            $params['openid.assoc_type'] != $ret['assoc_type']) { +            if ($params['openid.assoc_type'] != $ret['assoc_type']) { +                $this->_setError("The returned assoc_type differed from the supplied openid.assoc_type"); +            } else { +                $this->_setError("Missing required data from provider (assoc_handle, expires_in, assoc_type are required)"); +            } +            return false; +        } + +        $handle     = $ret['assoc_handle']; +        $expiresIn = $ret['expires_in']; + +        if ($ret['assoc_type'] == 'HMAC-SHA1') { +            $macFunc = 'sha1'; +        } else if ($ret['assoc_type'] == 'HMAC-SHA256' && +            $version >= 2.0) { +            $macFunc = 'sha256'; +        } else { +            $this->_setError("Unsupported assoc_type"); +            return false; +        } + +        if ((empty($ret['session_type']) || +             ($version >= 2.0 && $ret['session_type'] == 'no-encryption')) && +             isset($ret['mac_key'])) { +            $secret = base64_decode($ret['mac_key']); +        } else if (isset($ret['session_type']) && +            $ret['session_type'] == 'DH-SHA1' && +            !empty($ret['dh_server_public']) && +            !empty($ret['enc_mac_key'])) { +            $dhFunc = 'sha1'; +        } else if (isset($ret['session_type']) && +            $ret['session_type'] == 'DH-SHA256' && +            $version >= 2.0 && +            !empty($ret['dh_server_public']) && +            !empty($ret['enc_mac_key'])) { +            $dhFunc = 'sha256'; +        } else { +            $this->_setError("Unsupported session_type"); +            return false; +        } +        if (isset($dhFunc)) { +            $serverPub = base64_decode($ret['dh_server_public']); +            $dhSec = Zend_OpenId::computeDhSecret($serverPub, $dh); +            if ($dhSec === false) { +                $this->_setError("DH secret comutation failed"); +                return false; +            } +            $sec = Zend_OpenId::digest($dhFunc, $dhSec); +            if ($sec === false) { +                $this->_setError("Could not create digest"); +                return false; +            } +            $secret = $sec ^ base64_decode($ret['enc_mac_key']); +        } +        if ($macFunc == 'sha1') { +            if (Zend_OpenId::strlen($secret) != 20) { +                $this->_setError("The length of the sha1 secret must be 20"); +                return false; +            } +        } else if ($macFunc == 'sha256') { +            if (Zend_OpenId::strlen($secret) != 32) { +                $this->_setError("The length of the sha256 secret must be 32"); +                return false; +            } +        } +        $this->_addAssociation( +            $url, +            $handle, +            $macFunc, +            $secret, +            time() + $expiresIn); +        return true; +    } + +    /** +     * Performs discovery of identity and finds OpenID URL, OpenID server URL +     * and OpenID protocol version. Returns true on succees and false on +     * failure. +     * +     * @param string &$id OpenID identity URL +     * @param string &$server OpenID server URL +     * @param float &$version OpenID protocol version +     * @return bool +     * @todo OpenID 2.0 (7.3) XRI and Yadis discovery +     */ +    protected function _discovery(&$id, &$server, &$version) +    { +        $realId = $id; +        if ($this->_storage->getDiscoveryInfo( +                $id, +                $realId, +                $server, +                $version, +                $expire)) { +            $id = $realId; +            return true; +        } + +        /* TODO: OpenID 2.0 (7.3) XRI and Yadis discovery */ + +        /* HTML-based discovery */ +        $response = $this->_httpRequest($id, 'GET', array(), $status); +        if ($status != 200 || !is_string($response)) { +            return false; +        } +        if (preg_match( +                '/<link[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid2.provider[ \t]*[^"\']*\\1[^>]*href=(["\'])([^"\']+)\\2[^>]*\/?>/i', +                $response, +                $r)) { +            $version = 2.0; +            $server = $r[3]; +        } else if (preg_match( +                '/<link[^>]*href=(["\'])([^"\']+)\\1[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid2.provider[ \t]*[^"\']*\\3[^>]*\/?>/i', +                $response, +                $r)) { +            $version = 2.0; +            $server = $r[2]; +        } else if (preg_match( +                '/<link[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid.server[ \t]*[^"\']*\\1[^>]*href=(["\'])([^"\']+)\\2[^>]*\/?>/i', +                $response, +                $r)) { +            $version = 1.1; +            $server = $r[3]; +        } else if (preg_match( +                '/<link[^>]*href=(["\'])([^"\']+)\\1[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid.server[ \t]*[^"\']*\\3[^>]*\/?>/i', +                $response, +                $r)) { +            $version = 1.1; +            $server = $r[2]; +        } else { +            return false; +        } +        if ($version >= 2.0) { +            if (preg_match( +                    '/<link[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid2.local_id[ \t]*[^"\']*\\1[^>]*href=(["\'])([^"\']+)\\2[^>]*\/?>/i', +                    $response, +                    $r)) { +                $realId = $r[3]; +            } else if (preg_match( +                    '/<link[^>]*href=(["\'])([^"\']+)\\1[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid2.local_id[ \t]*[^"\']*\\3[^>]*\/?>/i', +                    $response, +                    $r)) { +                $realId = $r[2]; +            } +        } else { +            if (preg_match( +                    '/<link[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid.delegate[ \t]*[^"\']*\\1[^>]*href=(["\'])([^"\']+)\\2[^>]*\/?>/i', +                    $response, +                    $r)) { +                $realId = $r[3]; +            } else if (preg_match( +                    '/<link[^>]*href=(["\'])([^"\']+)\\1[^>]*rel=(["\'])[ \t]*(?:[^ \t"\']+[ \t]+)*?openid.delegate[ \t]*[^"\']*\\3[^>]*\/?>/i', +                    $response, +                    $r)) { +                $realId = $r[2]; +            } +        } + +        $expire = time() + 60 * 60; +        $this->_storage->addDiscoveryInfo($id, $realId, $server, $version, $expire); +        $id = $realId; +        return true; +    } + +    /** +     * Performs check of OpenID identity. +     * +     * This is the first step of OpenID authentication process. +     * On success the function does not return (it does HTTP redirection to +     * server and exits). On failure it returns false. +     * +     * @param bool $immediate enables or disables interaction with user +     * @param string $id OpenID identity +     * @param string $returnTo HTTP URL to redirect response from server to +     * @param string $root HTTP URL to identify consumer on server +     * @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 +     */ +    protected function _checkId($immediate, $id, $returnTo=null, $root=null, +        $extensions=null, Zend_Controller_Response_Abstract $response = null) +    { +        $this->_setError(''); + +        if (!Zend_OpenId::normalize($id)) { +            $this->_setError("Normalisation failed"); +            return false; +        } +        $claimedId = $id; + +        if (!$this->_discovery($id, $server, $version)) { +            $this->_setError("Discovery failed: " . $this->getError()); +            return false; +        } +        if (!$this->_associate($server, $version)) { +            $this->_setError("Association failed: " . $this->getError()); +            return false; +        } +        if (!$this->_getAssociation( +                $server, +                $handle, +                $macFunc, +                $secret, +                $expires)) { +            /* Use dumb mode */ +            unset($handle); +            unset($macFunc); +            unset($secret); +            unset($expires); +        } + +        $params = array(); +        if ($version >= 2.0) { +            $params['openid.ns'] = Zend_OpenId::NS_2_0; +        } + +        $params['openid.mode'] = $immediate ? +            'checkid_immediate' : 'checkid_setup'; + +        $params['openid.identity'] = $id; + +        $params['openid.claimed_id'] = $claimedId; + +        if ($version <= 2.0) { +            if ($this->_session !== null) { +                $this->_session->identity = $id; +                $this->_session->claimed_id = $claimedId; +            } else if (defined('SID')) { +                $_SESSION["zend_openid"] = array( +                    "identity" => $id, +                    "claimed_id" => $claimedId); +            } else { +                require_once "Zend/Session/Namespace.php"; +                $this->_session = new Zend_Session_Namespace("zend_openid"); +                $this->_session->identity = $id; +                $this->_session->claimed_id = $claimedId; +            } +        } + +        if (isset($handle)) { +            $params['openid.assoc_handle'] = $handle; +        } + +        $params['openid.return_to'] = Zend_OpenId::absoluteUrl($returnTo); + +        if (empty($root)) { +            $root = Zend_OpenId::selfUrl(); +            if ($root[strlen($root)-1] != '/') { +                $root = dirname($root); +            } +        } +        if ($version >= 2.0) { +            $params['openid.realm'] = $root; +        } else { +            $params['openid.trust_root'] = $root; +        } + +        if (!Zend_OpenId_Extension::forAll($extensions, 'prepareRequest', $params)) { +            $this->_setError("Extension::prepareRequest failure"); +            return false; +        } + +        Zend_OpenId::redirect($server, $params, $response); +        return true; +    } + +    /** +     * Sets HTTP client object to make HTTP requests +     * +     * @param Zend_Http_Client $client HTTP client object to be used +     */ +    public function setHttpClient($client) { +        $this->_httpClient = $client; +    } + +    /** +     * Returns HTTP client object that will be used to make HTTP requests +     * +     * @return Zend_Http_Client +     */ +    public function getHttpClient() { +        return $this->_httpClient; +    } + +    /** +     * Sets session object to store climed_id +     * +     * @param Zend_Session_Namespace $session HTTP client object to be used +     */ +    public function setSession(Zend_Session_Namespace $session) { +        $this->_session = $session; +    } + +    /** +     * Returns session object that is used to store climed_id +     * +     * @return Zend_Session_Namespace +     */ +    public function getSession() { +        return $this->_session; +    } + +    /** +     * Saves error message +     * +     * @param string $message error message +     */ +    protected function _setError($message) +    { +        $this->_error = $message; +    } + +    /** +     * Returns error message that explains failure of login, check or verify +     * +     * @return string +     */ +    public function getError() +    { +        return $this->_error; +    } + +} diff --git a/applications/core/lib/Zend/OpenId/Consumer/Storage.php b/applications/core/lib/Zend/OpenId/Consumer/Storage.php new file mode 100644 index 0000000..68e4ed0 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Consumer/Storage.php @@ -0,0 +1,132 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Storage.php 9239 2008-04-18 12:09:31Z dmitry $ + */ + +/** + * Abstract class to implement external storage for OpenID consumer + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +abstract class Zend_OpenId_Consumer_Storage +{ + +    /** +     * Stores information about association identified by $url/$handle +     * +     * @param string $url OpenID server URL +     * @param string $handle assiciation handle +     * @param string $macFunc HMAC function (sha1 or sha256) +     * @param string $secret shared secret +     * @param long $expires expiration UNIX time +     * @return void +     */ +    abstract public function addAssociation($url, $handle, $macFunc, $secret, $expires); + +    /** +     * Gets information about association identified by $url +     * Returns true if given association found and not expired and false +     * otherwise +     * +     * @param string $url OpenID server URL +     * @param string &$handle assiciation handle +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    abstract public function getAssociation($url, &$handle, &$macFunc, &$secret, &$expires); + +    /** +     * Gets information about association identified by $handle +     * Returns true if given association found and not expired and false +     * othverwise +     * +     * @param string $handle assiciation handle +     * @param string &$url OpenID server URL +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    abstract public function getAssociationByHandle($handle, &$url, &$macFunc, &$secret, &$expires); + +    /** +     * Deletes association identified by $url +     * +     * @param string $url OpenID server URL +     * @return void +     */ +    abstract public function delAssociation($url); + +    /** +     * Stores information discovered from identity $id +     * +     * @param string $id identity +     * @param string $realId discovered real identity URL +     * @param string $server discovered OpenID server URL +     * @param float $version discovered OpenID protocol version +     * @param long $expires expiration UNIX time +     * @return void +     */ +    abstract public function addDiscoveryInfo($id, $realId, $server, $version, $expires); + +    /** +     * Gets information discovered from identity $id +     * Returns true if such information exists and false otherwise +     * +     * @param string $id identity +     * @param string &$realId discovered real identity URL +     * @param string &$server discovered OpenID server URL +     * @param float &$version discovered OpenID protocol version +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    abstract public function getDiscoveryInfo($id, &$realId, &$server, &$version, &$expires); + +    /** +     * Removes cached information discovered from identity $id +     * +     * @param string $id identity +     * @return bool +     */ +    abstract public function delDiscoveryInfo($id); + +    /** +     * The function checks the uniqueness of openid.response_nonce +     * +     * @param string $provider openid.openid_op_endpoint field from authentication response +     * @param string $nonce openid.response_nonce field from authentication response +     * @return bool +     */ +    abstract public function isUniqueNonce($provider, $nonce); + +    /** +     * Removes data from the uniqueness database that is older then given date +     * +     * @param string $date Date of expired data +     */ +    abstract public function purgeNonces($date=null); +} diff --git a/applications/core/lib/Zend/OpenId/Consumer/Storage/File.php b/applications/core/lib/Zend/OpenId/Consumer/Storage/File.php new file mode 100644 index 0000000..c75dea9 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Consumer/Storage/File.php @@ -0,0 +1,460 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: File.php 13522 2009-01-06 16:35:55Z thomas $ + */ + +/** + * @see Zend_OpenId_Consumer_Storage + */ +require_once "Zend/OpenId/Consumer/Storage.php"; + +/** + * External storage implemmentation using serialized files + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Consumer + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Consumer_Storage_File extends Zend_OpenId_Consumer_Storage +{ + +    /** +     * Directory name to store data files in +     * +     * @var string $_dir +     */ +    private $_dir; + +    /** +     * Constructs storage object and creates storage directory +     * +     * @param string $dir directory name to store data files in +     * @throws Zend_OpenId_Exception +     */ +    public function __construct($dir = null) +    { +        if ($dir === null) { +            $tmp = getenv('TMP'); +            if (empty($tmp)) { +                $tmp = getenv('TEMP'); +                if (empty($tmp)) { +                    $tmp = "/tmp"; +                } +            } +            $user = get_current_user(); +            if (is_string($user) && !empty($user)) { +                $tmp .= '/' . $user; +            } +            $dir = $tmp . '/openid/consumer'; +        } +        $this->_dir = $dir; +        if (!is_dir($this->_dir)) { +            if (!@mkdir($this->_dir, 0700, 1)) { +                /** +                 * @see Zend_OpenId_Exception +                 */ +                require_once 'Zend/OpenId/Exception.php'; +                throw new Zend_OpenId_Exception( +                    'Cannot access storage directory ' . $dir, +                    Zend_OpenId_Exception::ERROR_STORAGE); +            } +        } +        if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) { +            /** +             * @see Zend_OpenId_Exception +             */ +            require_once 'Zend/OpenId/Exception.php'; +            throw new Zend_OpenId_Exception( +                'Cannot create a lock file in the directory ' . $dir, +                Zend_OpenId_Exception::ERROR_STORAGE); +        } +        fclose($f); +        if (($f = fopen($this->_dir.'/discovery.lock', 'w+')) === null) { +            /** +             * @see Zend_OpenId_Exception +             */ +            require_once 'Zend/OpenId/Exception.php'; +            throw new Zend_OpenId_Exception( +                'Cannot create a lock file in the directory ' . $dir, +                Zend_OpenId_Exception::ERROR_STORAGE); +        } +        fclose($f); +        if (($f = fopen($this->_dir.'/nonce.lock', 'w+')) === null) { +            /** +             * @see Zend_OpenId_Exception +             */ +            require_once 'Zend/OpenId/Exception.php'; +            throw new Zend_OpenId_Exception( +                'Cannot create a lock file in the directory ' . $dir, +                Zend_OpenId_Exception::ERROR_STORAGE); +        } +        fclose($f); +    } + +    /** +     * Stores information about association identified by $url/$handle +     * +     * @param string $url OpenID server URL +     * @param string $handle assiciation handle +     * @param string $macFunc HMAC function (sha1 or sha256) +     * @param string $secret shared secret +     * @param long $expires expiration UNIX time +     * @return bool +     */ +    public function addAssociation($url, $handle, $macFunc, $secret, $expires) +    { +        $name1 = $this->_dir . '/assoc_url_' . md5($url); +        $name2 = $this->_dir . '/assoc_handle_' . md5($handle); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name1, 'w+'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $data = serialize(array($url, $handle, $macFunc, $secret, $expires)); +        fwrite($f, $data); +        if (function_exists('symlink')) { +            @unlink($name2); +            if (symlink($name1, $name2)) { +                fclose($f); +                fclose($lock); +                return true; +            } +        } +        $f2 = @fopen($name2, 'w+'); +        if ($f2) { +            fwrite($f2, $data); +            fclose($f2); +            @unlink($name1); +            $ret = true; +        } else { +            $ret = false; +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Gets information about association identified by $url +     * Returns true if given association found and not expired and false +     * otherwise +     * +     * @param string $url OpenID server URL +     * @param string &$handle assiciation handle +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    public function getAssociation($url, &$handle, &$macFunc, &$secret, &$expires) +    { +        $name1 = $this->_dir . '/assoc_url_' . md5($url); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name1, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data); +            if ($url === $storedUrl && $expires > time()) { +                $ret = true; +            } else { +                $name2 = $this->_dir . '/assoc_handle_' . md5($handle); +                fclose($f); +                @unlink($name2); +                @unlink($name1); +                fclose($lock); +                return false; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Gets information about association identified by $handle +     * Returns true if given association found and not expired and false +     * otherwise +     * +     * @param string $handle assiciation handle +     * @param string &$url OpenID server URL +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    public function getAssociationByHandle($handle, &$url, &$macFunc, &$secret, &$expires) +    { +        $name2 = $this->_dir . '/assoc_handle_' . md5($handle); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name2, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($url, $storedHandle, $macFunc, $secret, $expires) = unserialize($data); +            if ($handle === $storedHandle && $expires > time()) { +                $ret = true; +            } else { +                fclose($f); +                @unlink($name2); +                $name1 = $this->_dir . '/assoc_url_' . md5($url); +                @unlink($name1); +                fclose($lock); +                return false; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Deletes association identified by $url +     * +     * @param string $url OpenID server URL +     * @return bool +     */ +    public function delAssociation($url) +    { +        $name1 = $this->_dir . '/assoc_url_' . md5($url); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name1, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data); +            if ($url === $storedUrl) { +                $name2 = $this->_dir . '/assoc_handle_' . md5($handle); +                fclose($f); +                @unlink($name2); +                @unlink($name1); +                fclose($lock); +                return true; +            } +        } +        fclose($f); +        fclose($lock); +        return true; +    } + +    /** +     * Stores information discovered from identity $id +     * +     * @param string $id identity +     * @param string $realId discovered real identity URL +     * @param string $server discovered OpenID server URL +     * @param float $version discovered OpenID protocol version +     * @param long $expires expiration UNIX time +     * @return bool +     */ +    public function addDiscoveryInfo($id, $realId, $server, $version, $expires) +    { +        $name = $this->_dir . '/discovery_' . md5($id); +        $lock = @fopen($this->_dir . '/discovery.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'w+'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $data = serialize(array($id, $realId, $server, $version, $expires)); +        fwrite($f, $data); +        fclose($f); +        fclose($lock); +        return true; +    } + +    /** +     * Gets information discovered from identity $id +     * Returns true if such information exists and false otherwise +     * +     * @param string $id identity +     * @param string &$realId discovered real identity URL +     * @param string &$server discovered OpenID server URL +     * @param float &$version discovered OpenID protocol version +     * @param long &$expires expiration UNIX time +     * @return bool +     */ +    public function getDiscoveryInfo($id, &$realId, &$server, &$version, &$expires) +    { +        $name = $this->_dir . '/discovery_' . md5($id); +        $lock = @fopen($this->_dir . '/discovery.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedId, $realId, $server, $version, $expires) = unserialize($data); +            if ($id === $storedId && $expires > time()) { +                $ret = true; +            } else { +                fclose($f); +                @unlink($name); +                fclose($lock); +                return false; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Removes cached information discovered from identity $id +     * +     * @param string $id identity +     * @return bool +     */ +    public function delDiscoveryInfo($id) +    { +        $name = $this->_dir . '/discovery_' . md5($id); +        $lock = @fopen($this->_dir . '/discovery.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        @unlink($name); +        fclose($lock); +        return true; +    } + +    /** +     * The function checks the uniqueness of openid.response_nonce +     * +     * @param string $provider openid.openid_op_endpoint field from authentication response +     * @param  string $nonce openid.response_nonce field from authentication response +     * @return bool +     */ +    public function isUniqueNonce($provider, $nonce) +    { +        $name = $this->_dir . '/nonce_' . md5($provider.';'.$nonce); +        $lock = @fopen($this->_dir . '/nonce.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'x'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        fwrite($f, $provider.';'.$nonce); +        fclose($f); +        fclose($lock); +        return true; +    } + +    /** +     * Removes data from the uniqueness database that is older then given date +     * +     * @param mixed $date date of expired data +     */ +    public function purgeNonces($date=null) +    { +        $lock = @fopen($this->_dir . '/nonce.lock', 'w+'); +        if ($lock !== false) { +            flock($lock, LOCK_EX); +        } +        if (!is_int($date) && !is_string($date)) { +            foreach (glob($this->_dir . '/nonce_*') as $name) { +                @unlink($name); +            } +        } else { +            if (is_string($date)) { +                $time = time($date); +            } else { +                $time = $date; +            } +            foreach (glob($this->_dir . '/nonce_*') as $name) { +                if (filemtime($name) < $time) { +                    @unlink($name); +                } +            } +        } +        if ($lock !== false) { +            fclose($lock); +        } +    } +} diff --git a/applications/core/lib/Zend/OpenId/Exception.php b/applications/core/lib/Zend/OpenId/Exception.php new file mode 100644 index 0000000..42d21ae --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Exception.php @@ -0,0 +1,58 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $ + */ + +/** + * @see Zend_Exception + */ +require_once "Zend/Exception.php"; + +/** + * Exception class for Zend_OpenId + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Exception extends Zend_Exception +{ + +    /** +     * The specified digest algotithm is not supported by this PHP installation +     */ +    const UNSUPPORTED_DIGEST    = 1; + +    /** +     * The long math arithmetick is not supported by this PHP installation +     */ +    const UNSUPPORTED_LONG_MATH = 2; + +    /** +     * Internal long math arithmetic error +     */ +    const ERROR_LONG_MATH       = 3; + +    /** +     * Iternal storage error +     */ +    const ERROR_STORAGE         = 4; +} diff --git a/applications/core/lib/Zend/OpenId/Extension.php b/applications/core/lib/Zend/OpenId/Extension.php new file mode 100644 index 0000000..9924be0 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Extension.php @@ -0,0 +1,137 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Extension.php 13522 2009-01-06 16:35:55Z thomas $ + */ + +/** + * Abstract extension class for Zend_OpenId + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +abstract class Zend_OpenId_Extension +{ + +    /** +     * Calls given function with given argument for all extensions +     * +     * @param mixed $extensions list of extensions or one extension +     * @param string $func function to be called +     * @param mixed &$params argument to pass to given funcion +     * @return bool +     */ +    static public function forAll($extensions, $func, &$params) +    { +        if ($extensions !== null) { +            if (is_array($extensions)) { +                foreach ($extensions as $ext) { +                    if ($ext instanceof Zend_OpenId_Extension) { +                        if (!$ext->$func($params)) { +                            return false; +                        } +                    } else { +                        return false; +                    } +                } +            } else if (!is_object($extensions) || +                       !($extensions instanceof Zend_OpenId_Extension) || +                       !$extensions->$func($params)) { +                return false; +            } +        } +        return true; +    } + +    /** +     * Method to add additional data to OpenId 'checkid_immediate' or +     * 'checkid_setup' request. This method addes nothing but inherited class +     * may add additional data into request. +     * +     * @param array &$params request's var/val pairs +     * @return bool +     */ +    public function prepareRequest(&$params) +    { +        return true; +    } + +    /** +     * Method to parse OpenId 'checkid_immediate' or 'checkid_setup' request +     * and initialize object with passed data. This method parses nothing but +     * inherited class may override this method to do somthing. +     * +     * @param array $params request's var/val pairs +     * @return bool +     */ +    public function parseRequest($params) +    { +        return true; +    } + +    /** +     * Method to add additional data to OpenId 'id_res' response. This method +     * addes nothing but inherited class may add additional data into response. +     * +     * @param array &$params response's var/val pairs +     * @return bool +     */ +    public function prepareResponse(&$params) +    { +        return true; +    } + +    /** +     * Method to parse OpenId 'id_res' response and initialize object with +     * passed data. This method parses nothing but inherited class may override +     * this method to do somthing. +     * +     * @param array $params response's var/val pairs +     * @return bool +     */ +    public function parseResponse($params) +    { +        return true; +    } + +    /** +     * Method to prepare data to store it in trusted servers database. +     * +     * @param array &$data data to be stored in tusted servers database +     * @return bool +     */ +    public function getTrustData(&$data) +    { +        return true; +    } + +    /** +     * Method to check if data from trusted servers database is enough to +     * sutisfy request. +     * +     * @param array $data data from tusted servers database +     * @return bool +     */ +    public function checkTrustData($data) +    { +        return true; +    } +} diff --git a/applications/core/lib/Zend/OpenId/Extension/Sreg.php b/applications/core/lib/Zend/OpenId/Extension/Sreg.php new file mode 100644 index 0000000..0ee3e86 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Extension/Sreg.php @@ -0,0 +1,300 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Sreg.php 8064 2008-02-16 10:58:39Z thomas $ + */ + +/** + * @see Zend_OpenId_Extension + */ +require_once "Zend/OpenId/Extension.php"; + +/** + * 'Simple Refistration Extension' for Zend_OpenId + * + * @category   Zend + * @package    Zend_OpenId + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Extension_Sreg extends Zend_OpenId_Extension +{ +    /** +     * SREG 1.1 namespace. All OpenID SREG 1.1 messages MUST contain variable +     * openid.ns.sreg with its value. +     */ +    const NAMESPACE_1_1 = "http://openid.net/extensions/sreg/1.1"; + +    private $_props; +    private $_policy_url; +    private $_version; + +    /** +     * Creates SREG extension object +     * +     * @param array $props associative array of SREG variables +     * @param string $policy_url SREG policy URL +     * @param float $version SREG version +     * @return array +     */ +    public function __construct(array $props=null, $policy_url=null, $version=1.0) +    { +        $this->_props = $props; +        $this->_policy_url = $policy_url; +        $this->_version = $version; +    } + +    /** +     * Returns associative array of SREG variables +     * +     * @return array +     */ +    public function getProperties() { +        if (is_array($this->_props)) { +            return $this->_props; +        } else { +            return array(); +        } +    } + +    /** +     * Returns SREG policy URL +     * +     * @return string +     */ +    public function getPolicyUrl() { +        return $this->_policy_url; +    } + +    /** +     * Returns SREG protocol version +     * +     * @return float +     */ +    public function getVersion() { +        return $this->_version; +    } + +    /** +     * Returns array of allowed SREG variable names. +     * +     * @return array +     */ +    public static function getSregProperties() +    { +        return array( +            "nickname", +            "email", +            "fullname", +            "dob", +            "gender", +            "postcode", +            "country", +            "language", +            "timezone" +        ); +    } + +    /** +     * Adds additional SREG data to OpenId 'checkid_immediate' or +     * 'checkid_setup' request. +     * +     * @param array &$params request's var/val pairs +     * @return bool +     */ +    public function prepareRequest(&$params) +    { +        if (is_array($this->_props) && count($this->_props) > 0) { +            foreach ($this->_props as $prop => $req) { +                if ($req) { +                    if (isset($required)) { +                        $required .= ','.$prop; +                    } else { +                        $required = $prop; +                    } +                } else { +                    if (isset($optional)) { +                        $optional .= ','.$prop; +                    } else { +                        $optional = $prop; +                    } +                } +            } +            if ($this->_version >= 1.1) { +                $params['openid.ns.sreg'] = Zend_OpenId_Extension_Sreg::NAMESPACE_1_1; +            } +            if (!empty($required)) { +                $params['openid.sreg.required'] = $required; +            } +            if (!empty($optional)) { +                $params['openid.sreg.optional'] = $optional; +            } +            if (!empty($this->_policy_url)) { +                $params['openid.sreg.policy_url'] = $this->_policy_url; +            } +        } +        return true; +    } + +    /** +     * Parses OpenId 'checkid_immediate' or 'checkid_setup' request, +     * extracts SREG variables and sets ovject properties to corresponding +     * values. +     * +     * @param array $params request's var/val pairs +     * @return bool +     */ +    public function parseRequest($params) +    { +        if (isset($params['openid_ns_sreg']) && +            $params['openid_ns_sreg'] === Zend_OpenId_Extension_Sreg::NAMESPACE_1_1) { +            $this->_version= 1.1; +        } else { +            $this->_version= 1.0; +        } +        if (!empty($params['openid_sreg_policy_url'])) { +            $this->_policy_url = $params['openid_sreg_policy_url']; +        } else { +            $this->_policy_url = null; +        } +        $props = array(); +        if (!empty($params['openid_sreg_optional'])) { +            foreach (explode(',', $params['openid_sreg_optional']) as $prop) { +                $prop = trim($prop); +                $props[$prop] = false; +            } +        } +        if (!empty($params['openid_sreg_required'])) { +            foreach (explode(',', $params['openid_sreg_required']) as $prop) { +                $prop = trim($prop); +                $props[$prop] = true; +            } +        } +        $props2 = array(); +        foreach (self::getSregProperties() as $prop) { +            if (isset($props[$prop])) { +                $props2[$prop] = $props[$prop]; +            } +        } + +        $this->_props = (count($props2) > 0) ? $props2 : null; +        return true; +    } + +    /** +     * Adds additional SREG data to OpenId 'id_res' response. +     * +     * @param array &$params response's var/val pairs +     * @return bool +     */ +    public function prepareResponse(&$params) +    { +        if (is_array($this->_props) && count($this->_props) > 0) { +            if ($this->_version >= 1.1) { +                $params['openid.ns.sreg'] = Zend_OpenId_Extension_Sreg::NAMESPACE_1_1; +            } +            foreach (self::getSregProperties() as $prop) { +                if (!empty($this->_props[$prop])) { +                    $params['openid.sreg.' . $prop] = $this->_props[$prop]; +                } +            } +        } +        return true; +    } + +    /** +     * Parses OpenId 'id_res' response and sets object's properties according +     * to 'openid.sreg.*' variables in response +     * +     * @param array $params response's var/val pairs +     * @return bool +     */ +    public function parseResponse($params) +    { +        if (isset($params['openid_ns_sreg']) && +            $params['openid_ns_sreg'] === Zend_OpenId_Extension_Sreg::NAMESPACE_1_1) { +            $this->_version= 1.1; +        } else { +            $this->_version= 1.0; +        } +        $props = array(); +        foreach (self::getSregProperties() as $prop) { +            if (!empty($params['openid_sreg_' . $prop])) { +                $props[$prop] = $params['openid_sreg_' . $prop]; +            } +        } +        if (isset($this->_props) && is_array($this->_props)) { +            foreach (self::getSregProperties() as $prop) { +                if (isset($this->_props[$prop]) && +                    $this->_props[$prop] && +                    !isset($props[$prop])) { +                    return false; +                } +            } +        } +        $this->_props = (count($props) > 0) ? $props : null; +        return true; +    } + +    /** +     * Addes SREG properties that are allowed to be send to consumer to +     * the given $data argument. +     * +     * @param array &$data data to be stored in tusted servers database +     * @return bool +     */ +    public function getTrustData(&$data) +    { +        $data[get_class()] = $this->getProperties(); +        return true; +    } + +    /** +     * Check if given $data contains necessury SREG properties to sutisfy +     * OpenId request. On success sets SREG response properties from given +     * $data and returns true, on failure returns false. +     * +     * @param array $data data from tusted servers database +     * @return bool +     */ +    public function checkTrustData($data) +    { +        if (is_array($this->_props) && count($this->_props) > 0) { +            $props = array(); +            $name = get_class(); +            if (isset($data[$name])) { +                $props = $data[$name]; +            } else { +                $props = array(); +            } +            $props2 = array(); +            foreach ($this->_props as $prop => $req) { +                if (empty($props[$prop])) { +                    if ($req) { +                        return false; +                    } +                } else { +                    $props2[$prop] = $props[$prop]; +                } +            } +            $this->_props = (count($props2) > 0) ? $props2 : null; +        } +        return true; +    } +} diff --git a/applications/core/lib/Zend/OpenId/Provider.php b/applications/core/lib/Zend/OpenId/Provider.php new file mode 100644 index 0000000..c1a10ef --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Provider.php @@ -0,0 +1,781 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Provider.php 13522 2009-01-06 16:35:55Z thomas $ + */ + +/** + * @see Zend_OpenId + */ +require_once "Zend/OpenId.php"; + +/** + * @see Zend_OpenId_Extension + */ +require_once "Zend/OpenId/Extension.php"; + +/** + * OpenID provider (server) implementation + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 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) { +            require_once "Zend/OpenId/Provider/User/Session.php"; +            $this->_user = new Zend_OpenId_Provider_User_Session(); +        } else { +            $this->_user = $user; +        } +        if ($storage === null) { +            require_once "Zend/OpenId/Provider/Storage/File.php"; +            $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 (base64_decode($params['openid_sig']) === +            Zend_OpenId::hashHmac($macFunc, $data, $secret)) { +            $ret['is_valid'] = 'true'; +        } else { +            $ret['is_valid'] = 'false'; +        } +        return $ret; +    } +} diff --git a/applications/core/lib/Zend/OpenId/Provider/Storage.php b/applications/core/lib/Zend/OpenId/Provider/Storage.php new file mode 100644 index 0000000..53aa7cd --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Provider/Storage.php @@ -0,0 +1,106 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Storage.php 8064 2008-02-16 10:58:39Z thomas $ + */ + +/** + * Abstract class to implement external storage for OpenID consumer + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +abstract class Zend_OpenId_Provider_Storage +{ + +    /** +     * Stores information about session identified by $handle +     * +     * @param string $handle assiciation handle +     * @param string $macFunc HMAC function (sha1 or sha256) +     * @param string $secret shared secret +     * @param string $expires expiration UNIX time +     * @return void +     */ +    abstract public function addAssociation($handle, $macFunc, $secret, $expires); + +    /** +     * Gets information about association identified by $handle +     * Returns true if given association found and not expired and false +     * otherwise +     * +     * @param string $handle assiciation handle +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param string &$expires expiration UNIX time +     * @return bool +     */ +    abstract public function getAssociation($handle, &$macFunc, &$secret, &$expires); + +    /** +     * Register 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 +     */ +    abstract public function addUser($id, $password); + +    /** +     * Returns true if user with given $id exists and false otherwise +     * +     * @param string $id user identity URL +     * @return bool +     */ +    abstract public function hasUser($id); + +    /** +     * Verify if user with given $id exists and has specified $password +     * +     * @param string $id user identity URL +     * @param string $password user password +     * @return bool +     */ +    abstract public function checkUser($id, $password); + +    /** +     * Returns array of all trusted/untrusted sites for given user identified +     * by $id +     * +     * @param string $id user identity URL +     * @return array +     */ +    abstract public function getTrustedSites($id); + +    /** +     * Stores information about trusted/untrusted site for given user +     * +     * @param string $id user identity URL +     * @param string $site site URL +     * @param mixed $trusted trust data from extensions or just a boolean value +     * @return bool +     */ +    abstract public function addSite($id, $site, $trusted); +} diff --git a/applications/core/lib/Zend/OpenId/Provider/Storage/File.php b/applications/core/lib/Zend/OpenId/Provider/Storage/File.php new file mode 100644 index 0000000..6169766 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Provider/Storage/File.php @@ -0,0 +1,397 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: File.php 13522 2009-01-06 16:35:55Z thomas $ + */ + +/** + * @see Zend_OpenId_Provider_Storage + */ +require_once "Zend/OpenId/Provider/Storage.php"; + +/** + * External storage implemmentation using serialized files + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Provider_Storage_File extends Zend_OpenId_Provider_Storage +{ + +    /** +     * Directory name to store data files in +     * +     * @var string $_dir +     */ +    private $_dir; + +    /** +     * Constructs storage object and creates storage directory +     * +     * @param string $dir directory name to store data files in +     * @throws Zend_OpenId_Exception +     */ +    public function __construct($dir = null) +    { +        if ($dir === null) { +            $tmp = getenv('TMP'); +            if (empty($tmp)) { +                $tmp = getenv('TEMP'); +                if (empty($tmp)) { +                    $tmp = "/tmp"; +                } +            } +            $user = get_current_user(); +            if (is_string($user) && !empty($user)) { +                $tmp .= '/' . $user; +            } +            $dir = $tmp . '/openid/provider'; +        } +        $this->_dir = $dir; +        if (!is_dir($this->_dir)) { +            if (!@mkdir($this->_dir, 0700, 1)) { +                throw new Zend_OpenId_Exception( +                    "Cannot access storage directory $dir", +                    Zend_OpenId_Exception::ERROR_STORAGE); +            } +        } +        if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) { +            throw new Zend_OpenId_Exception( +                'Cannot create a lock file in the directory ' . $dir, +                Zend_OpenId_Exception::ERROR_STORAGE); +        } +        fclose($f); +        if (($f = fopen($this->_dir.'/user.lock', 'w+')) === null) { +            throw new Zend_OpenId_Exception( +                'Cannot create a lock file in the directory ' . $dir, +                Zend_OpenId_Exception::ERROR_STORAGE); +        } +        fclose($f); +    } + +    /** +     * Stores information about session identified by $handle +     * +     * @param string $handle assiciation handle +     * @param string $macFunc HMAC function (sha1 or sha256) +     * @param string $secret shared secret +     * @param string $expires expiration UNIX time +     * @return bool +     */ +    public function addAssociation($handle, $macFunc, $secret, $expires) +    { +        $name = $this->_dir . '/assoc_' . md5($handle); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'w+'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $data = serialize(array($handle, $macFunc, $secret, $expires)); +        fwrite($f, $data); +        fclose($f); +        fclose($lock); +        return true; +    } + +    /** +     * Gets information about association identified by $handle +     * Returns true if given association found and not expired and false +     * otherwise +     * +     * @param string $handle assiciation handle +     * @param string &$macFunc HMAC function (sha1 or sha256) +     * @param string &$secret shared secret +     * @param string &$expires expiration UNIX time +     * @return bool +     */ +    public function getAssociation($handle, &$macFunc, &$secret, &$expires) +    { +        $name = $this->_dir . '/assoc_' . md5($handle); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedHandle, $macFunc, $secret, $expires) = unserialize($data); +            if ($handle === $storedHandle && $expires > time()) { +                $ret = true; +            } else { +                fclose($f); +                @unlink($name); +                fclose($lock); +                return false; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Removes information about association identified by $handle +     * +     * @param string $handle assiciation handle +     * @return bool +     */ +    public function delAssociation($handle) +    { +        $name = $this->_dir . '/assoc_' . md5($handle); +        $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        @unlink($name); +        fclose($lock); +        return true; +    } + +    /** +     * Register 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 addUser($id, $password) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'x'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $data = serialize(array($id, $password, array())); +        fwrite($f, $data); +        fclose($f); +        fclose($lock); +        return true; +    } + +    /** +     * Returns true if user with given $id exists and false otherwise +     * +     * @param string $id user identity URL +     * @return bool +     */ +    public function hasUser($id) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_SH)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedId, $storedPassword, $trusted) = unserialize($data); +            if ($id === $storedId) { +                $ret = true; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Verify if user with given $id exists and has specified $password +     * +     * @param string $id user identity URL +     * @param string $password user password +     * @return bool +     */ +    public function checkUser($id, $password) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_SH)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedId, $storedPassword, $trusted) = unserialize($data); +            if ($id === $storedId && $password === $storedPassword) { +                $ret = true; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Removes information abou specified user +     * +     * @param string $id user identity URL +     * @return bool +     */ +    public function delUser($id) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        @unlink($name); +        fclose($lock); +        return true; +    } + +    /** +     * Returns array of all trusted/untrusted sites for given user identified +     * by $id +     * +     * @param string $id user identity URL +     * @return array +     */ +    public function getTrustedSites($id) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_SH)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedId, $storedPassword, $trusted) = unserialize($data); +            if ($id === $storedId) { +                $ret = $trusted; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } + +    /** +     * Stores information about trusted/untrusted site for given user +     * +     * @param string $id user identity URL +     * @param string $site site URL +     * @param mixed $trusted trust data from extension or just a boolean value +     * @return bool +     */ +    public function addSite($id, $site, $trusted) +    { +        $name = $this->_dir . '/user_' . md5($id); +        $lock = @fopen($this->_dir . '/user.lock', 'w+'); +        if ($lock === false) { +            return false; +        } +        if (!flock($lock, LOCK_EX)) { +            fclose($lock); +            return false; +        } +        $f = @fopen($name, 'r+'); +        if ($f === false) { +            fclose($lock); +            return false; +        } +        $ret = false; +        $data = stream_get_contents($f); +        if (!empty($data)) { +            list($storedId, $storedPassword, $sites) = unserialize($data); +            if ($id === $storedId) { +                if ($trusted === null) { +                    unset($sites[$site]); +                } else { +                    $sites[$site] = $trusted; +                } +                rewind($f); +                ftruncate($f, 0); +                $data = serialize(array($id, $storedPassword, $sites)); +                fwrite($f, $data); +                $ret = true; +            } +        } +        fclose($f); +        fclose($lock); +        return $ret; +    } +} diff --git a/applications/core/lib/Zend/OpenId/Provider/User.php b/applications/core/lib/Zend/OpenId/Provider/User.php new file mode 100644 index 0000000..db73612 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Provider/User.php @@ -0,0 +1,57 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: User.php 8064 2008-02-16 10:58:39Z thomas $ + */ + +/** + * Abstract class to get/store information about logged in user in Web Browser + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +abstract class Zend_OpenId_Provider_User +{ + +    /** +     * Stores information about logged in user +     * +     * @param string $id user identity URL +     * @return bool +     */ +    abstract public function setLoggedInUser($id); + +    /** +     * Returns identity URL of logged in user or false +     * +     * @return mixed +     */ +    abstract public function getLoggedInUser(); + +    /** +     * Performs logout. Clears information about logged in user. +     * +     * @return bool +     */ +    abstract public function delLoggedInUser(); +} diff --git a/applications/core/lib/Zend/OpenId/Provider/User/Session.php b/applications/core/lib/Zend/OpenId/Provider/User/Session.php new file mode 100644 index 0000000..90870b0 --- /dev/null +++ b/applications/core/lib/Zend/OpenId/Provider/User/Session.php @@ -0,0 +1,104 @@ +<?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 [email protected] so we can send you a copy immediately. + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + * @version    $Id: Session.php 8064 2008-02-16 10:58:39Z thomas $ + */ + +/** + * @see Zend_OpenId_Provider_User + */ +require_once "Zend/OpenId/Provider/User.php"; + +/** + * @see Zend_Session_Namespace + */ +require_once "Zend/Session/Namespace.php"; + +/** + * Class to get/store information about logged in user in Web Browser using + * PHP session + * + * @category   Zend + * @package    Zend_OpenId + * @subpackage Zend_OpenId_Provider + * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) + * @license    http://framework.zend.com/license/new-bsd     New BSD License + */ +class Zend_OpenId_Provider_User_Session extends Zend_OpenId_Provider_User +{ +    /** +     * Reference to an implementation of Zend_Session_Namespace object +     * +     * @var Zend_Session_Namespace $_session +     */ +    private $_session = null; + +    /** +     * Creates Zend_OpenId_Provider_User_Session object with given session +     * namespace or creates new session namespace named "openid" +     * +     * @param Zend_Session_Namespace $session +     */ +    public function __construct(Zend_Session_Namespace $session = null) +    { +        if ($session === null) { +            $this->_session = new Zend_Session_Namespace("openid"); +        } else { +            $this->_session = $session; +        } +    } + +    /** +     * Stores information about logged in user in session data +     * +     * @param string $id user identity URL +     * @return bool +     */ +    public function setLoggedInUser($id) +    { +        $this->_session->logged_in = $id; +        return true; +    } + +    /** +     * Returns identity URL of logged in user or false +     * +     * @return mixed +     */ +    public function getLoggedInUser() +    { +        if (isset($this->_session->logged_in)) { +            return $this->_session->logged_in; +        } +        return false; +    } + +    /** +     * Performs logout. Clears information about logged in user. +     * +     * @return bool +     */ +    public function delLoggedInUser() +    { +        unset($this->_session->logged_in); +        return true; +    } + +} | 
