File indexing completed on 2025-03-02 05:29:37

0001 <?php
0002 
0003 /**
0004  * Zend Framework
0005  *
0006  * LICENSE
0007  *
0008  * This source file is subject to the new BSD license that is bundled
0009  * with this package in the file LICENSE.txt.
0010  * It is also available through the world-wide-web at this URL:
0011  * http://framework.zend.com/license/new-bsd
0012  * If you did not receive a copy of the license and are unable to
0013  * obtain it through the world-wide-web, please send an email
0014  * to license@zend.com so we can send you a copy immediately.
0015  *
0016  * @category   Zend
0017  * @package    Zend_OpenId
0018  * @subpackage Zend_OpenId_Provider
0019  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0020  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0021  * @version    $Id$
0022  */
0023 
0024 /**
0025  * @see Zend_OpenId_Provider_Storage
0026  */
0027 // require_once "Zend/OpenId/Provider/Storage.php";
0028 
0029 /**
0030  * External storage implemmentation using serialized files
0031  *
0032  * @category   Zend
0033  * @package    Zend_OpenId
0034  * @subpackage Zend_OpenId_Provider
0035  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0036  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0037  */
0038 class Zend_OpenId_Provider_Storage_File extends Zend_OpenId_Provider_Storage
0039 {
0040 
0041     /**
0042      * Directory name to store data files in
0043      *
0044      * @var string $_dir
0045      */
0046     private $_dir;
0047 
0048     /**
0049      * Constructs storage object and creates storage directory
0050      *
0051      * @param string $dir directory name to store data files in
0052      * @throws Zend_OpenId_Exception
0053      */
0054     public function __construct($dir = null)
0055     {
0056         if ($dir === null) {
0057             $tmp = getenv('TMP');
0058             if (empty($tmp)) {
0059                 $tmp = getenv('TEMP');
0060                 if (empty($tmp)) {
0061                     $tmp = "/tmp";
0062                 }
0063             }
0064             $user = get_current_user();
0065             if (is_string($user) && !empty($user)) {
0066                 $tmp .= '/' . $user;
0067             }
0068             $dir = $tmp . '/openid/provider';
0069         }
0070         $this->_dir = $dir;
0071         if (!is_dir($this->_dir)) {
0072             if (!@mkdir($this->_dir, 0700, 1)) {
0073                 throw new Zend_OpenId_Exception(
0074                     "Cannot access storage directory $dir",
0075                     Zend_OpenId_Exception::ERROR_STORAGE);
0076             }
0077         }
0078         if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) {
0079             throw new Zend_OpenId_Exception(
0080                 'Cannot create a lock file in the directory ' . $dir,
0081                 Zend_OpenId_Exception::ERROR_STORAGE);
0082         }
0083         fclose($f);
0084         if (($f = fopen($this->_dir.'/user.lock', 'w+')) === null) {
0085             throw new Zend_OpenId_Exception(
0086                 'Cannot create a lock file in the directory ' . $dir,
0087                 Zend_OpenId_Exception::ERROR_STORAGE);
0088         }
0089         fclose($f);
0090     }
0091 
0092     /**
0093      * Stores information about session identified by $handle
0094      *
0095      * @param string $handle assiciation handle
0096      * @param string $macFunc HMAC function (sha1 or sha256)
0097      * @param string $secret shared secret
0098      * @param string $expires expiration UNIX time
0099      * @return bool
0100      */
0101     public function addAssociation($handle, $macFunc, $secret, $expires)
0102     {
0103         $name = $this->_dir . '/assoc_' . md5($handle);
0104         $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
0105         if ($lock === false) {
0106             return false;
0107         }
0108         if (!flock($lock, LOCK_EX)) {
0109             fclose($lock);
0110             return false;
0111         }
0112         try {
0113             $f = @fopen($name, 'w+');
0114             if ($f === false) {
0115                 fclose($lock);
0116                 return false;
0117             }
0118             $data = serialize(array($handle, $macFunc, $secret, $expires));
0119             fwrite($f, $data);
0120             fclose($f);
0121             fclose($lock);
0122             return true;
0123         } catch (Exception $e) {
0124             fclose($lock);
0125             throw $e;
0126         }
0127     }
0128 
0129     /**
0130      * Gets information about association identified by $handle
0131      * Returns true if given association found and not expired and false
0132      * otherwise
0133      *
0134      * @param string $handle assiciation handle
0135      * @param string &$macFunc HMAC function (sha1 or sha256)
0136      * @param string &$secret shared secret
0137      * @param string &$expires expiration UNIX time
0138      * @return bool
0139      */
0140     public function getAssociation($handle, &$macFunc, &$secret, &$expires)
0141     {
0142         $name = $this->_dir . '/assoc_' . md5($handle);
0143         $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
0144         if ($lock === false) {
0145             return false;
0146         }
0147         if (!flock($lock, LOCK_EX)) {
0148             fclose($lock);
0149             return false;
0150         }
0151         try {
0152             $f = @fopen($name, 'r');
0153             if ($f === false) {
0154                 fclose($lock);
0155                 return false;
0156             }
0157             $ret = false;
0158             $data = stream_get_contents($f);
0159             if (!empty($data)) {
0160                 list($storedHandle, $macFunc, $secret, $expires) = unserialize($data);
0161                 if ($handle === $storedHandle && $expires > time()) {
0162                     $ret = true;
0163                 } else {
0164                     fclose($f);
0165                     @unlink($name);
0166                     fclose($lock);
0167                     return false;
0168                 }
0169             }
0170             fclose($f);
0171             fclose($lock);
0172             return $ret;
0173         } catch (Exception $e) {
0174             fclose($lock);
0175             throw $e;
0176         }
0177     }
0178 
0179     /**
0180      * Removes information about association identified by $handle
0181      *
0182      * @param string $handle assiciation handle
0183      * @return bool
0184      */
0185     public function delAssociation($handle)
0186     {
0187         $name = $this->_dir . '/assoc_' . md5($handle);
0188         $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
0189         if ($lock === false) {
0190             return false;
0191         }
0192         if (!flock($lock, LOCK_EX)) {
0193             fclose($lock);
0194             return false;
0195         }
0196         try {
0197             @unlink($name);
0198             fclose($lock);
0199             return true;
0200         } catch (Exception $e) {
0201             fclose($lock);
0202             throw $e;
0203         }
0204     }
0205 
0206     /**
0207      * Register new user with given $id and $password
0208      * Returns true in case of success and false if user with given $id already
0209      * exists
0210      *
0211      * @param string $id user identity URL
0212      * @param string $password encoded user password
0213      * @return bool
0214      */
0215     public function addUser($id, $password)
0216     {
0217         $name = $this->_dir . '/user_' . md5($id);
0218         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0219         if ($lock === false) {
0220             return false;
0221         }
0222         if (!flock($lock, LOCK_EX)) {
0223             fclose($lock);
0224             return false;
0225         }
0226         try {
0227             $f = @fopen($name, 'x');
0228             if ($f === false) {
0229                 fclose($lock);
0230                 return false;
0231             }
0232             $data = serialize(array($id, $password, array()));
0233             fwrite($f, $data);
0234             fclose($f);
0235             fclose($lock);
0236             return true;
0237         } catch (Exception $e) {
0238             fclose($lock);
0239             throw $e;
0240         }
0241     }
0242 
0243     /**
0244      * Returns true if user with given $id exists and false otherwise
0245      *
0246      * @param string $id user identity URL
0247      * @return bool
0248      */
0249     public function hasUser($id)
0250     {
0251         $name = $this->_dir . '/user_' . md5($id);
0252         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0253         if ($lock === false) {
0254             return false;
0255         }
0256         if (!flock($lock, LOCK_SH)) {
0257             fclose($lock);
0258             return false;
0259         }
0260         try {
0261             $f = @fopen($name, 'r');
0262             if ($f === false) {
0263                 fclose($lock);
0264                 return false;
0265             }
0266             $ret = false;
0267             $data = stream_get_contents($f);
0268             if (!empty($data)) {
0269                 list($storedId, $storedPassword, $trusted) = unserialize($data);
0270                 if ($id === $storedId) {
0271                     $ret = true;
0272                 }
0273             }
0274             fclose($f);
0275             fclose($lock);
0276             return $ret;
0277         } catch (Exception $e) {
0278             fclose($lock);
0279             throw $e;
0280         }
0281     }
0282 
0283     /**
0284      * Verify if user with given $id exists and has specified $password
0285      *
0286      * @param string $id user identity URL
0287      * @param string $password user password
0288      * @return bool
0289      */
0290     public function checkUser($id, $password)
0291     {
0292         $name = $this->_dir . '/user_' . md5($id);
0293         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0294         if ($lock === false) {
0295             return false;
0296         }
0297         if (!flock($lock, LOCK_SH)) {
0298             fclose($lock);
0299             return false;
0300         }
0301         try {
0302             $f = @fopen($name, 'r');
0303             if ($f === false) {
0304                 fclose($lock);
0305                 return false;
0306             }
0307             $ret = false;
0308             $data = stream_get_contents($f);
0309             if (!empty($data)) {
0310                 list($storedId, $storedPassword, $trusted) = unserialize($data);
0311                 if ($id === $storedId && $password === $storedPassword) {
0312                     $ret = true;
0313                 }
0314             }
0315             fclose($f);
0316             fclose($lock);
0317             return $ret;
0318         } catch (Exception $e) {
0319             fclose($lock);
0320             throw $e;
0321         }
0322     }
0323 
0324     /**
0325      * Removes information abou specified user
0326      *
0327      * @param string $id user identity URL
0328      * @return bool
0329      */
0330     public function delUser($id)
0331     {
0332         $name = $this->_dir . '/user_' . md5($id);
0333         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0334         if ($lock === false) {
0335             return false;
0336         }
0337         if (!flock($lock, LOCK_EX)) {
0338             fclose($lock);
0339             return false;
0340         }
0341         try {
0342             @unlink($name);
0343             fclose($lock);
0344             return true;
0345         } catch (Exception $e) {
0346             fclose($lock);
0347             throw $e;
0348         }
0349     }
0350 
0351     /**
0352      * Returns array of all trusted/untrusted sites for given user identified
0353      * by $id
0354      *
0355      * @param string $id user identity URL
0356      * @return array
0357      */
0358     public function getTrustedSites($id)
0359     {
0360         $name = $this->_dir . '/user_' . md5($id);
0361         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0362         if ($lock === false) {
0363             return false;
0364         }
0365         if (!flock($lock, LOCK_SH)) {
0366             fclose($lock);
0367             return false;
0368         }
0369         try {
0370             $f = @fopen($name, 'r');
0371             if ($f === false) {
0372                 fclose($lock);
0373                 return false;
0374             }
0375             $ret = false;
0376             $data = stream_get_contents($f);
0377             if (!empty($data)) {
0378                 list($storedId, $storedPassword, $trusted) = unserialize($data);
0379                 if ($id === $storedId) {
0380                     $ret = $trusted;
0381                 }
0382             }
0383             fclose($f);
0384             fclose($lock);
0385             return $ret;
0386         } catch (Exception $e) {
0387             fclose($lock);
0388             throw $e;
0389         }
0390     }
0391 
0392     /**
0393      * Stores information about trusted/untrusted site for given user
0394      *
0395      * @param string $id user identity URL
0396      * @param string $site site URL
0397      * @param mixed $trusted trust data from extension or just a boolean value
0398      * @return bool
0399      */
0400     public function addSite($id, $site, $trusted)
0401     {
0402         $name = $this->_dir . '/user_' . md5($id);
0403         $lock = @fopen($this->_dir . '/user.lock', 'w+');
0404         if ($lock === false) {
0405             return false;
0406         }
0407         if (!flock($lock, LOCK_EX)) {
0408             fclose($lock);
0409             return false;
0410         }
0411         try {
0412             $f = @fopen($name, 'r+');
0413             if ($f === false) {
0414                 fclose($lock);
0415                 return false;
0416             }
0417             $ret = false;
0418             $data = stream_get_contents($f);
0419             if (!empty($data)) {
0420                 list($storedId, $storedPassword, $sites) = unserialize($data);
0421                 if ($id === $storedId) {
0422                     if ($trusted === null) {
0423                         unset($sites[$site]);
0424                     } else {
0425                         $sites[$site] = $trusted;
0426                     }
0427                     rewind($f);
0428                     ftruncate($f, 0);
0429                     $data = serialize(array($id, $storedPassword, $sites));
0430                     fwrite($f, $data);
0431                     $ret = true;
0432                 }
0433             }
0434             fclose($f);
0435             fclose($lock);
0436             return $ret;
0437         } catch (Exception $e) {
0438             fclose($lock);
0439             throw $e;
0440         }
0441     }
0442 }