diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2018-09-10 17:02:37 +0200 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2018-09-25 09:54:20 +0200 |
commit | 7586b19e524761c1e8aab5170375a0d6c9e8f7a2 (patch) | |
tree | e2a0fc5fa9754c12cfd226bf7aa48964fce18237 /lib/private/Authentication | |
parent | 92fa373314e77dc905036812253f6b776a9e1aaf (diff) | |
download | nextcloud-server-7586b19e524761c1e8aab5170375a0d6c9e8f7a2.tar.gz nextcloud-server-7586b19e524761c1e8aab5170375a0d6c9e8f7a2.zip |
Only allow 2FA state changs if providers support the operation
Ref https://github.com/nextcloud/server/issues/11019.
Add `twofactorauth:cleanup` command
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib/private/Authentication')
5 files changed, 149 insertions, 25 deletions
diff --git a/lib/private/Authentication/Exceptions/InvalidProviderException.php b/lib/private/Authentication/Exceptions/InvalidProviderException.php new file mode 100644 index 00000000000..6cdd0947509 --- /dev/null +++ b/lib/private/Authentication/Exceptions/InvalidProviderException.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Authentication\Exceptions; + +use Exception; +use Throwable; + +class InvalidProviderException extends Exception { + + public function __construct(string $providerId, Throwable $previous = null) { + parent::__construct("The provider '$providerId' does not exist'", 0, $previous); + } + +} diff --git a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php index ce03eb09661..d8299a335a3 100644 --- a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php +++ b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php @@ -93,4 +93,13 @@ class ProviderUserAssignmentDao { } + public function deleteAll(string $providerId) { + $qb = $this->conn->getQueryBuilder(); + + $deleteQuery = $qb->delete(self::TABLE_NAME) + ->where($qb->expr()->eq('provider_id', $qb->createNamedParameter($providerId))); + + $deleteQuery->execute(); + } + } diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php index 6fa41897e1e..71cc5874e5d 100644 --- a/lib/private/Authentication/TwoFactorAuth/Manager.php +++ b/lib/private/Authentication/TwoFactorAuth/Manager.php @@ -100,12 +100,6 @@ class Manager { * @return boolean */ public function isTwoFactorAuthenticated(IUser $user): bool { - $twoFactorEnabled = ((int) $this->config->getUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 0)) === 0; - - if (!$twoFactorEnabled) { - return false; - } - $providerStates = $this->providerRegistry->getProviderStates($user); $providers = $this->providerLoader->getProviders($user); $fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user); @@ -113,25 +107,7 @@ class Manager { $providerIds = array_keys($enabled); $providerIdsWithoutBackupCodes = array_diff($providerIds, [self::BACKUP_CODES_PROVIDER_ID]); - return $twoFactorEnabled && !empty($providerIdsWithoutBackupCodes); - } - - /** - * Disable 2FA checks for the given user - * - * @param IUser $user - */ - public function disableTwoFactorAuthentication(IUser $user) { - $this->config->setUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 1); - } - - /** - * Enable all 2FA checks for the given user - * - * @param IUser $user - */ - public function enableTwoFactorAuthentication(IUser $user) { - $this->config->deleteUserValue($user->getUID(), 'core', 'two_factor_auth_disabled'); + return !empty($providerIdsWithoutBackupCodes); } /** diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderManager.php b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php new file mode 100644 index 00000000000..234085b062d --- /dev/null +++ b/lib/private/Authentication/TwoFactorAuth/ProviderManager.php @@ -0,0 +1,98 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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 <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Authentication\TwoFactorAuth; + +use OC\Authentication\Exceptions\InvalidProviderException; +use OCP\Authentication\TwoFactorAuth\IActivatableByAdmin; +use OCP\Authentication\TwoFactorAuth\IDeactivableByAdmin; +use OCP\Authentication\TwoFactorAuth\IDeactivatableByAdmin; +use OCP\Authentication\TwoFactorAuth\IProvider; +use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\IUser; + +class ProviderManager { + + /** @var ProviderLoader */ + private $providerLoader; + + /** @var IRegistry */ + private $providerRegistry; + + public function __construct(ProviderLoader $providerLoader, IRegistry $providerRegistry) { + $this->providerLoader = $providerLoader; + $this->providerRegistry = $providerRegistry; + } + + private function getProvider(string $providerId, IUser $user): IProvider { + $providers = $this->providerLoader->getProviders($user); + + if (!isset($providers[$providerId])) { + throw new InvalidProviderException($providerId); + } + + return $providers[$providerId]; + } + + /** + * Try to enable the provider with the given id for the given user + * + * @param IUser $user + * + * @return bool whether the provider supports this operation + */ + public function tryEnableProviderFor(string $providerId, IUser $user): bool { + $provider = $this->getProvider($providerId, $user); + + if ($provider instanceof IActivatableByAdmin) { + $provider->enableFor($user); + $this->providerRegistry->enableProviderFor($provider, $user); + return true; + } else { + return false; + } + } + + /** + * Try to disable the provider with the given id for the given user + * + * @param IUser $user + * + * @return bool whether the provider supports this operation + */ + public function tryDisableProviderFor(string $providerId, IUser $user): bool { + $provider = $this->getProvider($providerId, $user); + + if ($provider instanceof IDeactivatableByAdmin) { + $provider->disableFor($user); + $this->providerRegistry->disableProviderFor($provider, $user); + return true; + } else { + return false; + } + } + +} diff --git a/lib/private/Authentication/TwoFactorAuth/Registry.php b/lib/private/Authentication/TwoFactorAuth/Registry.php index 0cfb052440e..2fc90e5d6d9 100644 --- a/lib/private/Authentication/TwoFactorAuth/Registry.php +++ b/lib/private/Authentication/TwoFactorAuth/Registry.php @@ -52,4 +52,7 @@ class Registry implements IRegistry { $this->assignmentDao->persist($provider->getId(), $user->getUID(), 0); } + public function cleanUp(string $providerId) { + $this->assignmentDao->deleteAll($providerId); + } } |