diff options
author | Nicolas Grekas <nicolas.grekas@gmail.com> | 2016-05-12 10:59:27 -0500 |
---|---|---|
committer | Nicolas Grekas <nicolas.grekas@gmail.com> | 2016-05-12 10:59:27 -0500 |
commit | ef9abbe2063b55156fb88c353b4e332eef0793fc (patch) | |
tree | 50460e40705b01ba4751038e69acbad9074e8087 | |
parent | cc9e95904aafbb46d8e5133049078ba099f9c4e1 (diff) | |
parent | 787f7af77f69aa72028a3865f3689a6f18995c96 (diff) | |
download | symfony-security-ef9abbe2063b55156fb88c353b4e332eef0793fc.zip symfony-security-ef9abbe2063b55156fb88c353b4e332eef0793fc.tar.gz symfony-security-ef9abbe2063b55156fb88c353b4e332eef0793fc.tar.bz2 |
Merge branch '3.0'v3.1.0-BETA1
* 3.0: (31 commits)
Drop hirak/prestissimo
[MonologBridge] Uninstallable together with symfony/http-kernel in 3.0.6
bumped Symfony version to 3.0.7
updated VERSION for 3.0.6
updated CHANGELOG for 3.0.6
bumped Symfony version to 2.8.7
updated VERSION for 2.8.6
updated CHANGELOG for 2.8.6
bumped Symfony version to 2.7.14
updated VERSION for 2.7.13
updated CHANGELOG for 2.7.13
bumped Symfony version to 2.3.42
[Debug] Fix fatal error handlers on PHP 7
updated VERSION for 2.3.41
update CONTRIBUTORS for 2.3.41
updated CHANGELOG for 2.3.41
fixed bad merge
Fixed issue with blank password with Ldap
limited the maximum length of a submitted username
[2.3][Component/Security] Fixed phpdoc in AnonymousToken constructor for user param
...
Conflicts:
src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
src/Symfony/Component/HttpKernel/Kernel.php
8 files changed, 113 insertions, 3 deletions
diff --git a/Core/Authentication/Provider/LdapBindAuthenticationProvider.php b/Core/Authentication/Provider/LdapBindAuthenticationProvider.php index 950b603..5ebb09a 100644 --- a/Core/Authentication/Provider/LdapBindAuthenticationProvider.php +++ b/Core/Authentication/Provider/LdapBindAuthenticationProvider.php @@ -73,6 +73,10 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider $username = $token->getUsername(); $password = $token->getCredentials(); + if ('' === $password) { + throw new BadCredentialsException('The presented password must not be empty.'); + } + try { $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN); $dn = str_replace('{username}', $username, $this->dnString); diff --git a/Core/Authentication/Token/AnonymousToken.php b/Core/Authentication/Token/AnonymousToken.php index e1dfef4..2c73cb4 100644 --- a/Core/Authentication/Token/AnonymousToken.php +++ b/Core/Authentication/Token/AnonymousToken.php @@ -26,7 +26,7 @@ class AnonymousToken extends AbstractToken * Constructor. * * @param string $secret A secret used to make sure the token is created by the app and not by a malicious client - * @param string $user The user + * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string. * @param RoleInterface[] $roles An array of roles */ public function __construct($secret, $user, array $roles = array()) diff --git a/Core/Authentication/Token/PreAuthenticatedToken.php b/Core/Authentication/Token/PreAuthenticatedToken.php index 1798203..5a3fc95 100644 --- a/Core/Authentication/Token/PreAuthenticatedToken.php +++ b/Core/Authentication/Token/PreAuthenticatedToken.php @@ -26,7 +26,7 @@ class PreAuthenticatedToken extends AbstractToken /** * Constructor. * - * @param string|object $user The user + * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string. * @param mixed $credentials The user credentials * @param string $providerKey The provider key * @param RoleInterface[]|string[] $roles An array of roles diff --git a/Core/Security.php b/Core/Security.php index 14d32f8..84cc77d 100644 --- a/Core/Security.php +++ b/Core/Security.php @@ -21,4 +21,5 @@ final class Security const ACCESS_DENIED_ERROR = '_security.403_error'; const AUTHENTICATION_ERROR = '_security.last_error'; const LAST_USERNAME = '_security.last_username'; + const MAX_USERNAME_LENGTH = 4096; } diff --git a/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php index 4d2eead..da3068f 100644 --- a/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php +++ b/Core/Tests/Authentication/Provider/LdapBindAuthenticationProviderTest.php @@ -26,6 +26,23 @@ class LdapBindAuthenticationProviderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException + * @expectedExceptionMessage The presented password must not be empty. + */ + public function testEmptyPasswordShouldThrowAnException() + { + $userProvider = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); + $ldap = $this->getMock('Symfony\Component\Ldap\LdapClientInterface'); + $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); + + $provider = new LdapBindAuthenticationProvider($userProvider, $userChecker, 'key', $ldap); + $reflection = new \ReflectionMethod($provider, 'checkAuthentication'); + $reflection->setAccessible(true); + + $reflection->invoke($provider, new User('foo', null), new UsernamePasswordToken('foo', '', 'key')); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException * @expectedExceptionMessage The presented password is invalid. */ public function testBindFailureShouldThrowAnException() @@ -43,7 +60,7 @@ class LdapBindAuthenticationProviderTest extends \PHPUnit_Framework_TestCase $reflection = new \ReflectionMethod($provider, 'checkAuthentication'); $reflection->setAccessible(true); - $reflection->invoke($provider, new User('foo', null), new UsernamePasswordToken('foo', '', 'key')); + $reflection->invoke($provider, new User('foo', null), new UsernamePasswordToken('foo', 'bar', 'key')); } public function testRetrieveUser() diff --git a/Http/Firewall/SimpleFormAuthenticationListener.php b/Http/Firewall/SimpleFormAuthenticationListener.php index 76c66bc..7c940c3 100644 --- a/Http/Firewall/SimpleFormAuthenticationListener.php +++ b/Http/Firewall/SimpleFormAuthenticationListener.php @@ -21,6 +21,7 @@ use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerI use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\ParameterBagUtils; @@ -107,6 +108,10 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); } + if (strlen($username) > Security::MAX_USERNAME_LENGTH) { + throw new BadCredentialsException('Invalid username.'); + } + $request->getSession()->set(Security::LAST_USERNAME, $username); $token = $this->simpleAuthenticator->createToken($request, $username, $password, $this->providerKey); diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index c8195ce..426457d 100644 --- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -23,6 +23,7 @@ use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException; use Symfony\Component\Security\Core\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -83,6 +84,10 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL $password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']); } + if (strlen($username) > Security::MAX_USERNAME_LENGTH) { + throw new BadCredentialsException('Invalid username.'); + } + $request->getSession()->set(Security::LAST_USERNAME, $username); return $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey)); diff --git a/Tests/Http/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/Tests/Http/Firewall/UsernamePasswordFormAuthenticationListenerTest.php new file mode 100644 index 0000000..eca14d3 --- /dev/null +++ b/Tests/Http/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Tests\Http\Firewall; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener; +use Symfony\Component\Security\Core\Security; + +class UsernamePasswordFormAuthenticationListenerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getUsernameForLength + */ + public function testHandleWhenUsernameLength($username, $ok) + { + $request = Request::create('/login_check', 'POST', array('_username' => $username)); + $request->setSession($this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface')); + + $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); + $httpUtils + ->expects($this->any()) + ->method('checkRequestPath') + ->will($this->returnValue(true)) + ; + + $failureHandler = $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface'); + $failureHandler + ->expects($ok ? $this->never() : $this->once()) + ->method('onAuthenticationFailure') + ->will($this->returnValue(new Response())) + ; + + $authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager')->disableOriginalConstructor()->getMock(); + $authenticationManager + ->expects($ok ? $this->once() : $this->never()) + ->method('authenticate') + ->will($this->returnValue(new Response())) + ; + + $listener = new UsernamePasswordFormAuthenticationListener( + $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'), + $authenticationManager, + $this->getMock('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface'), + $httpUtils, + 'TheProviderKey', + $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface'), + $failureHandler, + array('require_previous_session' => false) + ); + + $event = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false); + $event + ->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($request)) + ; + + $listener->handle($event); + } + + public function getUsernameForLength() + { + return array( + array(str_repeat('x', Security::MAX_USERNAME_LENGTH + 1), false), + array(str_repeat('x', Security::MAX_USERNAME_LENGTH - 1), true), + ); + } +} |