diff --git a/CHANGELOG-6.0.md b/CHANGELOG-6.0.md index 36533d04d2bc3..07005e3077334 100644 --- a/CHANGELOG-6.0.md +++ b/CHANGELOG-6.0.md @@ -7,6 +7,32 @@ in 6.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.0.0...v6.0.1 +* 6.0.19 (2023-01-24) + + * bug #49078 [Security/Http] Check tokens before loading users from providers (nicolas-grekas) + * bug #49077 [DependencyInjection] Fix named arguments when using ContainerBuilder before compilation (nicolas-grekas) + * bug #49031 [Cache] fix collecting cache stats when nesting computations (nicolas-grekas) + * bug #49046 Fix for Windows when projects are deployed on junctions/symlinks (nerdgod) + * bug #49025 [Notifier] [OvhCloud] handle invalid receiver (seferov) + * bug #48993 [VarDumper] Fix JS to expand / collapse (nicolas-grekas) + * bug #48983 Fix BC user_identifier support after deprecation username (vtsykun) + * bug #48986 [Validator] Fix Email validator logic (fabpot) + * bug #48969 [PropertyInfo] Fixes constructor extractor for mixed type (michael.kubovic) + * bug #48978 [Serializer] use method_exists() instead of catching reflection exceptions (xabbuh) + * bug #48937 [SecurityBundle] Fix using same handler for multiple authenticators (RobertMe) + * bug #48971 [DependencyInjection] Fix dump order of inlined deps (nicolas-grekas) + * bug #48966 [HttpClient] Let curl handle content-length headers (nicolas-grekas) + * bug #48968 [VarExporter] Fix exporting enums (nicolas-grekas) + * bug #48926 [DependencyInjection] Fix support for named arguments on non-autowired services (nicolas-grekas) + * bug #48943 [FrameworkBundle] Fix deprecation when accessing a "container.private" service from the test container (nicolas-grekas) + * bug #48931 [DependencyInjection] Fix dumping inlined withers (nicolas-grekas) + * bug #48898 [HttpClient] Move Http clients data collecting at a late level (pforesi) + * bug #48896 [DoctrineBridge] Fix detecting mapping with one line annotations (franmomu) + * bug #48916 [FrameworkBundle] restore call to addGlobalIgnoredName (alexislefebvre) + * bug #48917 [Config] Fix XML dump when node example is an array (alexandre-daubois) + * bug #48904 [Validator] Allow egulias/email-validator v4 (chalasr) + * bug #48831 [Uid] Fix validating nil and max uuid (fancyweb) + * 6.0.18 (2022-12-29) * bug #48823 [Cache] Fix possibly null value passed to preg_match() in RedisTrait (chalasr) diff --git a/CHANGELOG-6.1.md b/CHANGELOG-6.1.md index f798e9732f746..e60e17769bcc6 100644 --- a/CHANGELOG-6.1.md +++ b/CHANGELOG-6.1.md @@ -7,6 +7,33 @@ in 6.1 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.1.0...v6.1.1 +* 6.1.11 (2023-01-24) + + * bug #49078 [Security/Http] Check tokens before loading users from providers (nicolas-grekas) + * bug #49077 [DependencyInjection] Fix named arguments when using ContainerBuilder before compilation (nicolas-grekas) + * bug #49031 [Cache] fix collecting cache stats when nesting computations (nicolas-grekas) + * bug #49046 Fix for Windows when projects are deployed on junctions/symlinks (nerdgod) + * bug #49025 [Notifier] [OvhCloud] handle invalid receiver (seferov) + * bug #48993 [VarDumper] Fix JS to expand / collapse (nicolas-grekas) + * bug #48983 Fix BC user_identifier support after deprecation username (vtsykun) + * bug #48986 [Validator] Fix Email validator logic (fabpot) + * bug #48969 [PropertyInfo] Fixes constructor extractor for mixed type (michael.kubovic) + * bug #48978 [Serializer] use method_exists() instead of catching reflection exceptions (xabbuh) + * bug #48937 [SecurityBundle] Fix using same handler for multiple authenticators (RobertMe) + * bug #48971 [DependencyInjection] Fix dump order of inlined deps (nicolas-grekas) + * bug #48966 [HttpClient] Let curl handle content-length headers (nicolas-grekas) + * bug #48968 [VarExporter] Fix exporting enums (nicolas-grekas) + * bug #48933 [Validator] Fix bad handling of nulls when the 'fields' option of the Unique constraint is set (plfort) + * bug #48926 [DependencyInjection] Fix support for named arguments on non-autowired services (nicolas-grekas) + * bug #48943 [FrameworkBundle] Fix deprecation when accessing a "container.private" service from the test container (nicolas-grekas) + * bug #48931 [DependencyInjection] Fix dumping inlined withers (nicolas-grekas) + * bug #48898 [HttpClient] Move Http clients data collecting at a late level (pforesi) + * bug #48896 [DoctrineBridge] Fix detecting mapping with one line annotations (franmomu) + * bug #48916 [FrameworkBundle] restore call to addGlobalIgnoredName (alexislefebvre) + * bug #48917 [Config] Fix XML dump when node example is an array (alexandre-daubois) + * bug #48904 [Validator] Allow egulias/email-validator v4 (chalasr) + * bug #48831 [Uid] Fix validating nil and max uuid (fancyweb) + * 6.1.10 (2022-12-29) * bug #48823 [Cache] Fix possibly null value passed to preg_match() in RedisTrait (chalasr) diff --git a/CHANGELOG-6.2.md b/CHANGELOG-6.2.md index caa48fbf31992..4051e25d750d2 100644 --- a/CHANGELOG-6.2.md +++ b/CHANGELOG-6.2.md @@ -7,6 +7,15 @@ in 6.2 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.2.0...v6.2.1 +* 6.2.6 (2023-02-01) + + * bug #49141 [HttpFoundation] Fix bad return type in IpUtils::checkIp4() (tristankretzer) + * bug #49126 [DependencyInjection] Fix order of arguments when mixing positional and named ones (nicolas-grekas) + * bug #49104 [HttpClient] Fix collecting data non-late for the profiler (nicolas-grekas) + * bug #49103 [Security/Http] Fix compat of persistent remember-me with legacy tokens (nicolas-grekas) + * security #cve-2022-24895 [Security/Http] Remove CSRF tokens from storage on successful login (nicolas-grekas) + * security #cve-2022-24894 [HttpKernel] Remove private headers before storing responses with HttpCache (nicolas-grekas) + * 6.2.5 (2023-01-24) * bug #49078 [Security/Http] Check tokens before loading users from providers (nicolas-grekas) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 94862ab99db42..016a12f53a9c9 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -23,8 +23,8 @@ The Symfony Connect username in parenthesis allows to get more information - Victor Berchet (victor) - Yonel Ceruto (yonelceruto) - Tobias Nyholm (tobias) - - Oskar Stark (oskarstark) - Javier Eguiluz (javier.eguiluz) + - Oskar Stark (oskarstark) - Ryan Weaver (weaverryan) - Johannes S (johannes) - Jakub Zalas (jakubzalas) @@ -33,8 +33,8 @@ The Symfony Connect username in parenthesis allows to get more information - Hamza Amrouche (simperfit) - Samuel ROZE (sroze) - Pascal Borreli (pborreli) - - Romain Neutron - Jules Pietri (heah) + - Romain Neutron - Joseph Bielawski (stloyd) - Drak (drak) - Abdellatif Ait boudad (aitboudad) @@ -57,12 +57,12 @@ The Symfony Connect username in parenthesis allows to get more information - Grégoire Paris (greg0ire) - Gabriel Ostrolucký (gadelat) - Jonathan Wage (jwage) + - Alexandre Daubois (alexandre-daubois) - Titouan Galopin (tgalopin) - David Maicher (dmaicher) - - Alexandre Daubois (alexandre-daubois) + - Alexander Schranz (alexander-schranz) - Alexandre Salomé (alexandresalome) - William DURAND - - Alexander Schranz (alexander-schranz) - ornicar - Dany Maillard (maidmaid) - Mathieu Santostefano (welcomattic) @@ -80,13 +80,13 @@ The Symfony Connect username in parenthesis allows to get more information - Saša Stamenković (umpirsky) - Antoine Lamirault - Alex Pott - - Vincent Langlet (deviling) - Mathieu Lechat (mat_the_cat) + - Vincent Langlet (deviling) - Guilhem N (guilhemn) - Vladimir Reznichenko (kalessil) - Sarah Khalil (saro0h) - - Konstantin Kudryashov (everzet) - Tomas Norkūnas (norkunas) + - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Eriksen Costa - Florin Patan (florinpatan) @@ -99,13 +99,13 @@ The Symfony Connect username in parenthesis allows to get more information - Massimiliano Arione (garak) - Douglas Greenshields (shieldo) - Christian Raue + - Fran Moreno (franmomu) - Jáchym Toušek (enumag) - Mathias Arlaud (mtarld) - Graham Campbell (graham) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Issei Murasawa (issei_m) - - Fran Moreno (franmomu) - Malte Schlüter (maltemaltesich) - Vasilij Dusko - Denis (yethee) @@ -218,7 +218,9 @@ The Symfony Connect username in parenthesis allows to get more information - Juti Noppornpitak (shiroyuki) - Joe Bennett (kralos) - Nate Wiebe (natewiebe13) + - Farhad Safarov (safarov) - Anthony MARTIN + - Nicolas Philippe (nikophil) - Colin O'Dell (colinodell) - Sebastian Hörl (blogsh) - Ben Davies (bendavies) @@ -229,11 +231,11 @@ The Symfony Connect username in parenthesis allows to get more information - Albert Casademont (acasademont) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) + - Sergey (upyx) - Michael Voříšek - - Farhad Safarov (safarov) - SpacePossum - - Nicolas Philippe (nikophil) - Pablo Godel (pgodel) + - Hubert Lenoir (hubert_lenoir) - Denis Brumann (dbrumann) - Romaric Drigon (romaricdrigon) - Andréia Bohner (andreia) @@ -248,9 +250,7 @@ The Symfony Connect username in parenthesis allows to get more information - Vincent Touzet (vincenttouzet) - Fabien Bourigault (fbourigault) - soyuka - - Sergey (upyx) - Jérémy Derussé - - Hubert Lenoir (hubert_lenoir) - Florent Mata (fmata) - mcfedr (mcfedr) - Maciej Malarz (malarzm) @@ -298,6 +298,7 @@ The Symfony Connect username in parenthesis allows to get more information - Yoann RENARD (yrenard) - Thomas Lallement (raziel057) - Timothée Barray (tyx) + - Alexis Lefebvre - James Halsall (jaitsu) - Mikael Pajunen - Warnar Boekkooi (boekkooi) @@ -323,6 +324,7 @@ The Symfony Connect username in parenthesis allows to get more information - D (denderello) - Jonathan Scheiber (jmsche) - DQNEO + - Romain Monteil (ker0x) - Andrii Bodnar - gnito-org - Artem (artemgenvald) @@ -370,7 +372,6 @@ The Symfony Connect username in parenthesis allows to get more information - Pierre Minnieur (pminnieur) - Kyle - Dominique Bongiraud - - Romain Monteil (ker0x) - Hidde Wieringa (hiddewie) - Christopher Davis (chrisguitarguy) - Lukáš Holeczy (holicz) @@ -379,7 +380,6 @@ The Symfony Connect username in parenthesis allows to get more information - Emanuele Panzeri (thepanz) - Matthew Smeets - François Zaninotto (fzaninotto) - - Alexis Lefebvre - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) @@ -500,6 +500,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thomas Schulz (king2500) - Benjamin Morel - Bernd Stellwag + - Philippe SEGATORI (tigitz) - Frank de Jonge - Chris Tanaskoski - julien57 @@ -563,6 +564,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gabor Toth (tgabi333) - realmfoo - Thomas Tourlourat (armetiz) + - Gasan Guseynov (gassan) - Andrey Esaulov (andremaha) - Grégoire Passault (gregwar) - Jerzy Zawadzki (jzawadzki) @@ -607,7 +609,6 @@ The Symfony Connect username in parenthesis allows to get more information - Tri Pham (phamuyentri) - marie - Erkhembayar Gantulga (erheme318) - - Philippe SEGATORI (tigitz) - Fractal Zombie - Gunnstein Lye (glye) - Thomas Talbot (ioni) @@ -620,6 +621,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jérôme Tamarelle (jtamarelle-prismamedia) - Emil Masiakowski - Alexandre Parent + - Angelov Dejan (angelov) - DT Inier (gam6itko) - Matthew Lewinski (lewinski) - Magnus Nordlander (magnusnordlander) @@ -671,6 +673,7 @@ The Symfony Connect username in parenthesis allows to get more information - mondrake (mondrake) - Yaroslav Kiliba - “Filip + - FORT Pierre-Louis (plfort) - Simon Watiau (simonwatiau) - Ruben Jacobs (rubenj) - Arkadius Stefanski (arkadius) @@ -861,7 +864,6 @@ The Symfony Connect username in parenthesis allows to get more information - Arturs Vonda - Xavier Briand (xavierbriand) - Daniel Badura - - Angelov Dejan (angelov) - vagrant - Asier Illarramendi (doup) - AKeeman (akeeman) @@ -869,10 +871,10 @@ The Symfony Connect username in parenthesis allows to get more information - Restless-ET - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) + - Vladimir Tsykun (vtsykun) - Chris Sedlmayr (catchamonkey) - Kamil Kokot (pamil) - Seb Koelen - - FORT Pierre-Louis (plfort) - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) @@ -984,7 +986,6 @@ The Symfony Connect username in parenthesis allows to get more information - Rodrigo Borrego Bernabé (rodrigobb) - John Bafford (jbafford) - Emanuele Iannone - - Gasan Guseynov (gassan) - Ondrej Machulda (ondram) - Denis Gorbachev (starfall) - Martin Morávek (keeo) @@ -1075,6 +1076,7 @@ The Symfony Connect username in parenthesis allows to get more information - Arnaud Frézet - Nicolas Martin (cocorambo) - luffy1727 + - Allison Guilhem (a_guilhem) - LHommet Nicolas (nicolaslh) - Sebastian Blum - Amirreza Shafaat (amirrezashafaat) @@ -1140,10 +1142,10 @@ The Symfony Connect username in parenthesis allows to get more information - Javier López (loalf) - tamar peled - Reinier Kip + - Robert Meijers - Geoffrey Brier (geoffrey-brier) - Sofien Naas - Christophe Meneses (c77men) - - Vladimir Tsykun - Andrei O - Dustin Dobervich (dustin10) - Alejandro Diaz Torres @@ -1603,6 +1605,7 @@ The Symfony Connect username in parenthesis allows to get more information - Patrick Dawkins (pjcdawkins) - Paul Kamer (pkamer) - Rafał Wrzeszcz (rafalwrzeszcz) + - Reyo Stallenberg (reyostallenberg) - Rémi Faivre (rfv) - Nguyen Xuan Quynh - Reen Lokum @@ -2007,7 +2010,6 @@ The Symfony Connect username in parenthesis allows to get more information - Chris Jones (leek) - neghmurken - stefan.r - - Allison Guilhem (a_guilhem) - xaav - Jean-Christophe Cuvelier [Artack] - Mahmoud Mostafa (mahmoud) @@ -2090,6 +2092,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ole Rößner (basster) - Faton (notaf) - Tom Houdmont + - mark burdett - Per Sandström (per) - Goran Juric - Laurent G. (laurentg) @@ -2116,6 +2119,7 @@ The Symfony Connect username in parenthesis allows to get more information - Norbert Schultheisz - Maximilian Berghoff (electricmaxxx) - SOEDJEDE Felix (fsoedjede) + - otsch - Piotr Antosik (antek88) - Nacho Martin (nacmartin) - Sergey Novikov (s12v) @@ -2125,6 +2129,7 @@ The Symfony Connect username in parenthesis allows to get more information - MARYNICH Mikhail (mmarynich-ext) - Viktor Novikov (nowiko) - Paul Mitchum (paul-m) + - Phil E. Taylor (philetaylor) - Angel Koilov (po_taka) - Dan Finnie - Ken Marfilla (marfillaster) @@ -2140,6 +2145,7 @@ The Symfony Connect username in parenthesis allows to get more information - Martijn Evers - Benjamin Paap (benjaminpaap) - Christian + - ju1ius - Denis Golubovskiy (bukashk0zzz) - Serge (nfx) - Mikkel Paulson @@ -2288,6 +2294,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jay Klehr - Sergey Yuferev - Monet Emilien + - voodooism - Tobias Stöckler - Mario Young - martkop26 @@ -2296,7 +2303,7 @@ The Symfony Connect username in parenthesis allows to get more information - cilefen (cilefen) - Mo Di (modi) - Pablo Schläpfer - - Robert Meijers + - Nikos Charalampidis - Xavier RENAUDIN - Christian Wahler (christian) - Jelte Steijaert (jelte) @@ -2413,6 +2420,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ilya Biryukov (ibiryukov) - Roma (memphys) - Giorgio Premi + - Matthias Bilger - Krzysztof Pyrkosz - ncou - Ian Carroll @@ -2458,6 +2466,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas Eeckeloo (neeckeloo) - Andriy Prokopenko (sleepyboy) - Dariusz Ruminski + - Thomas Hanke - Daniel Tschinder - Arnaud CHASSEUX - Wojciech Gorczyca @@ -2469,6 +2478,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mara Blaga - Rick Prent - skalpa + - Pierre Foresi - Pieter Jordaan - Tournoud (damientournoud) - Michael Dowling (mtdowling) @@ -2543,6 +2553,7 @@ The Symfony Connect username in parenthesis allows to get more information - Cédric Anne - LubenZA - Flavian Sierk + - Rik van der Heijden - Michael Bessolov - Zdeněk Drahoš - Dan Harper @@ -2621,7 +2632,6 @@ The Symfony Connect username in parenthesis allows to get more information - Jakub Janata (janatjak) - Jibé Barth (jibbarth) - Matthew Foster (mfoster) - - Reyo Stallenberg (reyostallenberg) - Paul Seiffert (seiffert) - Vasily Khayrulin (sirian) - Stas Soroka (stasyan) @@ -2685,6 +2695,7 @@ The Symfony Connect username in parenthesis allows to get more information - Radek Wionczek (rwionczek) - Nick Stemerdink - David Stone + - Vincent Bouzeran - Grayson Koonce - Wissame MEKHILEF - Romain Dorgueil @@ -2792,6 +2803,7 @@ The Symfony Connect username in parenthesis allows to get more information - Adam - Ivo - Sören Bernstein + - michael.kubovic - devel - taiiiraaa - gedrox @@ -2982,6 +2994,7 @@ The Symfony Connect username in parenthesis allows to get more information - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) - Mokhtar Tlili (sf-djuba) + - Gregor Nathanael Meyer (spackmat) - Marcin Szepczynski (szepczynski) - Simone Di Maulo (toretto460) - Cyrille Jouineau (tuxosaurus) @@ -3100,6 +3113,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alexis BOYER - Kaipi Yann - adam-mospan + - nerdgod - Sam Williams - Guillaume Aveline - Adrian Philipp @@ -3184,6 +3198,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sam Anthony - Christian Stocker - Oussama Elgoumri + - Gert de Pagter - David Lima - Dawid Nowak - Lesnykh Ilia diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php index 9cff34b0a2835..b25de4312fc41 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php @@ -106,7 +106,10 @@ ->set('security.authentication.trust_resolver', AuthenticationTrustResolver::class) ->set('security.authentication.session_strategy', SessionAuthenticationStrategy::class) - ->args([param('security.authentication.session_strategy.strategy')]) + ->args([ + param('security.authentication.session_strategy.strategy'), + service('security.csrf.token_storage')->ignoreOnInvalid(), + ]) ->alias(SessionAuthenticationStrategyInterface::class, 'security.authentication.session_strategy') ->set('security.authentication.session_strategy_noop', SessionAuthenticationStrategy::class) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php index ad2fc0c63d1e0..72a4b7bb1502b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/CsrfFormLoginTest.php @@ -11,6 +11,12 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; + class CsrfFormLoginTest extends AbstractWebTestCase { /** @@ -20,6 +26,10 @@ public function testFormLoginAndLogoutWithCsrfTokens($options) { $client = $this->createClient($options); + $this->callInRequestContext($client, function () { + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); + }); + $form = $client->request('GET', '/login')->selectButton('login')->form(); $form['user_login[username]'] = 'johannes'; $form['user_login[password]'] = 'test'; @@ -40,6 +50,10 @@ public function testFormLoginAndLogoutWithCsrfTokens($options) $client->click($logoutLinks[0]); $this->assertRedirect($client->getResponse(), '/'); + + $this->callInRequestContext($client, function () { + $this->assertFalse(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + }); } /** @@ -49,6 +63,10 @@ public function testFormLoginWithInvalidCsrfToken($options) { $client = $this->createClient($options); + $this->callInRequestContext($client, function () { + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); + }); + $form = $client->request('GET', '/login')->selectButton('login')->form(); $form['user_login[_token]'] = ''; $client->submit($form); @@ -57,6 +75,10 @@ public function testFormLoginWithInvalidCsrfToken($options) $text = $client->followRedirect()->text(null, true); $this->assertStringContainsString('Invalid CSRF token.', $text); + + $this->callInRequestContext($client, function () { + $this->assertTrue(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); + }); } /** @@ -105,4 +127,22 @@ public function provideClientOptions() yield [['test_case' => 'CsrfFormLogin', 'root_config' => 'config.yml']]; yield [['test_case' => 'CsrfFormLogin', 'root_config' => 'routes_as_path.yml']]; } + + private function callInRequestContext(KernelBrowser $client, callable $callable): void + { + /** @var EventDispatcherInterface $eventDispatcher */ + $eventDispatcher = static::getContainer()->get(EventDispatcherInterface::class); + $wrappedCallable = function (RequestEvent $event) use (&$callable) { + $callable(); + $event->setResponse(new Response('')); + $event->stopPropagation(); + }; + + $eventDispatcher->addListener(KernelEvents::REQUEST, $wrappedCallable); + try { + $client->request('GET', '/'.uniqid('', true)); + } finally { + $eventDispatcher->removeListener(KernelEvents::REQUEST, $wrappedCallable); + } + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php index 72ed1be80d077..50473ed84e912 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php @@ -24,9 +24,6 @@ public function testCsrfTokensAreClearedOnLogout() { $client = $this->createClient(['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']); $client->disableReboot(); - $this->callInRequestContext($client, function () { - static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); - }); $client->request('POST', '/login', [ '_username' => 'johannes', @@ -34,8 +31,7 @@ public function testCsrfTokensAreClearedOnLogout() ]); $this->callInRequestContext($client, function () { - $this->assertTrue(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo')); - $this->assertSame('bar', static::getContainer()->get('security.csrf.token_storage')->getToken('foo')); + static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar'); }); $client->request('GET', '/logout'); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index f336cdae7dd69..0272b63276cb8 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -27,7 +27,7 @@ "symfony/password-hasher": "^5.4|^6.0", "symfony/security-core": "^6.2", "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^6.2" + "symfony/security-http": "^6.2.6" }, "require-dev": { "doctrine/annotations": "^1.10.4|^2", diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index cf0bd9ae244a0..7ecbf4e824839 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -272,6 +272,10 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a foreach ($parameters as $index => $parameter) { $this->defaultArgument->names[$index] = $parameter->name; + if (\array_key_exists($parameter->name, $arguments)) { + $arguments[$index] = $arguments[$parameter->name]; + unset($arguments[$parameter->name]); + } if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) { continue; } @@ -367,7 +371,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a // it's possible index 1 was set, then index 0, then 2, etc // make sure that we re-order so they're injected as expected - ksort($arguments); + ksort($arguments, \SORT_NATURAL); return $arguments; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php index 0039496d72ec4..6f9ea2efd603d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -171,10 +171,17 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed } } + $names = []; + foreach ($reflectionMethod->getParameters() as $key => $parameter) { + $names[$key] = $parameter->name; + if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { continue; } + if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name]) { + continue; + } $typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?'); @@ -205,8 +212,15 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed } } + foreach ($names as $key => $name) { + if (\array_key_exists($name, $arguments) && (0 === $key || \array_key_exists($key - 1, $arguments))) { + $arguments[$key] = $arguments[$name]; + unset($arguments[$name]); + } + } + if ($arguments !== $call[1]) { - ksort($arguments); + ksort($arguments, \SORT_NATURAL); $calls[$i][1] = $arguments; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 958c01ebec4ff..d74d2b27c1b46 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -1159,6 +1159,21 @@ public function testDecorationWithServiceAndAliasedInterface() static::assertInstanceOf(DecoratedDecorator::class, $container->get(DecoratorImpl::class)); } + public function testAutowireWithNamedArgs() + { + $container = new ContainerBuilder(); + + $container->register('foo', MultipleArgumentsOptionalScalar::class) + ->setArguments(['foo' => 'abc']) + ->setAutowired(true) + ->setPublic(true); + $container->register(A::class, A::class); + + (new AutowirePass())->process($container); + + $this->assertEquals([new TypedReference(A::class, A::class), 'abc'], $container->getDefinition('foo')->getArguments()); + } + public function testAutowireAttribute() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php index d6e9b344da349..497acee2f779c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -243,4 +243,24 @@ public function testBindWithTarget() $this->assertSame('bar', (string) $container->getDefinition('with_target')->getArgument(0)); } + + public function testBindWithNamedArgs() + { + $container = new ContainerBuilder(); + + $bindings = [ + '$apiKey' => new BoundArgument('K'), + ]; + + $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class); + $definition->setArguments(['c' => 'C', 'hostName' => 'H']); + $definition->setBindings($bindings); + + $container->register('foo', CaseSensitiveClass::class); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + + $this->assertEquals(['C', 'K', 'H'], $definition->getArguments()); + } } diff --git a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php index 4878dba990372..1c33ebc8e125e 100644 --- a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php +++ b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php @@ -38,22 +38,28 @@ public function registerClient(string $name, TraceableHttpClient $client) public function collect(Request $request, Response $response, \Throwable $exception = null) { + $this->lateCollect(); } public function lateCollect() { - $this->reset(); + $this->data['request_count'] = 0; + $this->data['error_count'] = 0; + $this->data += ['clients' => []]; foreach ($this->clients as $name => $client) { [$errorCount, $traces] = $this->collectOnClient($client); - $this->data['clients'][$name] = [ - 'traces' => $traces, - 'error_count' => $errorCount, + $this->data['clients'] += [ + $name => [ + 'traces' => [], + 'error_count' => 0, + ], ]; + $this->data['clients'][$name]['traces'] = array_merge($this->data['clients'][$name]['traces'], $traces); $this->data['request_count'] += \count($traces); - $this->data['error_count'] += $errorCount; + $this->data['error_count'] += $this->data['clients'][$name]['error_count'] += $errorCount; $client->reset(); } diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 746720ea78ea2..8f78d1b1d629a 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -72,7 +72,7 @@ public static function checkIp4(string $requestIp, string $ip): bool [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { - return self::$checkedIps[$cacheKey] = filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); + return self::$checkedIps[$cacheKey] = false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); } if ($netmask < 0 || $netmask > 32) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index 6085331b28bf3..5669f188a1e86 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -137,4 +137,21 @@ public function anonymizedIpData() ['::123.234.235.236', '::123.234.235.0'], // deprecated IPv4-compatible IPv6 address ]; } + + /** + * @dataProvider getIp4SubnetMaskZeroData + */ + public function testIp4SubnetMaskZero($matches, $remoteAddr, $cidr) + { + $this->assertSame($matches, IpUtils::checkIp4($remoteAddr, $cidr)); + } + + public function getIp4SubnetMaskZeroData() + { + return [ + [true, '1.2.3.4', '0.0.0.0/0'], + [true, '1.2.3.4', '192.168.1.0/0'], + [false, '1.2.3.4', '256.256.256/0'], // invalid CIDR notation + ]; + } } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index 0309db21a0dd8..01d010b812a0d 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -29,17 +29,28 @@ class Store implements StoreInterface private \SplObjectStorage $keyCache; /** @var array */ private array $locks = []; + private array $options; /** + * Constructor. + * + * The available options are: + * + * * private_headers Set of response headers that should not be stored + * when a response is cached. (default: Set-Cookie) + * * @throws \RuntimeException */ - public function __construct(string $root) + public function __construct(string $root, array $options = []) { $this->root = $root; if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); } $this->keyCache = new \SplObjectStorage(); + $this->options = array_merge([ + 'private_headers' => ['Set-Cookie'], + ], $options); } /** @@ -212,6 +223,10 @@ public function write(Request $request, Response $response): string $headers = $this->persistResponse($response); unset($headers['age']); + foreach ($this->options['private_headers'] as $h) { + unset($headers[strtolower($h)]); + } + array_unshift($entries, [$storedEnv, $headers]); if (!$this->save($key, serialize($entries))) { diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f6b86a8e3aef1..d8b37df0ceb88 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -75,11 +75,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.2.5'; - public const VERSION_ID = 60205; + public const VERSION = '6.2.6'; + public const VERSION_ID = 60206; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 2; - public const RELEASE_VERSION = 5; + public const RELEASE_VERSION = 6; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '07/2023'; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 2a7c8a0e469b2..014009e185bdd 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -12,8 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\Store; class StoreTest extends TestCase @@ -317,6 +319,17 @@ public function testPurgeHttpAndHttps() $this->assertEmpty($this->getStoreMetadata($requestHttps)); } + public function testDoesNotStorePrivateHeaders() + { + $request = Request::create('https://example.com/foo'); + $response = new Response('foo'); + $response->headers->setCookie(Cookie::fromString('foo=bar')); + + $this->store->write($request, $response); + $this->assertArrayNotHasKey('set-cookie', $this->getStoreMetadata($request)[0][1]); + $this->assertNotEmpty($response->headers->getCookies()); + } + protected function storeSimpleEntry($path = null, $headers = []) { $path ??= '/test'; diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentRememberMeHandler.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentRememberMeHandler.php index 1d68ef4d740de..d1046c55f5b8a 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentRememberMeHandler.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentRememberMeHandler.php @@ -34,7 +34,6 @@ final class PersistentRememberMeHandler extends AbstractRememberMeHandler { private TokenProviderInterface $tokenProvider; private ?TokenVerifierInterface $tokenVerifier; - private string $secret; public function __construct(TokenProviderInterface $tokenProvider, #[\SensitiveParameter] string $secret, UserProviderInterface $userProvider, RequestStack $requestStack, array $options, LoggerInterface $logger = null, TokenVerifierInterface $tokenVerifier = null) { @@ -45,7 +44,6 @@ public function __construct(TokenProviderInterface $tokenProvider, #[\SensitiveP } $this->tokenProvider = $tokenProvider; $this->tokenVerifier = $tokenVerifier; - $this->secret = $secret; } public function createRememberMeCookie(UserInterface $user): void diff --git a/src/Symfony/Component/Security/Http/RememberMe/RememberMeDetails.php b/src/Symfony/Component/Security/Http/RememberMe/RememberMeDetails.php index 76dc07504a229..0ae8bc0372cb5 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/RememberMeDetails.php +++ b/src/Symfony/Component/Security/Http/RememberMe/RememberMeDetails.php @@ -36,6 +36,9 @@ public function __construct(string $userFqcn, string $userIdentifier, int $expir public static function fromRawCookie(string $rawCookie): self { + if (!str_contains($rawCookie, self::COOKIE_DELIMITER)) { + $rawCookie = base64_decode($rawCookie); + } $cookieParts = explode(self::COOKIE_DELIMITER, $rawCookie, 4); if (4 !== \count($cookieParts)) { throw new AuthenticationException('The cookie contains invalid data.'); diff --git a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php index 0d4a310f3ddb8..7e555b0774a6c 100644 --- a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php +++ b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php @@ -13,6 +13,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface; /** * The default session strategy implementation. @@ -31,10 +32,15 @@ class SessionAuthenticationStrategy implements SessionAuthenticationStrategyInte public const INVALIDATE = 'invalidate'; private string $strategy; + private ?ClearableTokenStorageInterface $csrfTokenStorage = null; - public function __construct(string $strategy) + public function __construct(string $strategy, ClearableTokenStorageInterface $csrfTokenStorage = null) { $this->strategy = $strategy; + + if (self::MIGRATE === $strategy) { + $this->csrfTokenStorage = $csrfTokenStorage; + } } public function onAuthentication(Request $request, TokenInterface $token) @@ -44,10 +50,12 @@ public function onAuthentication(Request $request, TokenInterface $token) return; case self::MIGRATE: - // Note: this logic is duplicated in several authentication listeners - // until Symfony 5.0 due to a security fix with BC compat $request->getSession()->migrate(true); + if ($this->csrfTokenStorage) { + $this->csrfTokenStorage->clear(); + } + return; case self::INVALIDATE: diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentRememberMeHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentRememberMeHandlerTest.php index da4f26eaaf6d4..76472b1d5733c 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentRememberMeHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/PersistentRememberMeHandlerTest.php @@ -156,4 +156,19 @@ public function testConsumeRememberMeCookieExpired() $this->handler->consumeRememberMeCookie(new RememberMeDetails(InMemoryUser::class, 'wouter', 360, 'series1:tokenvalue')); } + + public function testBase64EncodedTokens() + { + $this->tokenProvider->expects($this->any()) + ->method('loadTokenBySeries') + ->with('series1') + ->willReturn(new PersistentToken(InMemoryUser::class, 'wouter', 'series1', 'tokenvalue', new \DateTime('-10 min'))) + ; + + $this->tokenProvider->expects($this->once())->method('updateToken')->with('series1'); + + $rememberMeDetails = new RememberMeDetails(InMemoryUser::class, 'wouter', 360, 'series1:tokenvalue'); + $rememberMeDetails = RememberMeDetails::fromRawCookie(base64_encode($rememberMeDetails->toString())); + $this->handler->consumeRememberMeCookie($rememberMeDetails); + } } diff --git a/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php b/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php index 69953ae6fd14e..b52b2f5a522c8 100644 --- a/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Csrf\TokenStorage\ClearableTokenStorageInterface; use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy; class SessionAuthenticationStrategyTest extends TestCase @@ -57,6 +58,18 @@ public function testSessionIsInvalidated() $strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class)); } + public function testCsrfTokensAreCleared() + { + $session = $this->createMock(SessionInterface::class); + $session->expects($this->once())->method('migrate')->with($this->equalTo(true)); + + $csrfStorage = $this->createMock(ClearableTokenStorageInterface::class); + $csrfStorage->expects($this->once())->method('clear'); + + $strategy = new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE, $csrfStorage); + $strategy->onAuthentication($this->getRequest($session), $this->createMock(TokenInterface::class)); + } + private function getRequest($session = null) { $request = $this->createMock(Request::class); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy