summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Grekas <nicolas.grekas@gmail.com>2015-03-30 10:41:59 +0200
committerNicolas Grekas <nicolas.grekas@gmail.com>2015-03-30 10:41:59 +0200
commit05006144a36061d7a30ac4522e24f1b0a1ac82b6 (patch)
tree002375d131dcafcb932af718c35b35ec58019301
parent2e43dea46f12839ed7131d459390c5bcf9f4cb77 (diff)
parent02b20eccaf64c7c3c138f89e91f0a83c90cebfa2 (diff)
downloadsymfony-security-05006144a36061d7a30ac4522e24f1b0a1ac82b6.zip
symfony-security-05006144a36061d7a30ac4522e24f1b0a1ac82b6.tar.gz
symfony-security-05006144a36061d7a30ac4522e24f1b0a1ac82b6.tar.bz2
Merge branch '2.7'
* 2.7: (29 commits) [Validator] Added missing Hungarian translation remove usage of deprecated class Fix merge Fix merge CS: fixes [Translation][Extractor] Allow extracting an array of files besides extracting a directory [VarDumper] Fix dumping ThrowingCasterException [Console][Table] Add support for colspan/rowspan + multiple header lines Translator component has default domain for null implemented no need to have default translation domain logic in 3 different places Displays friendly message if the event does not have any registered listeners [VarDumper] Ctrl+click toggles-all and fix IE8 support Implemented check on interface implementation [Form] [TwigBridge] Bootstrap layout whitespace control |Validator] Add PHPUnit hint in AbstractConstraintValidatorTest [VarDumper] implement expand all on ALT+click [WebProfilerBundle] Fixed collapsed profiler menu icons [travis] Kill tests when a new commit has been pushed fixed CS Change behavior to mirror hash_equals() returning early if there is a length mismatch CS fixing ... Conflicts: src/Symfony/Bridge/Twig/composer.json src/Symfony/Bundle/FrameworkBundle/composer.json src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php
-rw-r--r--Core/Authentication/AuthenticationProviderManager.php6
-rw-r--r--Core/Tests/Authentication/AuthenticationProviderManagerTest.php10
-rw-r--r--Core/Util/StringUtils.php49
-rw-r--r--Http/RememberMe/TokenBasedRememberMeServices.php2
4 files changed, 55 insertions, 12 deletions
diff --git a/Core/Authentication/AuthenticationProviderManager.php b/Core/Authentication/AuthenticationProviderManager.php
index f713e8f..16de8da 100644
--- a/Core/Authentication/AuthenticationProviderManager.php
+++ b/Core/Authentication/AuthenticationProviderManager.php
@@ -48,6 +48,12 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface
throw new \InvalidArgumentException('You must at least add one authentication provider.');
}
+ foreach ($providers as $provider) {
+ if (!$provider instanceof AuthenticationProviderInterface) {
+ throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_class($provider)));
+ }
+ }
+
$this->providers = $providers;
$this->eraseCredentials = (bool) $eraseCredentials;
}
diff --git a/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
index df25874..cc8b7c0 100644
--- a/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
+++ b/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
@@ -27,6 +27,16 @@ class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase
new AuthenticationProviderManager(array());
}
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testAuthenticateWithProvidersWithIncorrectInterface()
+ {
+ new AuthenticationProviderManager(array(
+ new \stdClass(),
+ ));
+ }
+
public function testAuthenticateWhenNoProviderSupportsToken()
{
$manager = new AuthenticationProviderManager(array(
diff --git a/Core/Util/StringUtils.php b/Core/Util/StringUtils.php
index e8f3e3b..e68347f 100644
--- a/Core/Util/StringUtils.php
+++ b/Core/Util/StringUtils.php
@@ -38,29 +38,56 @@ class StringUtils
*/
public static function equals($knownString, $userInput)
{
- $knownString = (string) $knownString;
- $userInput = (string) $userInput;
+ // Avoid making unnecessary duplications of secret data
+ if (!is_string($knownString)) {
+ $knownString = (string) $knownString;
+ }
+
+ if (!is_string($userInput)) {
+ $userInput = (string) $userInput;
+ }
if (function_exists('hash_equals')) {
return hash_equals($knownString, $userInput);
}
- $knownLen = strlen($knownString);
- $userLen = strlen($userInput);
+ $knownLen = self::safeStrlen($knownString);
+ $userLen = self::safeStrlen($userInput);
- // Extend the known string to avoid uninitialized string offsets
- $knownString .= $userInput;
+ if ($userLen !== $knownLen) {
+ return false;
+ }
- // Set the result to the difference between the lengths
- $result = $knownLen - $userLen;
+ $result = 0;
- // Note that we ALWAYS iterate over the user-supplied length
- // This is to mitigate leaking length information
- for ($i = 0; $i < $userLen; $i++) {
+ for ($i = 0; $i < $knownLen; $i++) {
$result |= (ord($knownString[$i]) ^ ord($userInput[$i]));
}
// They are only identical strings if $result is exactly 0...
return 0 === $result;
}
+
+ /**
+ * Returns the number of bytes in a string.
+ *
+ * @param string $string The string whose length we wish to obtain
+ *
+ * @return int
+ */
+ public static function safeStrlen($string)
+ {
+ // Premature optimization
+ // Since this cannot be changed at runtime, we can cache it
+ static $funcExists = null;
+ if (null === $funcExists) {
+ $funcExists = function_exists('mb_strlen');
+ }
+
+ if ($funcExists) {
+ return mb_strlen($string, '8bit');
+ }
+
+ return strlen($string);
+ }
}
diff --git a/Http/RememberMe/TokenBasedRememberMeServices.php b/Http/RememberMe/TokenBasedRememberMeServices.php
index 9042963..3fe39ac 100644
--- a/Http/RememberMe/TokenBasedRememberMeServices.php
+++ b/Http/RememberMe/TokenBasedRememberMeServices.php
@@ -54,7 +54,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
throw new \RuntimeException(sprintf('The UserProviderInterface implementation must return an instance of UserInterface, but returned "%s".', get_class($user)));
}
- if (true !== StringUtils::equals($hash, $this->generateCookieHash($class, $username, $expires, $user->getPassword()))) {
+ if (true !== StringUtils::equals($this->generateCookieHash($class, $username, $expires, $user->getPassword()), $hash)) {
throw new AuthenticationException('The cookie\'s hash is invalid.');
}