aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
authorRoeland Jago Douma <rullzer@users.noreply.github.com>2020-03-31 22:17:40 +0200
committerGitHub <noreply@github.com>2020-03-31 22:17:40 +0200
commitb39fb55ee0b4bc4c4bd0fcedca3f836a17586495 (patch)
tree17089677aeeace2d6e4c488b0a0558be69564430 /lib/private
parent09d56e9d3db7893a73b32d7cc420dcb450f1bb79 (diff)
parent84f3d2ddebbda3d565a61f38d9d79e66072ab692 (diff)
downloadnextcloud-server-b39fb55ee0b4bc4c4bd0fcedca3f836a17586495.tar.gz
nextcloud-server-b39fb55ee0b4bc4c4bd0fcedca3f836a17586495.zip
Merge pull request #19845 from nextcloud/enh/events/loginFailedEvent
Event for failed login attempts
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/Authentication/Events/LoginFailed.php43
-rw-r--r--lib/private/Authentication/Listeners/LoginFailedListener.php64
-rw-r--r--lib/private/Authentication/Login/LoggedInCheckCommand.php18
-rw-r--r--lib/private/Server.php6
-rw-r--r--lib/private/User/Session.php8
5 files changed, 135 insertions, 4 deletions
diff --git a/lib/private/Authentication/Events/LoginFailed.php b/lib/private/Authentication/Events/LoginFailed.php
new file mode 100644
index 00000000000..cc5a547fdef
--- /dev/null
+++ b/lib/private/Authentication/Events/LoginFailed.php
@@ -0,0 +1,43 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020, 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\Events;
+
+use OCP\EventDispatcher\Event;
+
+class LoginFailed extends Event {
+
+ /** @var string */
+ private $loginName;
+
+ public function __construct(string $loginName) {
+ parent::__construct();
+
+ $this->loginName = $loginName;
+ }
+
+ public function getLoginName(): string {
+ return $this->loginName;
+ }
+}
diff --git a/lib/private/Authentication/Listeners/LoginFailedListener.php b/lib/private/Authentication/Listeners/LoginFailedListener.php
new file mode 100644
index 00000000000..d4f46d9547f
--- /dev/null
+++ b/lib/private/Authentication/Listeners/LoginFailedListener.php
@@ -0,0 +1,64 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020, 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\Listeners;
+
+use OC\Authentication\Events\LoginFailed;
+use OCP\Authentication\Events\LoginFailedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IUserManager;
+use OCP\Util;
+
+class LoginFailedListener implements IEventListener {
+
+ /** @var IEventDispatcher */
+ private $dispatcher;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ public function __construct(IEventDispatcher $dispatcher, IUserManager $userManager) {
+ $this->dispatcher = $dispatcher;
+ $this->userManager = $userManager;
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof LoginFailed)) {
+ return;
+ }
+
+ $uid = $event->getLoginName();
+ Util::emitHook(
+ '\OCA\Files_Sharing\API\Server2Server',
+ 'preLoginNameUsedAsUserName',
+ ['uid' => &$uid]
+ );
+ if($this->userManager->userExists($uid)) {
+ $this->dispatcher->dispatchTyped(new LoginFailedEvent($uid));
+ }
+ }
+
+}
diff --git a/lib/private/Authentication/Login/LoggedInCheckCommand.php b/lib/private/Authentication/Login/LoggedInCheckCommand.php
index 9c1e45e0db7..78f27bfa937 100644
--- a/lib/private/Authentication/Login/LoggedInCheckCommand.php
+++ b/lib/private/Authentication/Login/LoggedInCheckCommand.php
@@ -25,24 +25,36 @@ declare(strict_types=1);
namespace OC\Authentication\Login;
+use OC\Authentication\Events\LoginFailed;
use OC\Core\Controller\LoginController;
+use OCP\Authentication\Events\LoginFailedEvent;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
+use OCP\IUserManager;
+use OCP\Util;
class LoggedInCheckCommand extends ALoginCommand {
/** @var ILogger */
private $logger;
+ /** @var IEventDispatcher */
+ private $dispatcher;
+ /** @var IUserManager */
+ private $userManager;
- public function __construct(ILogger $logger) {
+ public function __construct(ILogger $logger, IEventDispatcher $dispatcher) {
$this->logger = $logger;
+ $this->dispatcher = $dispatcher;
}
public function process(LoginData $loginData): LoginResult {
if ($loginData->getUser() === false) {
- $username = $loginData->getUsername();
+ $loginName = $loginData->getUsername();
$ip = $loginData->getRequest()->getRemoteAddress();
- $this->logger->warning("Login failed: $username (Remote IP: $ip)");
+ $this->logger->warning("Login failed: $loginName (Remote IP: $ip)");
+
+ $this->dispatcher->dispatchTyped(new LoginFailed($loginName));
return LoginResult::failure($loginData, LoginController::LOGIN_MSG_INVALIDPASSWORD);
}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 27268981c2b..b9155563c0f 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -62,6 +62,8 @@ use OC\App\AppStore\Fetcher\CategoryFetcher;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Utility\SimpleContainer;
use OC\AppFramework\Utility\TimeFactory;
+use OC\Authentication\Events\LoginFailed;
+use OC\Authentication\Listeners\LoginFailedListener;
use OC\Authentication\LoginCredentials\Store;
use OC\Authentication\Token\IProvider;
use OC\Avatar\AvatarManager;
@@ -1416,6 +1418,10 @@ class Server extends ServerContainer implements IServerContainer {
// no avatar to remove
}
});
+
+ /** @var IEventDispatcher $eventDispatched */
+ $eventDispatched = $this->query(IEventDispatcher::class);
+ $eventDispatched->addServiceListener(LoginFailed::class, LoginFailedListener::class);
}
/**
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 3d97ddce7f9..9129fb7054b 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -51,6 +51,7 @@ use OC_User;
use OC_Util;
use OCA\DAV\Connector\Sabre\Auth;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Authentication\Events\LoginFailedEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\NotPermittedException;
use OCP\IConfig;
@@ -58,6 +59,7 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
+use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Lockdown\ILockdownManager;
use OCP\Security\ISecureRandom;
@@ -137,7 +139,8 @@ class Session implements IUserSession, Emitter {
ISecureRandom $random,
ILockdownManager $lockdownManager,
ILogger $logger,
- IEventDispatcher $dispatcher) {
+ IEventDispatcher $dispatcher
+ ) {
$this->manager = $manager;
$this->session = $session;
$this->timeFactory = $timeFactory;
@@ -467,6 +470,9 @@ class Session implements IUserSession, Emitter {
$this->logger->warning('Login failed: \'' . $user . '\' (Remote IP: \'' . \OC::$server->getRequest()->getRemoteAddress() . '\')', ['app' => 'core']);
$throttler->registerAttempt('login', $request->getRemoteAddress(), ['user' => $user]);
+
+ $this->dispatcher->dispatchTyped(new OC\Authentication\Events\LoginFailed($user));
+
if ($currentDelay === 0) {
$throttler->sleepDelay($request->getRemoteAddress(), 'login');
}