Security update for Core, with self-updated composer
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Access / CsrfTokenGeneratorTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Access;
4
5 use Drupal\Core\Site\Settings;
6 use Drupal\Tests\UnitTestCase;
7 use Drupal\Core\Access\CsrfTokenGenerator;
8 use Drupal\Component\Utility\Crypt;
9
10 /**
11  * Tests the CsrfTokenGenerator class.
12  *
13  * @group Access
14  * @coversDefaultClass \Drupal\Core\Access\CsrfTokenGenerator
15  */
16 class CsrfTokenGeneratorTest extends UnitTestCase {
17
18   /**
19    * The CSRF token generator.
20    *
21    * @var \Drupal\Core\Access\CsrfTokenGenerator
22    */
23   protected $generator;
24
25   /**
26    * The mock private key instance.
27    *
28    * @var \Drupal\Core\PrivateKey|\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $privateKey;
31
32   /**
33    * The mock session metadata bag.
34    *
35    * @var \Drupal\Core\Session\MetadataBag|\PHPUnit_Framework_MockObject_MockObject
36    */
37   protected $sessionMetadata;
38
39   /**
40    * {@inheritdoc}
41    */
42   protected function setUp() {
43     parent::setUp();
44
45     $this->privateKey = $this->getMockBuilder('Drupal\Core\PrivateKey')
46       ->disableOriginalConstructor()
47       ->setMethods(['get'])
48       ->getMock();
49
50     $this->sessionMetadata = $this->getMockBuilder('Drupal\Core\Session\MetadataBag')
51       ->disableOriginalConstructor()
52       ->getMock();
53
54     $settings = [
55       'hash_salt' => $this->randomMachineName(),
56     ];
57
58     new Settings($settings);
59
60     $this->generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
61   }
62
63   /**
64    * Set up default expectations on the mocks.
65    */
66   protected function setupDefaultExpectations() {
67     $key = Crypt::randomBytesBase64();
68     $this->privateKey->expects($this->any())
69       ->method('get')
70       ->will($this->returnValue($key));
71
72     $seed = Crypt::randomBytesBase64();
73     $this->sessionMetadata->expects($this->any())
74       ->method('getCsrfTokenSeed')
75       ->will($this->returnValue($seed));
76   }
77
78   /**
79    * Tests CsrfTokenGenerator::get().
80    *
81    * @covers ::get
82    */
83   public function testGet() {
84     $this->setupDefaultExpectations();
85
86     $this->assertInternalType('string', $this->generator->get());
87     $this->assertNotSame($this->generator->get(), $this->generator->get($this->randomMachineName()));
88     $this->assertNotSame($this->generator->get($this->randomMachineName()), $this->generator->get($this->randomMachineName()));
89   }
90
91   /**
92    * Tests that a new token seed is generated upon first use.
93    *
94    * @covers ::get
95    */
96   public function testGenerateSeedOnGet() {
97     $key = Crypt::randomBytesBase64();
98     $this->privateKey->expects($this->any())
99       ->method('get')
100       ->will($this->returnValue($key));
101
102     $this->sessionMetadata->expects($this->once())
103       ->method('getCsrfTokenSeed')
104       ->will($this->returnValue(NULL));
105
106     $this->sessionMetadata->expects($this->once())
107       ->method('setCsrfTokenSeed')
108       ->with($this->isType('string'));
109
110     $this->assertInternalType('string', $this->generator->get());
111   }
112
113   /**
114    * Tests CsrfTokenGenerator::validate().
115    *
116    * @covers ::validate
117    */
118   public function testValidate() {
119     $this->setupDefaultExpectations();
120
121     $token = $this->generator->get();
122     $this->assertTrue($this->generator->validate($token));
123     $this->assertFalse($this->generator->validate($token, 'foo'));
124
125     $token = $this->generator->get('bar');
126     $this->assertTrue($this->generator->validate($token, 'bar'));
127   }
128
129   /**
130    * Tests CsrfTokenGenerator::validate() with different parameter types.
131    *
132    * @param mixed $token
133    *   The token to be validated.
134    * @param mixed $value
135    *   (optional) An additional value to base the token on.
136    *
137    * @covers ::validate
138    * @dataProvider providerTestValidateParameterTypes
139    */
140   public function testValidateParameterTypes($token, $value) {
141     $this->setupDefaultExpectations();
142
143     // The following check might throw PHP fatals and notices, so we disable
144     // error assertions.
145     set_error_handler(function () {
146       return TRUE;
147     });
148     $this->assertFalse($this->generator->validate($token, $value));
149     restore_error_handler();
150   }
151
152   /**
153    * Provides data for testValidateParameterTypes.
154    *
155    * @return array
156    *   An array of data used by the test.
157    */
158   public function providerTestValidateParameterTypes() {
159     return [
160       [[], ''],
161       [TRUE, 'foo'],
162       [0, 'foo'],
163     ];
164   }
165
166   /**
167    * Tests CsrfTokenGenerator::validate() with invalid parameter types.
168    *
169    * @param mixed $token
170    *   The token to be validated.
171    * @param mixed $value
172    *   (optional) An additional value to base the token on.
173    *
174    * @covers ::validate
175    * @dataProvider providerTestInvalidParameterTypes
176    */
177   public function testInvalidParameterTypes($token, $value = '') {
178     $this->setupDefaultExpectations();
179
180     $this->setExpectedException(\InvalidArgumentException::class);
181     $this->generator->validate($token, $value);
182   }
183
184   /**
185    * Provides data for testInvalidParameterTypes.
186    *
187    * @return array
188    *   An array of data used by the test.
189    */
190   public function providerTestInvalidParameterTypes() {
191     return [
192       [NULL, new \stdClass()],
193       [0, []],
194       ['', []],
195       [[], []],
196     ];
197   }
198
199   /**
200    * Tests the exception thrown when no 'hash_salt' is provided in settings.
201    *
202    * @covers ::get
203    */
204   public function testGetWithNoHashSalt() {
205     // Update settings with no hash salt.
206     new Settings([]);
207     $generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
208     $this->setExpectedException(\RuntimeException::class);
209     $generator->get();
210   }
211
212 }