Merge branch '2.8'

* 2.8:
  removed usage of the deprecated StringUtils::equals() method
  Fix: Resolve tempdir symlink, not working on OSX
  fixed tests
  migrate session after remember me authentication
  prevent timing attacks in digest auth listener
  mitigate CSRF timing attack vulnerability
  fix potential timing attack issue
  [WebProfilerBundle] Added a top left border radius to the minified to…
  [Routing] Changing RouteCollectionBuilder::import() behavior to add to the builder
  [HttpKernel] Don't reset on shutdown but in FrameworkBundle/Test/KernelTestCase
  [Process] PhpExecutableFinder: add regression test
This commit is contained in:
Fabien Potencier 2015-11-23 11:41:47 +01:00
commit 45fe468074
12 changed files with 113 additions and 20 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Test;
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\KernelInterface;
@ -171,7 +172,11 @@ abstract class KernelTestCase extends \PHPUnit_Framework_TestCase
protected static function ensureKernelShutdown()
{
if (null !== static::$kernel) {
$container = static::$kernel->getContainer();
static::$kernel->shutdown();
if ($container instanceof ResettableContainerInterface) {
$container->reset();
}
}
}

View File

@ -1,5 +1,6 @@
.sf-minitoolbar {
background-color: #222;
border-top-left-radius: 4px;
bottom: 0;
display: none;
height: 30px;
@ -8,6 +9,7 @@
right: 0;
z-index: 99999;
}
.sf-minitoolbar a {
display: block;
}
@ -357,6 +359,8 @@
/* Override the setting when the toolbar is on the top */
{% if position == 'top' %}
.sf-minitoolbar {
border-bottom-left-radius: 4px;
border-top-left-radius: 0;
bottom: auto;
right: 0;
top: 0;

View File

@ -308,7 +308,7 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
{
$builder = new ContainerBuilder();
$builder->register('bar', 'stdClass');
$builder->register('foo1', 'FooClass')->addMethodCall('setBar', array(array('%%unescape_it%%')));
$builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%%unescape_it%%')));
$builder->setParameter('value', 'bar');
$this->assertEquals(array('%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
}
@ -317,7 +317,7 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
{
$builder = new ContainerBuilder();
$builder->register('bar', 'stdClass');
$builder->register('foo1', 'FooClass')->setProperty('bar', array('%value%', new Reference('bar'), '%%unescape_it%%'));
$builder->register('foo1', 'Bar\FooClass')->setProperty('bar', array('%value%', new Reference('bar'), '%%unescape_it%%'));
$builder->setParameter('value', 'bar');
$this->assertEquals(array('bar', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the properties');
}

View File

@ -1042,8 +1042,8 @@ class FilesystemTest extends FilesystemTestCase
$dirname = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'does_not_exist';
$filename = $this->filesystem->tempnam($dirname, 'bar');
$this->assertStringStartsWith(rtrim($scheme.sys_get_temp_dir(), DIRECTORY_SEPARATOR), $filename);
$realTempDir = realpath(sys_get_temp_dir());
$this->assertStringStartsWith(rtrim($scheme.$realTempDir, DIRECTORY_SEPARATOR), $filename);
$this->assertFileExists($filename);
// Tear down

View File

@ -23,7 +23,6 @@ use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\ResettableContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
@ -155,10 +154,6 @@ abstract class Kernel implements KernelInterface, TerminableInterface
$bundle->setContainer(null);
}
if ($this->container instanceof ResettableContainerInterface) {
$this->container->reset();
}
$this->container = null;
}

View File

@ -19,7 +19,25 @@ use Symfony\Component\Process\PhpExecutableFinder;
class PhpExecutableFinderTest extends \PHPUnit_Framework_TestCase
{
/**
* tests find() with the env var PHP_PATH.
* tests find() with the constant PHP_BINARY.
*/
public function testFind()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Should not be executed in HHVM context.');
}
$f = new PhpExecutableFinder();
$current = PHP_BINARY;
$args = 'phpdbg' === PHP_SAPI ? ' -qrr' : '';
$this->assertEquals($current.$args, $f->find(), '::find() returns the executable PHP');
$this->assertEquals($current, $f->find(false), '::find() returns the executable PHP');
}
/**
* tests find() with the env var / constant PHP_BINARY with HHVM.
*/
public function testFindWithHHVM()
{

View File

@ -49,16 +49,17 @@ class RouteCollectionBuilder
/**
* Import an external routing resource and returns the RouteCollectionBuilder.
*
* $routes->mount('/blog', $routes->import('blog.yml'));
* $routes->import('blog.yml', '/blog');
*
* @param mixed $resource
* @param string $type
* @param mixed $resource
* @param string|null $prefix
* @param string $type
*
* @return RouteCollectionBuilder
*
* @throws FileLoaderLoadException
*/
public function import($resource, $type = null)
public function import($resource, $prefix = '/', $type = null)
{
/** @var RouteCollection $collection */
$collection = $this->load($resource, $type);
@ -73,6 +74,9 @@ class RouteCollectionBuilder
$builder->addResource($resource);
}
// mount into this builder
$this->mount($prefix, $builder);
return $builder;
}

View File

@ -45,7 +45,7 @@ class RouteCollectionBuilderTest extends \PHPUnit_Framework_TestCase
// import the file!
$routes = new RouteCollectionBuilder($loader);
$importedRoutes = $routes->import('admin_routing.yml', 'yaml');
$importedRoutes = $routes->import('admin_routing.yml', '/', 'yaml');
// we should get back a RouteCollectionBuilder
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollectionBuilder', $importedRoutes);
@ -56,6 +56,9 @@ class RouteCollectionBuilderTest extends \PHPUnit_Framework_TestCase
$this->assertSame($originalRoute, $route);
// should return file_resource.yml, which is in the original collection
$this->assertCount(1, $addedCollection->getResources());
// make sure the routes were imported into the top-level builder
$this->assertCount(1, $routes->build());
}
/**
@ -285,7 +288,7 @@ class RouteCollectionBuilderTest extends \PHPUnit_Framework_TestCase
->method('load')
->will($this->returnValue($importedCollection));
// import this from the /admin route builder
$adminRoutes->mount('/imported', $adminRoutes->import('admin.yml'));
$adminRoutes->import('admin.yml', '/imported');
$collection = $routes->build();
$this->assertEquals('/admin/dashboard', $collection->get('admin_dashboard')->getPath(), 'Routes before mounting have the prefix');

View File

@ -99,7 +99,7 @@ class DigestAuthenticationListener implements ListenerInterface
return;
}
if ($serverDigestMd5 !== $digestAuth->getResponse()) {
if (!hash_equals($serverDigestMd5, $digestAuth->getResponse())) {
if (null !== $this->logger) {
$this->logger->debug('Unexpected response from the DigestAuth received; is the header returning a clear text passwords?', array('expected' => $serverDigestMd5, 'received' => $digestAuth->getResponse()));
}

View File

@ -21,6 +21,7 @@ use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
/**
* RememberMeListener implements authentication capabilities via a cookie.
@ -56,7 +57,7 @@ class RememberMeListener implements ListenerInterface
$this->logger = $logger;
$this->dispatcher = $dispatcher;
$this->catchExceptions = $catchExceptions;
$this->sessionStrategy = $sessionStrategy;
$this->sessionStrategy = null === $sessionStrategy ? new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE) : $sessionStrategy;
}
/**
@ -77,7 +78,7 @@ class RememberMeListener implements ListenerInterface
try {
$token = $this->authenticationManager->authenticate($token);
if (null !== $this->sessionStrategy && $request->hasSession() && $request->getSession()->isStarted()) {
if ($request->hasSession() && $request->getSession()->isStarted()) {
$this->sessionStrategy->onAuthentication($request, $token);
}
$this->tokenStorage->setToken($token);

View File

@ -71,7 +71,7 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices
list($series, $tokenValue) = $cookieParts;
$persistentToken = $this->tokenProvider->loadTokenBySeries($series);
if ($persistentToken->getTokenValue() !== $tokenValue) {
if (!hash_equals($persistentToken->getTokenValue(), $tokenValue)) {
throw new CookieTheftException('This token was already used. The account is possibly compromised.');
}

View File

@ -246,6 +246,69 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event);
}
public function testSessionIsMigratedByDefault()
{
list($listener, $tokenStorage, $service, $manager, , $dispatcher, $sessionStrategy) = $this->getListener(false, true, false);
$tokenStorage
->expects($this->once())
->method('getToken')
->will($this->returnValue(null))
;
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
$service
->expects($this->once())
->method('autoLogin')
->will($this->returnValue($token))
;
$tokenStorage
->expects($this->once())
->method('setToken')
->with($this->equalTo($token))
;
$manager
->expects($this->once())
->method('authenticate')
->will($this->returnValue($token))
;
$session = $this->getMock('\Symfony\Component\HttpFoundation\Session\SessionInterface');
$session
->expects($this->once())
->method('isStarted')
->will($this->returnValue(true))
;
$session
->expects($this->once())
->method('migrate')
;
$request = $this->getMock('\Symfony\Component\HttpFoundation\Request');
$request
->expects($this->any())
->method('hasSession')
->will($this->returnValue(true))
;
$request
->expects($this->any())
->method('getSession')
->will($this->returnValue($session))
;
$event = $this->getGetResponseEvent();
$event
->expects($this->once())
->method('getRequest')
->will($this->returnValue($request))
;
$listener->handle($event);
}
public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent()
{
list($listener, $tokenStorage, $service, $manager, , $dispatcher) = $this->getListener(true);