summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2013-10-10 08:30:51 +0200
committerFabien Potencier <fabien.potencier@gmail.com>2013-10-10 14:05:52 +0200
commit41cbe3694a5332d7e5bdb285c81bbfe23f31a220 (patch)
tree48b09420b041421ce1ee3e35d21d98ab11e7d793
parente3a08775fbfb1062167a56e3c5f606b3300d40a8 (diff)
downloadsymfony-security-41cbe3694a5332d7e5bdb285c81bbfe23f31a220.zip
symfony-security-41cbe3694a5332d7e5bdb285c81bbfe23f31a220.tar.gz
symfony-security-41cbe3694a5332d7e5bdb285c81bbfe23f31a220.tar.bz2
[Security] limited the password length passed to encodersv2.2.9
-rw-r--r--Core/Encoder/BCryptPasswordEncoder.php9
-rw-r--r--Core/Encoder/BasePasswordEncoder.php12
-rw-r--r--Core/Encoder/MessageDigestPasswordEncoder.php8
-rw-r--r--Core/Encoder/Pbkdf2PasswordEncoder.php8
-rw-r--r--Core/Encoder/PlaintextPasswordEncoder.php10
-rw-r--r--Tests/Core/Encoder/BCryptPasswordEncoderTest.php17
-rw-r--r--Tests/Core/Encoder/BasePasswordEncoderTest.php16
-rw-r--r--Tests/Core/Encoder/MessageDigestPasswordEncoderTest.php17
-rw-r--r--Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php17
-rw-r--r--Tests/Core/Encoder/PlaintextPasswordEncoderTest.php17
10 files changed, 129 insertions, 2 deletions
diff --git a/Core/Encoder/BCryptPasswordEncoder.php b/Core/Encoder/BCryptPasswordEncoder.php
index 1b7572d..c14cdff 100644
--- a/Core/Encoder/BCryptPasswordEncoder.php
+++ b/Core/Encoder/BCryptPasswordEncoder.php
@@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Core\Encoder;
use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
use Symfony\Component\Security\Core\Util\SecureRandomInterface;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
/**
* @author Elnur Abdurrakhimov <elnur@elnur.pro>
@@ -60,6 +61,10 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
*/
public function encodePassword($raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ throw new BadCredentialsException('Invalid password.');
+ }
+
if (function_exists('password_hash')) {
return password_hash($raw, PASSWORD_BCRYPT, array('cost' => $this->cost));
}
@@ -78,6 +83,10 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
*/
public function isPasswordValid($encoded, $raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ return false;
+ }
+
if (function_exists('password_verify')) {
return password_verify($raw, $encoded);
}
diff --git a/Core/Encoder/BasePasswordEncoder.php b/Core/Encoder/BasePasswordEncoder.php
index c26c9ce..b83eb30 100644
--- a/Core/Encoder/BasePasswordEncoder.php
+++ b/Core/Encoder/BasePasswordEncoder.php
@@ -20,6 +20,8 @@ use Symfony\Component\Security\Core\Util\StringUtils;
*/
abstract class BasePasswordEncoder implements PasswordEncoderInterface
{
+ const MAX_PASSWORD_LENGTH = 4096;
+
/**
* Demerges a merge password and salt string.
*
@@ -83,4 +85,14 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface
{
return StringUtils::equals($password1, $password2);
}
+
+ /**
+ * Checks if the password is too long.
+ *
+ * @return Boolean true if the password is too long, false otherwise
+ */
+ protected function isPasswordTooLong($password)
+ {
+ return strlen($password) > self::MAX_PASSWORD_LENGTH;
+ }
}
diff --git a/Core/Encoder/MessageDigestPasswordEncoder.php b/Core/Encoder/MessageDigestPasswordEncoder.php
index a8bd553..a7e5546 100644
--- a/Core/Encoder/MessageDigestPasswordEncoder.php
+++ b/Core/Encoder/MessageDigestPasswordEncoder.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Core\Encoder;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+
/**
* MessageDigestPasswordEncoder uses a message digest algorithm.
*
@@ -41,6 +43,10 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder
*/
public function encodePassword($raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ throw new BadCredentialsException('Invalid password.');
+ }
+
if (!in_array($this->algorithm, hash_algos(), true)) {
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
}
@@ -61,6 +67,6 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder
*/
public function isPasswordValid($encoded, $raw, $salt)
{
- return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
+ return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
}
}
diff --git a/Core/Encoder/Pbkdf2PasswordEncoder.php b/Core/Encoder/Pbkdf2PasswordEncoder.php
index 656545f..511a161 100644
--- a/Core/Encoder/Pbkdf2PasswordEncoder.php
+++ b/Core/Encoder/Pbkdf2PasswordEncoder.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Core\Encoder;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+
/**
* Pbkdf2PasswordEncoder uses the PBKDF2 (Password-Based Key Derivation Function 2).
*
@@ -54,6 +56,10 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
*/
public function encodePassword($raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ throw new BadCredentialsException('Invalid password.');
+ }
+
if (!in_array($this->algorithm, hash_algos(), true)) {
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
}
@@ -72,7 +78,7 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder
*/
public function isPasswordValid($encoded, $raw, $salt)
{
- return $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
+ return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
}
private function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0)
diff --git a/Core/Encoder/PlaintextPasswordEncoder.php b/Core/Encoder/PlaintextPasswordEncoder.php
index c21f3cd..22f3da4 100644
--- a/Core/Encoder/PlaintextPasswordEncoder.php
+++ b/Core/Encoder/PlaintextPasswordEncoder.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Core\Encoder;
+use Symfony\Component\Security\Core\Exception\BadCredentialsException;
+
/**
* PlaintextPasswordEncoder does not do any encoding.
*
@@ -35,6 +37,10 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder
*/
public function encodePassword($raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ throw new BadCredentialsException('Invalid password.');
+ }
+
return $this->mergePasswordAndSalt($raw, $salt);
}
@@ -43,6 +49,10 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder
*/
public function isPasswordValid($encoded, $raw, $salt)
{
+ if ($this->isPasswordTooLong($raw)) {
+ return false;
+ }
+
$pass2 = $this->mergePasswordAndSalt($raw, $salt);
if (!$this->ignorePasswordCase) {
diff --git a/Tests/Core/Encoder/BCryptPasswordEncoderTest.php b/Tests/Core/Encoder/BCryptPasswordEncoderTest.php
index bfaf5fc..0b368bf 100644
--- a/Tests/Core/Encoder/BCryptPasswordEncoderTest.php
+++ b/Tests/Core/Encoder/BCryptPasswordEncoderTest.php
@@ -109,4 +109,21 @@ class BCryptPasswordEncoderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected, $result);
}
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST);
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new BCryptPasswordEncoder($this->secureRandom, self::VALID_COST);
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
}
diff --git a/Tests/Core/Encoder/BasePasswordEncoderTest.php b/Tests/Core/Encoder/BasePasswordEncoderTest.php
index 2ef1dcc..762f6ab 100644
--- a/Tests/Core/Encoder/BasePasswordEncoderTest.php
+++ b/Tests/Core/Encoder/BasePasswordEncoderTest.php
@@ -53,6 +53,12 @@ class BasePasswordEncoderTest extends \PHPUnit_Framework_TestCase
$this->invokeMergePasswordAndSalt('password', '{foo}');
}
+ public function testIsPasswordTooLong()
+ {
+ $this->assertTrue($this->invokeIsPasswordTooLong(str_repeat('a', 10000)));
+ $this->assertFalse($this->invokeIsPasswordTooLong(str_repeat('a', 10)));
+ }
+
protected function invokeDemergePasswordAndSalt($password)
{
$encoder = new PasswordEncoder();
@@ -82,4 +88,14 @@ class BasePasswordEncoderTest extends \PHPUnit_Framework_TestCase
return $m->invoke($encoder, $p1, $p2);
}
+
+ protected function invokeIsPasswordTooLong($p)
+ {
+ $encoder = new PasswordEncoder();
+ $r = new \ReflectionObject($encoder);
+ $m = $r->getMethod('isPasswordTooLong');
+ $m->setAccessible(true);
+
+ return $m->invoke($encoder, $p);
+ }
}
diff --git a/Tests/Core/Encoder/MessageDigestPasswordEncoderTest.php b/Tests/Core/Encoder/MessageDigestPasswordEncoderTest.php
index 64032c4..117b8ba 100644
--- a/Tests/Core/Encoder/MessageDigestPasswordEncoderTest.php
+++ b/Tests/Core/Encoder/MessageDigestPasswordEncoderTest.php
@@ -42,4 +42,21 @@ class MessageDigestPasswordEncoderTest extends \PHPUnit_Framework_TestCase
$encoder = new MessageDigestPasswordEncoder('foobar');
$encoder->encodePassword('password', '');
}
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new MessageDigestPasswordEncoder();
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new MessageDigestPasswordEncoder();
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
}
diff --git a/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php b/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php
index 2c98543..e303708 100644
--- a/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php
+++ b/Tests/Core/Encoder/Pbkdf2PasswordEncoderTest.php
@@ -42,4 +42,21 @@ class Pbkdf2PasswordEncoderTest extends \PHPUnit_Framework_TestCase
$encoder = new Pbkdf2PasswordEncoder('foobar');
$encoder->encodePassword('password', '');
}
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('foobar');
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new Pbkdf2PasswordEncoder('foobar');
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
}
diff --git a/Tests/Core/Encoder/PlaintextPasswordEncoderTest.php b/Tests/Core/Encoder/PlaintextPasswordEncoderTest.php
index af0008f..8b1b888 100644
--- a/Tests/Core/Encoder/PlaintextPasswordEncoderTest.php
+++ b/Tests/Core/Encoder/PlaintextPasswordEncoderTest.php
@@ -36,4 +36,21 @@ class PlaintextPasswordEncoderTest extends \PHPUnit_Framework_TestCase
$this->assertSame('foo', $encoder->encodePassword('foo', ''));
}
+
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
+ */
+ public function testEncodePasswordLength()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $encoder->encodePassword(str_repeat('a', 5000), 'salt');
+ }
+
+ public function testCheckPasswordLength()
+ {
+ $encoder = new PlaintextPasswordEncoder();
+
+ $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), 'salt'));
+ }
}