Current File : /home/k/a/r/karenpetzb/www/items/category/OpenId.tar
Consumer.php000060400000102375150711771470007066 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_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 12972 2008-12-01 13:26:36Z dmitry $
 */

/**
 * @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::prepareResponse 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.climed_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;
    }

}
Exception.php000060400000003045150711771470007223 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @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;
}
Provider.php000060400000064424150711771470007067 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_Provider
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Provider.php 12507 2008-11-10 16:29:09Z matthew $
 */

/**
 * @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 (is_null($trusted)) {
            /* 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;
    }
}
Provider/Storage.php000060400000006517150711771470010472 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_Provider
 * @copyright  Copyright (c) 2005-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);
}
Provider/User/Session.php000060400000005337150711771470011426 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_Provider
 * @copyright  Copyright (c) 2005-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;
    }

}
Provider/User.php000060400000003166150711771470010001 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_Provider
 * @copyright  Copyright (c) 2005-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();
}
Provider/Storage/File.php000060400000026455150711771470011354 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_Provider
 * @copyright  Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: File.php 8456 2008-02-29 11:01:12Z dmitry $
 */

/**
 * @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 (is_null($dir)) {
            $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 (is_null($trusted)) {
                    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;
    }
}
Extension/Sreg.php000060400000021406150711771470010142 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @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;
    }
}
Extension.php000060400000007774150711771470007256 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @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 8064 2008-02-16 10:58:39Z 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 (!is_null($extensions)) {
            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;
    }
}
Consumer/Storage/File.php000060400000033743150711771470011353 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_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 12970 2008-12-01 12:55:17Z dmitry $
 */

/**
 * @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 (is_null($dir)) {
            $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);
        }
    }
}
Consumer/Storage.php000060400000010775150711771470010474 0ustar00<?php

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_OpenId
 * @subpackage Zend_OpenId_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);
}