PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/www/libs/Zend/Validator/Csrf.php

https://bitbucket.org/Ppito/kawaiviewmodel2
PHP | 316 lines | 184 code | 26 blank | 106 comment | 11 complexity | 46a4e0c057334c891cf743515bfa6221 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Validator
  9. */
  10. namespace Zend\Validator;
  11. use Traversable;
  12. use Zend\Math\Rand;
  13. use Zend\Session\Container as SessionContainer;
  14. use Zend\Stdlib\ArrayUtils;
  15. class Csrf extends AbstractValidator
  16. {
  17. /**
  18. * Error codes
  19. * @const string
  20. */
  21. const NOT_SAME = 'notSame';
  22. /**
  23. * Error messages
  24. * @var array
  25. */
  26. protected $messageTemplates = array(
  27. self::NOT_SAME => "The form submitted did not originate from the expected site",
  28. );
  29. /**
  30. * Actual hash used.
  31. *
  32. * @var mixed
  33. */
  34. protected $hash;
  35. /**
  36. * Static cache of the session names to generated hashes
  37. *
  38. * @var array
  39. */
  40. protected static $hashCache;
  41. /**
  42. * Name of CSRF element (used to create non-colliding hashes)
  43. *
  44. * @var string
  45. */
  46. protected $name = 'csrf';
  47. /**
  48. * Salt for CSRF token
  49. * @var string
  50. */
  51. protected $salt = 'salt';
  52. /**
  53. * @var SessionContainer
  54. */
  55. protected $session;
  56. /**
  57. * TTL for CSRF token
  58. * @var int|null
  59. */
  60. protected $timeout = 300;
  61. /**
  62. * Constructor
  63. *
  64. * @param array|Traversable $options
  65. */
  66. public function __construct($options = array())
  67. {
  68. parent::__construct($options);
  69. if ($options instanceof Traversable) {
  70. $options = ArrayUtils::iteratorToArray($options);
  71. }
  72. if (!is_array($options)) {
  73. $options = (array) $options;
  74. }
  75. foreach ($options as $key => $value) {
  76. switch (strtolower($key)) {
  77. case 'name':
  78. $this->setName($value);
  79. break;
  80. case 'salt':
  81. $this->setSalt($value);
  82. break;
  83. case 'session':
  84. $this->setSession($value);
  85. break;
  86. case 'timeout':
  87. $this->setTimeout($value);
  88. break;
  89. default:
  90. // ignore unknown options
  91. break;
  92. }
  93. }
  94. }
  95. /**
  96. * Does the provided token match the one generated?
  97. *
  98. * @param string $value
  99. * @param mixed $context
  100. * @return bool
  101. */
  102. public function isValid($value, $context = null)
  103. {
  104. $this->setValue((string) $value);
  105. $hash = $this->getValidationToken();
  106. if ($value !== $hash) {
  107. $this->error(self::NOT_SAME);
  108. return false;
  109. }
  110. return true;
  111. }
  112. /**
  113. * Set CSRF name
  114. *
  115. * @param string $name
  116. * @return Csrf
  117. */
  118. public function setName($name)
  119. {
  120. $this->name = (string) $name;
  121. return $this;
  122. }
  123. /**
  124. * Get CSRF name
  125. *
  126. * @return string
  127. */
  128. public function getName()
  129. {
  130. return $this->name;
  131. }
  132. /**
  133. * Set session container
  134. *
  135. * @param SessionContainer $session
  136. * @return Csrf
  137. */
  138. public function setSession(SessionContainer $session)
  139. {
  140. $this->session = $session;
  141. if ($this->hash) {
  142. $this->initCsrfToken();
  143. }
  144. return $this;
  145. }
  146. /**
  147. * Get session container
  148. *
  149. * Instantiate session container if none currently exists
  150. *
  151. * @return SessionContainer
  152. */
  153. public function getSession()
  154. {
  155. if (null === $this->session) {
  156. $this->session = new SessionContainer($this->getSessionName());
  157. }
  158. return $this->session;
  159. }
  160. /**
  161. * Salt for CSRF token
  162. *
  163. * @param string $salt
  164. * @return Csrf
  165. */
  166. public function setSalt($salt)
  167. {
  168. $this->salt = (string) $salt;
  169. return $this;
  170. }
  171. /**
  172. * Retrieve salt for CSRF token
  173. *
  174. * @return string
  175. */
  176. public function getSalt()
  177. {
  178. return $this->salt;
  179. }
  180. /**
  181. * Retrieve CSRF token
  182. *
  183. * If no CSRF token currently exists, or should be regenerated,
  184. * generates one.
  185. *
  186. * @param bool $regenerate default false
  187. * @return string
  188. */
  189. public function getHash($regenerate = false)
  190. {
  191. if ((null === $this->hash) || $regenerate) {
  192. if ($regenerate) {
  193. $this->hash = null;
  194. } else {
  195. $this->hash = $this->getValidationToken();
  196. }
  197. if (null === $this->hash) {
  198. $this->generateHash();
  199. }
  200. }
  201. return $this->hash;
  202. }
  203. /**
  204. * Get session namespace for CSRF token
  205. *
  206. * Generates a session namespace based on salt, element name, and class.
  207. *
  208. * @return string
  209. */
  210. public function getSessionName()
  211. {
  212. return str_replace('\\', '_', __CLASS__) . '_'
  213. . $this->getSalt() . '_'
  214. . strtr($this->getName(), array('[' => '_', ']' => ''));
  215. }
  216. /**
  217. * Set timeout for CSRF session token
  218. *
  219. * @param int|null $ttl
  220. * @return Csrf
  221. */
  222. public function setTimeout($ttl)
  223. {
  224. $this->timeout = ($ttl !== null) ? (int) $ttl : null;
  225. return $this;
  226. }
  227. /**
  228. * Get CSRF session token timeout
  229. *
  230. * @return int
  231. */
  232. public function getTimeout()
  233. {
  234. return $this->timeout;
  235. }
  236. /**
  237. * Initialize CSRF token in session
  238. *
  239. * @return void
  240. */
  241. protected function initCsrfToken()
  242. {
  243. $session = $this->getSession();
  244. //$session->setExpirationHops(1, null, true);
  245. $timeout = $this->getTimeout();
  246. if (null !== $timeout) {
  247. $session->setExpirationSeconds($timeout);
  248. }
  249. $session->hash = $this->getHash();
  250. }
  251. /**
  252. * Generate CSRF token
  253. *
  254. * Generates CSRF token and stores both in {@link $hash} and element
  255. * value.
  256. *
  257. * @return void
  258. */
  259. protected function generateHash()
  260. {
  261. if (isset(static::$hashCache[$this->getSessionName()])) {
  262. $this->hash = static::$hashCache[$this->getSessionName()];
  263. } else {
  264. $this->hash = md5($this->getSalt() . Rand::getBytes(32) . $this->getName());
  265. static::$hashCache[$this->getSessionName()] = $this->hash;
  266. }
  267. $this->setValue($this->hash);
  268. $this->initCsrfToken();
  269. }
  270. /**
  271. * Get validation token
  272. *
  273. * Retrieve token from session, if it exists.
  274. *
  275. * @return null|string
  276. */
  277. protected function getValidationToken()
  278. {
  279. $session = $this->getSession();
  280. if (isset($session->hash)) {
  281. return $session->hash;
  282. }
  283. return null;
  284. }
  285. }