File indexing completed on 2024-05-12 05:58:46

0001 <?php
0002 
0003 /**
0004  *  ocs-webserver
0005  *
0006  *  Copyright 2016 by pling GmbH.
0007  *
0008  *    This file is part of ocs-webserver.
0009  *
0010  *    This program is free software: you can redistribute it and/or modify
0011  *    it under the terms of the GNU Affero General Public License as
0012  *    published by the Free Software Foundation, either version 3 of the
0013  *    License, or (at your option) any later version.
0014  *
0015  *    This program is distributed in the hope that it will be useful,
0016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  *    GNU Affero General Public License for more details.
0019  *
0020  *    You should have received a copy of the GNU Affero General Public License
0021  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  **/
0023 class Default_Model_CsrfProtection
0024 {
0025     const validity = 3600;
0026 
0027     /**
0028      * @param Zend_Form $form
0029      * @param string    $csrf_salt_name
0030      * @param string    $field_name
0031      *
0032      * @return Zend_Form_Element
0033      * @throws Zend_Form_Exception
0034      * @throws Zend_Session_Exception
0035      */
0036     public static function createCsrf($form, $csrf_salt_name, $field_name = "csrf")
0037     {
0038         /** @var Zend_Form_Element_Hash $element */
0039         $element = $form->createElement('hash', $field_name, array(
0040             'salt' => $csrf_salt_name
0041         ));
0042         //Create unique ID if you need to use some Javascript on the CSRF Element
0043         $element->setAttrib('id', $form->getName() . '_' . $element->getId());
0044         $element->setDecorators(array('ViewHelper'));
0045         $element->setSession(new Zend_Session_Namespace('login_csrf'));
0046         $form->addElement($element);
0047 
0048         return $element;
0049     }
0050 
0051     /**
0052      * @param $hash
0053      *
0054      * @return bool
0055      * @throws Zend_Exception
0056      * @throws Zend_Session_Exception
0057      */
0058     public static function validateCsrfToken($hash)
0059     {
0060         $session = new Zend_Session_Namespace();
0061 
0062         if (false === function_exists("hash_equals")) {
0063             $valid = self::hash_equals($session->crsf_token, $hash);
0064             Zend_Registry::get('logger')->debug(__METHOD__
0065                 . PHP_EOL . ' - session csrf token: ' . print_r($session->crsf_token, true)
0066                 . PHP_EOL . ' - form csrf token: ' . print_r($hash, true)
0067                 . PHP_EOL . ' - crsf validation result: ' . (($valid === true) ? 'true' : 'false'));
0068 
0069             return $valid;
0070         }
0071 
0072         if (empty($session->crsf_token)) {
0073             return false;
0074         }
0075         $valid = hash_equals($session->crsf_token, $hash);
0076         Zend_Registry::get('logger')->debug(__METHOD__
0077                 . PHP_EOL . ' - session csrf token: ' . print_r($session->crsf_token, true)
0078                 . PHP_EOL . ' - form csrf token: ' . print_r($hash, true)
0079                 . PHP_EOL . ' - crsf validation result: ' . (($valid === true) ? 'true' : 'false'));
0080 
0081         return $valid;
0082     }
0083 
0084     /**
0085      * @param $a
0086      * @param $b
0087      *
0088      * @return bool
0089      * @author http://php.net/manual/en/function.hash-equals.php#usernotes  Cedric Van Bockhaven
0090      */
0091     private static function hash_equals($a, $b)
0092     {
0093         $ret = strlen($a) ^ strlen($b);
0094         $ret |= array_sum(unpack("C*", $a ^ $b));
0095 
0096         return !$ret;
0097     }
0098 
0099     /**
0100      * @return Zend_Form_Element_Hidden
0101      * @throws Zend_Form_Exception
0102      * @throws Zend_Session_Exception
0103      */
0104     public static function getFormCsrf($name = 'crsf_token')
0105     {
0106         $form_crsf = new Zend_Form_Element_Hidden($name);
0107         $form_crsf->setFilters(array('StringTrim'));
0108         $form_crsf->setRequired(true);
0109         $form_crsf->setDecorators(array('ViewHelper'));
0110         $form_crsf->setValue(self::getCsrfToken());
0111 
0112         return $form_crsf;
0113     }
0114 
0115     /**
0116      * @return mixed|string
0117      * @throws Zend_Session_Exception
0118      */
0119     public static function getCsrfToken()
0120     {
0121         $session = new Zend_Session_Namespace();
0122         if ($session->crsf_token AND $session->crsf_expire AND ($session->crsf_expire > microtime(true))) {
0123             return $session->crsf_token;
0124         }
0125         $session->crsf_expire = microtime(true) + self::validity;
0126         if (function_exists('mcrypt_create_iv')) {
0127             $session->crsf_token = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
0128         } else {
0129             $session->crsf_token = bin2hex(openssl_random_pseudo_bytes(32));
0130         }
0131 
0132         return $session->crsf_token;
0133     }
0134 
0135 }