diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 1ebd60567a6..a19d83121e0 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -147,10 +147,18 @@ public function index($token = '', $callUser = '', $password = '') { } if ($requirePassword) { - if ($password !== '' && $room->verifyPassword($password)) { + + $passwordVerification = $room->verifyPassword($password); + + if ($passwordVerification['result']) { $this->session->setPasswordForRoom($token, $token); } else { - return new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + if ($passwordVerification['url'] === '') { + return new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + } + else { + return new RedirectResponse($passwordVerification['url']); + } } } } @@ -194,10 +202,22 @@ protected function guestEnterRoom($token, $password) { $this->session->removePasswordForRoom($token); if ($room->hasPassword()) { - if ($password !== '' && $room->verifyPassword($password)) { + $passwordVerification = [ + 'result' => false, + 'url' => '' + ]; + + $passwordVerification = $room->verifyPassword($password); + + if ($passwordVerification['result']) { $this->session->setPasswordForRoom($token, $token); } else { - return new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + if ($passwordVerification['url'] == '') { + return new TemplateResponse($this->appName, 'authenticate', [], 'guest'); + } + else { + return new RedirectResponse($passwordVerification['url']); + } } } diff --git a/lib/Room.php b/lib/Room.php index b0c61ab7b5b..cc8f5082df7 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -516,7 +516,7 @@ public function joinRoom($userId, $password, $passedPasswordProtection = false) $result = $query->execute(); if ($result === 0) { - if (!$passedPasswordProtection && !$this->verifyPassword($password)) { + if (!$passedPasswordProtection && !$this->verifyPassword($password)['result']) { throw new InvalidPasswordException(); } @@ -575,7 +575,7 @@ public function leaveRoom($userId) { public function joinRoomGuest($password, $passedPasswordProtection = false) { $this->dispatcher->dispatch(self::class . '::preJoinRoomGuest', new GenericEvent($this)); - if (!$passedPasswordProtection && !$this->verifyPassword($password)) { + if (!$passedPasswordProtection && !$this->verifyPassword($password)['result']) { throw new InvalidPasswordException(); } @@ -595,6 +595,7 @@ public function joinRoomGuest($password, $passedPasswordProtection = false) { return $sessionId; } + /** * @param string $sessionId * @param bool $active @@ -633,7 +634,23 @@ public function changeInCall($sessionId, $active) { * @return bool */ public function verifyPassword($password) { - return !$this->hasPassword() || $this->hasher->verify($password, $this->password); + $event = new GenericEvent($this, [ + 'password' => $password + ]); + $this->dispatcher->dispatch(self::class . '::verifyPassword', $event); + if ($event->hasArgument('result')) { + $result = $event->getArgument('result'); + return [ + 'result' => $result['result'] ?? false, + 'url' => $result['url'] ?? '' + ]; + } + + $passwordVerification = [ + 'result' => !$this->hasPassword() || $this->hasher->verify($password, $this->password), + 'url' => '' + ]; + return $passwordVerification; } /** diff --git a/tests/php/PasswordVerificationTest.php b/tests/php/PasswordVerificationTest.php new file mode 100644 index 00000000000..a8943192a38 --- /dev/null +++ b/tests/php/PasswordVerificationTest.php @@ -0,0 +1,64 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\Spreed\Tests\php; + +use OCA\Spreed\Config; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IConfig; +use OCP\Security\IHasher; +use OCP\Security\ISecureRandom; +use Test\TestCase; +use Symfony\Component\EventDispatcher\GenericEvent; + +/** + * @group DB + */ +class PasswordVerificationTest extends TestCase { + + public function testVerifyPassword() { + $dispatcher = \OC::$server->getEventDispatcher(); + + $dispatcher->addListener('OCA\Spreed\Room::verifyPassword', function(GenericEvent $event) { + $password = $event->getArgument('password'); + $room = $event->getSubject(); + $hasPassword = $room->hasPassword(); + + if ($password == "1234") { + $event->setArgument('result', [ 'result' => true, 'url' => '']); + } + else { + $event->setArgument('result', [ 'result' => false, 'url' => 'https://test']); + } + }); + + $secureRandom = \OC::$server->getSecureRandom(); + $config = \OC::$server->getConfig(); + + $dbConnection = \OC::$server->getDatabaseConnection(); + $dispatcher = \OC::$server->getEventDispatcher(); + $manager = new Manager($dbConnection, $config, $secureRandom, $dispatcher, $this->createMock(IHasher::class)); + $room = $manager->createPublicRoom(); + $verificationResult = $room->verifyPassword('1234'); + $this->assertSame($verificationResult, ['result' => true, 'url' => '']); + $verificationResult = $room->verifyPassword('4321'); + $this->assertSame($verificationResult, ['result' => false, 'url' => 'https://test']); + } +}