diff options
Diffstat (limited to 'lib/private/Authentication/Token')
-rw-r--r-- | lib/private/Authentication/Token/IProvider.php | 3 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IToken.php | 1 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IWipeableToken.php | 29 | ||||
-rw-r--r-- | lib/private/Authentication/Token/Manager.php | 5 | ||||
-rw-r--r-- | lib/private/Authentication/Token/PublicKeyToken.php | 6 | ||||
-rw-r--r-- | lib/private/Authentication/Token/PublicKeyTokenProvider.php | 9 | ||||
-rw-r--r-- | lib/private/Authentication/Token/RemoteWipe.php | 149 |
7 files changed, 201 insertions, 1 deletions
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php index 21223cecdf7..e4403196583 100644 --- a/lib/private/Authentication/Token/IProvider.php +++ b/lib/private/Authentication/Token/IProvider.php @@ -29,6 +29,7 @@ namespace OC\Authentication\Token; use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; +use OC\Authentication\Exceptions\WipeTokenException; interface IProvider { @@ -59,6 +60,7 @@ interface IProvider { * @param string $tokenId * @throws InvalidTokenException * @throws ExpiredTokenException + * @throws WipeTokenException * @return IToken */ public function getToken(string $tokenId): IToken; @@ -69,6 +71,7 @@ interface IProvider { * @param int $tokenId * @throws InvalidTokenException * @throws ExpiredTokenException + * @throws WipeTokenException * @return IToken */ public function getTokenById(int $tokenId): IToken; diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php index e122ec02764..c01cf43fe93 100644 --- a/lib/private/Authentication/Token/IToken.php +++ b/lib/private/Authentication/Token/IToken.php @@ -30,6 +30,7 @@ interface IToken extends JsonSerializable { const TEMPORARY_TOKEN = 0; const PERMANENT_TOKEN = 1; + const WIPE_TOKEN = 2; const DO_NOT_REMEMBER = 0; const REMEMBER = 1; diff --git a/lib/private/Authentication/Token/IWipeableToken.php b/lib/private/Authentication/Token/IWipeableToken.php new file mode 100644 index 00000000000..8d4d3a60781 --- /dev/null +++ b/lib/private/Authentication/Token/IWipeableToken.php @@ -0,0 +1,29 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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\Token; + +interface IWipeableToken { + public function wipe(): void; +} diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php index 3174599221d..c49bd1b1e19 100644 --- a/lib/private/Authentication/Token/Manager.php +++ b/lib/private/Authentication/Token/Manager.php @@ -26,6 +26,7 @@ namespace OC\Authentication\Token; use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; +use OC\Authentication\Exceptions\WipeTokenException; class Manager implements IProvider { @@ -113,6 +114,8 @@ class Manager implements IProvider { public function getToken(string $tokenId): IToken { try { return $this->publicKeyTokenProvider->getToken($tokenId); + } catch (WipeTokenException $e) { + throw $e; } catch (ExpiredTokenException $e) { throw $e; } catch(InvalidTokenException $e) { @@ -143,6 +146,8 @@ class Manager implements IProvider { return $this->publicKeyTokenProvider->getTokenById($tokenId); } catch (ExpiredTokenException $e) { throw $e; + } catch (WipeTokenException $e) { + throw $e; } catch (InvalidTokenException $e) { return $this->defaultTokenProvider->getTokenById($tokenId); } diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php index b3d87fea7ea..c575273d7bd 100644 --- a/lib/private/Authentication/Token/PublicKeyToken.php +++ b/lib/private/Authentication/Token/PublicKeyToken.php @@ -44,7 +44,7 @@ use OCP\AppFramework\Db\Entity; * @method void setVersion(int $version) * @method bool getPasswordInvalid() */ -class PublicKeyToken extends Entity implements INamedToken { +class PublicKeyToken extends Entity implements INamedToken, IWipeableToken { const VERSION = 2; @@ -226,4 +226,8 @@ class PublicKeyToken extends Entity implements INamedToken { public function setPasswordInvalid(bool $invalid) { parent::setPasswordInvalid($invalid); } + + public function wipe(): void { + parent::setType(IToken::WIPE_TOKEN); + } } diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php index fa9f11a65ab..6e6d7acf242 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php +++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php @@ -26,6 +26,7 @@ namespace OC\Authentication\Token; use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; +use OC\Authentication\Exceptions\WipeTokenException; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; @@ -85,6 +86,10 @@ class PublicKeyTokenProvider implements IProvider { throw new ExpiredTokenException($token); } + if ($token->getType() === IToken::WIPE_TOKEN) { + throw new WipeTokenException($token); + } + return $token; } @@ -99,6 +104,10 @@ class PublicKeyTokenProvider implements IProvider { throw new ExpiredTokenException($token); } + if ($token->getType() === IToken::WIPE_TOKEN) { + throw new WipeTokenException($token); + } + return $token; } diff --git a/lib/private/Authentication/Token/RemoteWipe.php b/lib/private/Authentication/Token/RemoteWipe.php new file mode 100644 index 00000000000..6091d30fc25 --- /dev/null +++ b/lib/private/Authentication/Token/RemoteWipe.php @@ -0,0 +1,149 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 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\Token; + +use BadMethodCallException; +use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Exceptions\WipeTokenException; +use OCP\Activity\IManager as IActivityManager; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\ILogger; +use OCP\Notification\IManager as INotificationManager; + +class RemoteWipe { + + /** @var IProvider */ + private $tokenProvider; + + /** @var IActivityManager */ + private $activityManager; + + /** @var INotificationManager */ + private $notificationManager; + + /** @var ITimeFactory */ + private $timeFactory; + + /** @var ILogger */ + private $logger; + + public function __construct(IProvider $tokenProvider, + IActivityManager $activityManager, + INotificationManager $notificationManager, + ITimeFactory $timeFactory, + ILogger $logger) { + $this->tokenProvider = $tokenProvider; + $this->activityManager = $activityManager; + $this->notificationManager = $notificationManager; + $this->timeFactory = $timeFactory; + $this->logger = $logger; + } + + /** + * @param string $token + * + * @return bool whether wiping was started + * @throws InvalidTokenException + * + */ + public function start(string $token): bool { + try { + $this->tokenProvider->getToken($token); + + // We expect a WipedTokenException here. If we reach this point this + // is an ordinary token + return false; + } catch (WipeTokenException $e) { + // Expected -> continue below + } + + $dbToken = $e->getToken(); + + $this->logger->info("user " . $dbToken->getUID() . " started a remote wipe"); + $this->sendNotification('remote_wipe_start', $e->getToken()); + $this->publishActivity('remote_wipe_start', $e->getToken()); + + return true; + } + + /** + * @param string $token + * + * @return bool whether wiping could be finished + * @throws InvalidTokenException + */ + public function finish(string $token): bool { + try { + $this->tokenProvider->getToken($token); + + // We expect a WipedTokenException here. If we reach this point this + // is an ordinary token + return false; + } catch (WipeTokenException $e) { + // Expected -> continue below + } + + $dbToken = $e->getToken(); + + $this->tokenProvider->invalidateToken($token); + + $this->logger->info("user " . $dbToken->getUID() . " finished a remote wipe"); + $this->sendNotification('remote_wipe_finish', $e->getToken()); + $this->publishActivity('remote_wipe_finish', $e->getToken()); + + return true; + } + + private function publishActivity(string $event, IToken $token): void { + $activity = $this->activityManager->generateEvent(); + $activity->setApp('core') + ->setType('security') + ->setAuthor($token->getUID()) + ->setAffectedUser($token->getUID()) + ->setSubject($event, [ + 'name' => $token->getName(), + ]); + try { + $this->activityManager->publish($activity); + } catch (BadMethodCallException $e) { + $this->logger->warning('could not publish activity', ['app' => 'core']); + $this->logger->logException($e, ['app' => 'core']); + } + } + + private function sendNotification(string $event, IToken $token): void { + $notification = $this->notificationManager->createNotification(); + $notification->setApp('auth') + ->setUser($token->getUID()) + ->setDateTime($this->timeFactory->getDateTime()) + ->setObject('token', $token->getId()) + ->setSubject($event, [ + 'name' => $token->getName(), + ]); + $this->notificationManager->notify($notification); + } + +} |