diff --git a/core/lib/Drupal/Component/Utility/Crypt.php b/core/lib/Drupal/Component/Utility/Crypt.php index 7144e3b549909d0fbd1acfac7f4810e67d2c322a..6d101c2b56b12d958e799517a44de90ef176a083 100644 --- a/core/lib/Drupal/Component/Utility/Crypt.php +++ b/core/lib/Drupal/Component/Utility/Crypt.php @@ -81,7 +81,11 @@ public static function randomBytes($count) { * any = padding characters removed. */ public static function hmacBase64($data, $key) { - $hmac = base64_encode(hash_hmac('sha256', $data, $key, TRUE)); + // Casting $data and $key to strings here is necessary to avoid empty string + // results of the hash function if they are not scalar values. As this + // function is used in security-critical contexts like token validation it is + // important that it never returns an empty string. + $hmac = base64_encode(hash_hmac('sha256', (string) $data, (string) $key, TRUE)); // Modify the hmac so it's safe to use in URLs. return strtr($hmac, array('+' => '-', '/' => '_', '=' => '')); } diff --git a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php index b74c05d8b4309a40b84834ac6554244944fb731f..f2b015cfb2becd836caf16cb100498736fb360c1 100644 --- a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php +++ b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php @@ -84,7 +84,7 @@ public function get($value = '') { * is TRUE, the return value will always be TRUE for anonymous users. */ public function validate($token, $value = '', $skip_anonymous = FALSE) { - return ($skip_anonymous && $this->currentUser->isAnonymous()) || ($token == $this->get($value)); + return ($skip_anonymous && $this->currentUser->isAnonymous()) || ($token === $this->get($value)); } } diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php index 5b823a2a1bc336149697e4520c72955d060fb839..0db8f21438952320e84d349d1b751992cb160274 100644 --- a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php +++ b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php @@ -90,6 +90,43 @@ public function testValidate() { $this->assertFalse($this->generator->validate($token, 'foo', TRUE)); } + /** + * Tests CsrfTokenGenerator::validate() with different parameter types. + * + * @param mixed $token + * The token to be validated. + * @param mixed $value + * (optional) An additional value to base the token on. + * @param mixed $expected + * (optional) The expected result of validate(). Defaults to FALSE. + * + * @dataProvider providerTestValidateParameterTypes + */ + public function testValidateParameterTypes($token, $value = '', $expected = FALSE) { + // The following check might throw PHP fatals and notices, so we disable + // error assertions. + set_error_handler(function () {return TRUE;}); + $this->assertSame($expected, $this->generator->validate($token, $value)); + restore_error_handler(); + } + + /** + * Provides data for the validate test. + * + * @return array + * An array of data used by the test. + */ + public function providerTestValidateParameterTypes() { + return array( + array(NULL, new \stdClass()), + array(0, array()), + array('', array()), + array(array()), + array(TRUE, 'foo'), + array(0, 'foo'), + ); + } + } }