Patched to Drupal 8.4.8 level. See https://www.drupal.org/sa-core-2018-004 and patch...
[yaffs-website] / web / core / lib / Drupal / Core / Access / CsrfTokenGenerator.php
1 <?php
2
3 namespace Drupal\Core\Access;
4
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\PrivateKey;
7 use Drupal\Core\Session\MetadataBag;
8 use Drupal\Core\Site\Settings;
9
10 /**
11  * Generates and validates CSRF tokens.
12  *
13  * @see \Drupal\Tests\Core\Access\CsrfTokenGeneratorTest
14  */
15 class CsrfTokenGenerator {
16
17   /**
18    * The private key service.
19    *
20    * @var \Drupal\Core\PrivateKey
21    */
22   protected $privateKey;
23
24   /**
25    * The session metadata bag.
26    *
27    * @var \Drupal\Core\Session\MetadataBag
28    */
29   protected $sessionMetadata;
30
31   /**
32    * Constructs the token generator.
33    *
34    * @param \Drupal\Core\PrivateKey $private_key
35    *   The private key service.
36    * @param \Drupal\Core\Session\MetadataBag $session_metadata
37    *   The session metadata bag.
38    */
39   public function __construct(PrivateKey $private_key, MetadataBag $session_metadata) {
40     $this->privateKey = $private_key;
41     $this->sessionMetadata = $session_metadata;
42   }
43
44   /**
45    * Generates a token based on $value, the user session, and the private key.
46    *
47    * The generated token is based on the session of the current user. Normally,
48    * anonymous users do not have a session, so the generated token will be
49    * different on every page request. To generate a token for users without a
50    * session, manually start a session prior to calling this function.
51    *
52    * @param string $value
53    *   (optional) An additional value to base the token on.
54    *
55    * @return string
56    *   A 43-character URL-safe token for validation, based on the token seed,
57    *   the hash salt provided by Settings::getHashSalt(), and the
58    *   'drupal_private_key' configuration variable.
59    *
60    * @see \Drupal\Core\Site\Settings::getHashSalt()
61    * @see \Symfony\Component\HttpFoundation\Session\SessionInterface::start()
62    */
63   public function get($value = '') {
64     $seed = $this->sessionMetadata->getCsrfTokenSeed();
65     if (empty($seed)) {
66       $seed = Crypt::randomBytesBase64();
67       $this->sessionMetadata->setCsrfTokenSeed($seed);
68     }
69
70     return $this->computeToken($seed, $value);
71   }
72
73   /**
74    * Validates a token based on $value, the user session, and the private key.
75    *
76    * @param string $token
77    *   The token to be validated.
78    * @param string $value
79    *   (optional) An additional value to base the token on.
80    *
81    * @return bool
82    *   TRUE for a valid token, FALSE for an invalid token.
83    */
84   public function validate($token, $value = '') {
85     $seed = $this->sessionMetadata->getCsrfTokenSeed();
86     if (empty($seed)) {
87       return FALSE;
88     }
89
90     return Crypt::hashEquals($this->computeToken($seed, $value), $token);
91   }
92
93   /**
94    * Generates a token based on $value, the token seed, and the private key.
95    *
96    * @param string $seed
97    *   The per-session token seed.
98    * @param string $value
99    *   (optional) An additional value to base the token on.
100    *
101    * @return string
102    *   A 43-character URL-safe token for validation, based on the token seed,
103    *   the hash salt provided by Settings::getHashSalt(), and the
104    *   'drupal_private_key' configuration variable.
105    *
106    * @see \Drupal\Core\Site\Settings::getHashSalt()
107    */
108   protected function computeToken($seed, $value = '') {
109     return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . Settings::getHashSalt());
110   }
111
112 }