summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2015-05-21 06:28:27 +0200
committerFabien Potencier <fabien.potencier@gmail.com>2015-05-21 06:28:27 +0200
commita3fffdc56ce7a29745d3dea4800058de1a4edd84 (patch)
treeaf7292249208a220c30f0ee8cacd8ddf989085ae
parenta9a1d5007c7157828e2f833964e7c54fd0b779a6 (diff)
parent51f245f2684a0a819dcaff815f401494e63a582d (diff)
downloadsymfony-security-a3fffdc56ce7a29745d3dea4800058de1a4edd84.zip
symfony-security-a3fffdc56ce7a29745d3dea4800058de1a4edd84.tar.gz
symfony-security-a3fffdc56ce7a29745d3dea4800058de1a4edd84.tar.bz2
bug #14678 [Security] AbstractRememberMeServices::encodeCookie() validates cookie parts (MacDada)
This PR was squashed before being merged into the 2.3 branch (closes #14678). Discussion ---------- [Security] AbstractRememberMeServices::encodeCookie() validates cookie parts | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #14577 | License | MIT | Doc PR | no `AbstractRememberMeServices::encodeCookie()` guards against `COOKIE_DELIMITER` in `$cookieParts`. * it would make `AbstractRememberMeServices::cookieDecode()` broken * all current extending classes do it anyway (see #14670 ) * added tests – it's not a public method, but it is expected to be used by user implementations – as such, it's good to know that it works properly Commits ------- 464c39a [Security] AbstractRememberMeServices::encodeCookie() validates cookie parts
-rw-r--r--Http/RememberMe/AbstractRememberMeServices.php8
-rw-r--r--Http/RememberMe/TokenBasedRememberMeServices.php4
-rw-r--r--Tests/Http/RememberMe/AbstractRememberMeServicesTest.php34
3 files changed, 42 insertions, 4 deletions
diff --git a/Http/RememberMe/AbstractRememberMeServices.php b/Http/RememberMe/AbstractRememberMeServices.php
index b14e36d..16f7831 100644
--- a/Http/RememberMe/AbstractRememberMeServices.php
+++ b/Http/RememberMe/AbstractRememberMeServices.php
@@ -268,9 +268,17 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
* @param array $cookieParts
*
* @return string
+ *
+ * @throws \InvalidArgumentException When $cookieParts contain the cookie delimiter. Extending class should either remove or escape it.
*/
protected function encodeCookie(array $cookieParts)
{
+ foreach ($cookieParts as $cookiePart) {
+ if (false !== strpos($cookiePart, self::COOKIE_DELIMITER)) {
+ throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s"', self::COOKIE_DELIMITER));
+ }
+ }
+
return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts));
}
diff --git a/Http/RememberMe/TokenBasedRememberMeServices.php b/Http/RememberMe/TokenBasedRememberMeServices.php
index 3d2cf12..a129b1d 100644
--- a/Http/RememberMe/TokenBasedRememberMeServices.php
+++ b/Http/RememberMe/TokenBasedRememberMeServices.php
@@ -119,8 +119,6 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
* @param int $expires The Unix timestamp when the cookie expires
* @param string $password The encoded password
*
- * @throws \RuntimeException if username contains invalid chars
- *
* @return string
*/
protected function generateCookieValue($class, $username, $expires, $password)
@@ -141,8 +139,6 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices
* @param int $expires The Unix timestamp when the cookie expires
* @param string $password The encoded password
*
- * @throws \RuntimeException when the private key is empty
- *
* @return string
*/
protected function generateCookieHash($class, $username, $expires, $password)
diff --git a/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php b/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
index 0f64730..70ff6a0 100644
--- a/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
+++ b/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Tests\Http\RememberMe;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices;
class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
{
@@ -236,6 +237,30 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
);
}
+ public function testEncodeCookieAndDecodeCookieAreInvertible()
+ {
+ $cookieParts = array('aa', 'bb', 'cc');
+ $service = $this->getService();
+
+ $encoded = $this->callProtected($service, 'encodeCookie', array($cookieParts));
+ $this->assertInternalType('string', $encoded);
+
+ $decoded = $this->callProtected($service, 'decodeCookie', array($encoded));
+ $this->assertSame($cookieParts, $decoded);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage cookie delimiter
+ */
+ public function testThereShouldBeNoCookieDelimiterInCookieParts()
+ {
+ $cookieParts = array('aa', 'b'.AbstractRememberMeServices::COOKIE_DELIMITER.'b', 'cc');
+ $service = $this->getService();
+
+ $this->callProtected($service, 'encodeCookie', array($cookieParts));
+ }
+
protected function getService($userProvider = null, $options = array(), $logger = null)
{
if (null === $userProvider) {
@@ -258,4 +283,13 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase
return $provider;
}
+
+ private function callProtected($object, $method, array $args)
+ {
+ $reflection = new \ReflectionClass(get_class($object));
+ $reflectionMethod = $reflection->getMethod($method);
+ $reflectionMethod->setAccessible(true);
+
+ return $reflectionMethod->invokeArgs($object, $args);
+ }
}