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
This commit is contained in:
commit
2cf230d6a6
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue