File indexing completed on 2024-06-16 05:30:05

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Form
0017  * @subpackage Element
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  */
0021 
0022 /** Zend_Form_Element_Xhtml */
0023 // require_once 'Zend/Form/Element/Xhtml.php';
0024 
0025 /** @see Zend_Crypt_Math */
0026 // require_once 'Zend/Crypt/Math.php';
0027 
0028 /**
0029  * CSRF form protection
0030  *
0031  * @category   Zend
0032  * @package    Zend_Form
0033  * @subpackage Element
0034  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0035  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0036  * @version    $Id$
0037  */
0038 class Zend_Form_Element_Hash extends Zend_Form_Element_Xhtml
0039 {
0040     /**
0041      * Use formHidden view helper by default
0042      * @var string
0043      */
0044     public $helper = 'formHidden';
0045 
0046     /**
0047      * Actual hash used.
0048      *
0049      * @var mixed
0050      */
0051     protected $_hash;
0052 
0053     /**
0054      * Salt for CSRF token
0055      * @var string
0056      */
0057     protected $_salt = 'salt';
0058 
0059     /**
0060      * @var Zend_Session_Namespace
0061      */
0062     protected $_session;
0063 
0064     /**
0065      * TTL for CSRF token
0066      * @var int
0067      */
0068     protected $_timeout = 300;
0069 
0070     /**
0071      * Constructor
0072      *
0073      * Creates session namespace for CSRF token, and adds validator for CSRF
0074      * token.
0075      *
0076      * @param  string|array|Zend_Config $spec
0077      * @param  array|Zend_Config $options
0078      * @return void
0079      */
0080     public function __construct($spec, $options = null)
0081     {
0082         parent::__construct($spec, $options);
0083 
0084         $this->setAllowEmpty(false)
0085              ->setRequired(true)
0086              ->initCsrfValidator();
0087     }
0088 
0089     /**
0090      * Set session object
0091      *
0092      * @param  Zend_Session_Namespace $session
0093      * @return Zend_Form_Element_Hash
0094      */
0095     public function setSession($session)
0096     {
0097         $this->_session = $session;
0098         return $this;
0099     }
0100 
0101     /**
0102      * Get session object
0103      *
0104      * Instantiate session object if none currently exists
0105      *
0106      * @return Zend_Session_Namespace
0107      */
0108     public function getSession()
0109     {
0110         if (null === $this->_session) {
0111             // require_once 'Zend/Session/Namespace.php';
0112             $this->_session = new Zend_Session_Namespace($this->getSessionName());
0113         }
0114         return $this->_session;
0115     }
0116 
0117     /**
0118      * Initialize CSRF validator
0119      *
0120      * Creates Session namespace, and initializes CSRF token in session.
0121      * Additionally, adds validator for validating CSRF token.
0122      *
0123      * @return Zend_Form_Element_Hash
0124      */
0125     public function initCsrfValidator()
0126     {
0127         $session = $this->getSession();
0128         if (isset($session->hash)) {
0129             $rightHash = $session->hash;
0130         } else {
0131             $rightHash = null;
0132         }
0133 
0134         $this->addValidator('Identical', true, array($rightHash));
0135         return $this;
0136     }
0137 
0138     /**
0139      * Salt for CSRF token
0140      *
0141      * @param  string $salt
0142      * @return Zend_Form_Element_Hash
0143      */
0144     public function setSalt($salt)
0145     {
0146         $this->_salt = (string) $salt;
0147         return $this;
0148     }
0149 
0150     /**
0151      * Retrieve salt for CSRF token
0152      *
0153      * @return string
0154      */
0155     public function getSalt()
0156     {
0157         return $this->_salt;
0158     }
0159 
0160     /**
0161      * Retrieve CSRF token
0162      *
0163      * If no CSRF token currently exists, generates one.
0164      *
0165      * @return string
0166      */
0167     public function getHash()
0168     {
0169         if (null === $this->_hash) {
0170             $this->_generateHash();
0171         }
0172         return $this->_hash;
0173     }
0174 
0175     /**
0176      * Get session namespace for CSRF token
0177      *
0178      * Generates a session namespace based on salt, element name, and class.
0179      *
0180      * @return string
0181      */
0182     public function getSessionName()
0183     {
0184         return __CLASS__ . '_' . $this->getSalt() . '_' . $this->getName();
0185     }
0186 
0187     /**
0188      * Set timeout for CSRF session token
0189      *
0190      * @param  int $ttl
0191      * @return Zend_Form_Element_Hash
0192      */
0193     public function setTimeout($ttl)
0194     {
0195         $this->_timeout = (int) $ttl;
0196         return $this;
0197     }
0198 
0199     /**
0200      * Get CSRF session token timeout
0201      *
0202      * @return int
0203      */
0204     public function getTimeout()
0205     {
0206         return $this->_timeout;
0207     }
0208 
0209     /**
0210      * Override getLabel() to always be empty
0211      *
0212      * @return null
0213      */
0214     public function getLabel()
0215     {
0216         return null;
0217     }
0218 
0219     /**
0220      * Initialize CSRF token in session
0221      *
0222      * @return void
0223      */
0224     public function initCsrfToken()
0225     {
0226         $session = $this->getSession();
0227         $session->setExpirationHops(1, null, true);
0228         $session->setExpirationSeconds($this->getTimeout());
0229         $session->hash = $this->getHash();
0230     }
0231 
0232     /**
0233      * Render CSRF token in form
0234      *
0235      * @param  Zend_View_Interface $view
0236      * @return string
0237      */
0238     public function render(Zend_View_Interface $view = null)
0239     {
0240         $this->initCsrfToken();
0241         return parent::render($view);
0242     }
0243 
0244     /**
0245      * Generate CSRF token
0246      *
0247      * Generates CSRF token and stores both in {@link $_hash} and element
0248      * value.
0249      *
0250      * @return void
0251      */
0252     protected function _generateHash()
0253     {
0254         $this->_hash = md5(
0255             Zend_Crypt_Math::randBytes(32)
0256         );
0257         $this->setValue($this->_hash);
0258     }
0259 }