From a9705a014393be7e789643aef621147126e8d627 Mon Sep 17 00:00:00 2001 From: Tomas Date: Wed, 12 Jun 2019 07:10:29 +0300 Subject: [PATCH 1/8] Fix AuthenticationException::getToken typehint --- .../Security/Core/Exception/AuthenticationException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php index 2c6c7344a4..f79cf3ecf2 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php @@ -26,7 +26,7 @@ class AuthenticationException extends \RuntimeException implements \Serializable /** * Get the token. * - * @return TokenInterface + * @return TokenInterface|null */ public function getToken() { From 32d02d61414e5938602a1cee993f628fad0719ef Mon Sep 17 00:00:00 2001 From: Stefano Degenkamp Date: Wed, 19 Jun 2019 16:56:52 +0200 Subject: [PATCH 2/8] Update ajax security cheat sheet link As the cheat sheet series project has been moved to github. --- src/Symfony/Component/HttpFoundation/JsonResponse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 24798eea42..bb1fe1d0ae 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpFoundation; * object. It is however recommended that you do return an object as it * protects yourself against XSSI and JSON-JavaScript Hijacking. * - * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside + * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside * * @author Igor Wiedler */ From c1c3b54a0fbca9f85cdde38cc90431438c539eba Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 20 Jun 2019 03:38:05 +0100 Subject: [PATCH 3/8] [Messenger] fix delay exchange recreation after disconnect --- src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php b/src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php index 6f6b8b22a6..ecd72a7be9 100644 --- a/src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php @@ -430,6 +430,7 @@ class Connection $this->amqpChannel = null; $this->amqpQueues = []; $this->amqpExchange = null; + $this->amqpDelayExchange = null; } private function shouldSetup(): bool From bf6d2532de8e6bc7a6906c9aab750e4a0c966456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Fri, 14 Jun 2019 12:02:44 +0200 Subject: [PATCH 4/8] [Validator] Fix GroupSequenceProvider annotation --- src/Symfony/Component/Validator/Constraints/GroupSequence.php | 2 +- .../Component/Validator/GroupSequenceProviderInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/GroupSequence.php b/src/Symfony/Component/Validator/Constraints/GroupSequence.php index a39d712bf4..fc34ca1a45 100644 --- a/src/Symfony/Component/Validator/Constraints/GroupSequence.php +++ b/src/Symfony/Component/Validator/Constraints/GroupSequence.php @@ -57,7 +57,7 @@ class GroupSequence /** * The groups in the sequence. * - * @var string[]|array[]|GroupSequence[] + * @var string[]|string[][]|GroupSequence[] */ public $groups; diff --git a/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php b/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php index 5894397da4..1ce504331f 100644 --- a/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php +++ b/src/Symfony/Component/Validator/GroupSequenceProviderInterface.php @@ -22,7 +22,7 @@ interface GroupSequenceProviderInterface * Returns which validation groups should be used for a certain state * of the object. * - * @return string[]|GroupSequence An array of validation groups + * @return string[]|string[][]|GroupSequence An array of validation groups */ public function getGroupSequence(); } From f23a7f60cf5e18969ce987a594db1b507c6503c4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 20 Jun 2019 10:33:16 +0200 Subject: [PATCH 5/8] don't validate IP addresses from env var placeholders --- .../DependencyInjection/MainConfiguration.php | 35 --------------- .../DependencyInjection/SecurityExtension.php | 44 +++++++++++++++++-- .../Resources/config/routing.yml | 6 +++ .../SecurityRoutingIntegrationTest.php | 2 +- .../app/StandardFormLogin/config.yml | 5 +++ .../invalid_ip_access_control.yml | 2 +- 6 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index eda62ed9ac..1e1e97ccb5 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -143,15 +143,6 @@ class MainConfiguration implements ConfigurationInterface ->integerNode('port')->defaultNull()->end() ->arrayNode('ips') ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->beforeNormalization()->always()->then(function ($v) { - foreach ($v as $ip) { - if (false === $this->isValidIp($ip)) { - throw new \LogicException(sprintf('The given "%s" value in the "access_control" config option is not a valid IP address.', $ip)); - } - } - - return $v; - })->end() ->prototype('scalar')->end() ->end() ->arrayNode('methods') @@ -432,30 +423,4 @@ class MainConfiguration implements ConfigurationInterface ->end() ; } - - private function isValidIp(string $cidr): bool - { - $cidrParts = explode('/', $cidr); - - if (1 === \count($cidrParts)) { - return false !== filter_var($cidrParts[0], FILTER_VALIDATE_IP); - } - - $ip = $cidrParts[0]; - $netmask = $cidrParts[1]; - - if (!ctype_digit($netmask)) { - return false; - } - - if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - return $netmask <= 32; - } - - if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { - return $netmask <= 128; - } - - return false; - } } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index af4260f04c..4365d04329 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -731,20 +731,32 @@ class SecurityExtension extends Extension implements PrependExtensionInterface return $this->expressions[$id] = new Reference($id); } - private function createRequestMatcher($container, $path = null, $host = null, int $port = null, $methods = [], $ip = null, array $attributes = []) + private function createRequestMatcher(ContainerBuilder $container, $path = null, $host = null, int $port = null, $methods = [], array $ips = null, array $attributes = []) { if ($methods) { $methods = array_map('strtoupper', (array) $methods); } - $id = '.security.request_matcher.'.ContainerBuilder::hash([$path, $host, $port, $methods, $ip, $attributes]); + if (null !== $ips) { + foreach ($ips as $ip) { + $container->resolveEnvPlaceholders($ip, null, $usedEnvs); + + if (!$usedEnvs && !$this->isValidIp($ip)) { + throw new \LogicException(sprintf('The given value "%s" in the "security.access_control" config option is not a valid IP address.', $ip)); + } + + $usedEnvs = null; + } + } + + $id = '.security.request_matcher.'.ContainerBuilder::hash([$path, $host, $port, $methods, $ips, $attributes]); if (isset($this->requestMatchers[$id])) { return $this->requestMatchers[$id]; } // only add arguments that are necessary - $arguments = [$path, $host, $methods, $ip, $attributes, null, $port]; + $arguments = [$path, $host, $methods, $ips, $attributes, null, $port]; while (\count($arguments) > 0 && !end($arguments)) { array_pop($arguments); } @@ -788,4 +800,30 @@ class SecurityExtension extends Extension implements PrependExtensionInterface // first assemble the factories return new MainConfiguration($this->factories, $this->userProviderFactories); } + + private function isValidIp(string $cidr): bool + { + $cidrParts = explode('/', $cidr); + + if (1 === \count($cidrParts)) { + return false !== filter_var($cidrParts[0], FILTER_VALIDATE_IP); + } + + $ip = $cidrParts[0]; + $netmask = $cidrParts[1]; + + if (!ctype_digit($netmask)) { + return false; + } + + if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + return $netmask <= 32; + } + + if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + return $netmask <= 128; + } + + return false; + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml index 2fff93dcad..bf82a203d8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml @@ -40,6 +40,12 @@ secured-by-one-real-ip-with-mask: secured-by-one-real-ipv6: path: /secured-by-one-real-ipv6 +secured-by-one-env-placeholder: + path: /secured-by-one-env-placeholder + +secured-by-one-env-placeholder-and-one-real-ip: + path: /secured-by-one-env-placeholder-and-one-real-ip + form_logout: path: /logout_path diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php index 682c561ac5..c38bc1a4bf 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php @@ -109,7 +109,7 @@ class SecurityRoutingIntegrationTest extends WebTestCase public function testInvalidIpsInAccessControl() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage('The given "256.357.458.559" value in the "access_control" config option is not a valid IP address.'); + $this->expectExceptionMessage('The given value "256.357.458.559" in the "security.access_control" config option is not a valid IP address.'); $client = $this->createClient(['test_case' => 'StandardFormLogin', 'root_config' => 'invalid_ip_access_control.yml']); $client->request('GET', '/unprotected_resource'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml index df03c20c5c..4e2ac1e11b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml @@ -1,6 +1,9 @@ imports: - { resource: ./../config/default.yml } +parameters: + env(APP_IP): '127.0.0.1' + security: encoders: Symfony\Component\Security\Core\User\User: plaintext @@ -43,6 +46,8 @@ security: - { path: ^/secured-by-one-real-ip$, ips: 198.51.100.0, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/secured-by-one-real-ip-with-mask$, ips: '203.0.113.0/24', roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/secured-by-one-real-ipv6$, ips: 0:0:0:0:0:ffff:c633:6400, roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/secured-by-one-env-placeholder$, ips: '%env(APP_IP)%', roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/secured-by-one-env-placeholder-and-one-real-ip$, ips: ['%env(APP_IP)%', 198.51.100.0], roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/highly_protected_resource$, roles: IS_ADMIN } - { path: ^/protected-via-expression$, allow_if: "(is_anonymous() and request.headers.get('user-agent') matches '/Firefox/i') or is_granted('ROLE_USER')" } - { path: .*, roles: IS_AUTHENTICATED_FULLY } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/invalid_ip_access_control.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/invalid_ip_access_control.yml index e4f46c4704..cc6503affb 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/invalid_ip_access_control.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/invalid_ip_access_control.yml @@ -19,4 +19,4 @@ security: access_control: # the '256.357.458.559' IP is wrong on purpose, to check invalid IP errors - - { path: ^/unprotected_resource$, ips: [1.1.1.1, 256.357.458.559], roles: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/unprotected_resource$, ips: [1.1.1.1, '%env(APP_IP)%', 256.357.458.559], roles: IS_AUTHENTICATED_ANONYMOUSLY } From ea5b1f4d67e3218a005d6109b64250c80e81d98b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 20 Jun 2019 12:19:18 +0200 Subject: [PATCH 6/8] tag the FileType service as a form type --- src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 5088554ff1..c5bc8cf5db 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -93,6 +93,7 @@ The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. + From 74387cf21fed1f77c925a869e9585282544d47be Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 20 Jun 2019 22:29:36 +0200 Subject: [PATCH 7/8] fix translation domain --- src/Symfony/Component/Form/Extension/Core/Type/FileType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php index f8afce2ee5..86f161307b 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FileType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FileType.php @@ -159,7 +159,7 @@ class FileType extends AbstractType } if (null !== $this->translator) { - $message = $this->translator->trans($messageTemplate, $messageParameters); + $message = $this->translator->trans($messageTemplate, $messageParameters, 'validators'); } else { $message = strtr($messageTemplate, $messageParameters); } From 3bbf9da47bdf79d175f84a9a9c73a5d7d4f66beb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 21 Jun 2019 12:17:48 +0200 Subject: [PATCH 8/8] fix order of items in upgrade file --- UPGRADE-4.4.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/UPGRADE-4.4.md b/UPGRADE-4.4.md index 2fed4defb0..d3de7b168c 100644 --- a/UPGRADE-4.4.md +++ b/UPGRADE-4.4.md @@ -1,11 +1,6 @@ UPGRADE FROM 4.3 to 4.4 ======================= -HttpKernel ----------- - - * The `DebugHandlersListener` class has been marked as `final` - DependencyInjection ------------------- @@ -46,18 +41,24 @@ DependencyInjection arguments: [!tagged_iterator app.handler] ``` +FrameworkBundle +--------------- + + * Deprecated support for `templating` engine in `TemplateController`, use Twig instead + * The `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()` + has been deprecated. + * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final`. + * The `controller_name_converter` and `resolve_controller_name_subscriber` services have been deprecated. + HttpClient ---------- * Added method `cancel()` to `ResponseInterface` -FrameworkBundle ---------------- +HttpKernel +---------- - * The `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()` - has been deprecated. - * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final`. - * The `controller_name_converter` and `resolve_controller_name_subscriber` services have been deprecated. + * The `DebugHandlersListener` class has been marked as `final` Messenger --------- @@ -65,11 +66,6 @@ Messenger * Deprecated passing a `ContainerInterface` instance as first argument of the `ConsumeMessagesCommand` constructor, pass a `RoutableMessageBus` instance instead. -FrameworkBundle ---------------- - - * Deprecated support for `templating` engine in `TemplateController`, use Twig instead - MonologBridge --------------