Skip to content

Commit

Permalink
[PoC] Disable account after failed login attempts
Browse files Browse the repository at this point in the history
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
  • Loading branch information
rullzer committed Apr 21, 2020
1 parent 7e8175c commit a5b11ed
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
use OCA\Password_Policy\Capabilities;
use OCA\Password_Policy\Generator;
use OCA\Password_Policy\HistoryCompliance;
use OCA\Password_Policy\Listener\FailedLoginListener;
use OCA\Password_Policy\PasswordValidator;
use OCP\AppFramework\App;
use OCP\Authentication\Events\LoginFailedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
Expand Down Expand Up @@ -97,6 +99,8 @@ function (Event $event) use ($container) {
}
);

$eventDispatcher->addServiceListener(LoginFailedEvent::class, FailedLoginListener::class);

// TODO: remove these two legacy event listeners
$symfonyDispatcher = $server->getEventDispatcher();
$symfonyDispatcher->addListener(
Expand Down
80 changes: 80 additions & 0 deletions lib/FailedLoginCompliance.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?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 OCA\Password_Policy;

use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;

class FailedLoginCompliance {

/** @var IConfig */
private $config;

/** @var IUserManager */
private $userManager;

/** @var PasswordPolicyConfig */
private $passwordPolicyConfig;

public function __construct(
IConfig $config,
IUserManager $userManager,
PasswordPolicyConfig $passwordPolicyConfig) {
$this->config = $config;
$this->userManager = $userManager;
$this->passwordPolicyConfig = $passwordPolicyConfig;
}

public function failedLogin(string $uid) {
$user = $this->userManager->get($uid);

if (!($user instanceof IUser)) {
return;
}

$allowedAttempts = $this->passwordPolicyConfig->getMaximumLoginAttempts();

$attempts = $this->getAttempts($uid);
$attempts++;

if ($attempts >= $allowedAttempts) {
$this->setAttempts($uid, 0);
$user->setEnabled(false);
}
}

public function sucessfullLogin(IUser $user) {
$this->setAttempts($user->getUID(), 0);
}

private function getAttempts(string $uid): int {
return (int)$this->config->getUserValue($uid, 'password_policy', 'failedLoginAttempts', 0);
}

private function setAttempts(string $uid, int $attempts) {
return $this->config->setUserValue($uid, 'password_policy', 'failedLoginAttempts', $attempts);
}
}
49 changes: 49 additions & 0 deletions lib/Listeners/FailedLoginListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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 OCA\Password_Policy\Listener;

use OCA\Password_Policy\FailedLoginCompliance;
use OCP\Authentication\Events\LoginFailedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;

class FailedLoginListener implements IEventListener {

/** @var FailedLoginCompliance */
private $compliance;

public function __construct(FailedLoginCompliance $compliance) {
$this->compliance = $compliance;
}

public function handle(Event $event): void {
if (!($event instanceof LoginFailedEvent)) {
return;
}

$this->compliance->failedLogin($event->getUid());
}

}
48 changes: 48 additions & 0 deletions lib/Listeners/SuccesfullLoginListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?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 OCA\Password_Policy\Listener;

use OCA\Password_Policy\FailedLoginCompliance;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\User\Events\UserLoggedInEvent;

class SuccesfullLoginListener implements IEventListener {
/** @var FailedLoginCompliance */
private $compliance;

public function __construct(FailedLoginCompliance $compliance) {
$this->compliance = $compliance;
}

public function handle(Event $event): void {
if (!($event instanceof UserLoggedInEvent)) {
return;
}

$this->compliance->sucessfullLogin($event->getUser());
}

}
15 changes: 15 additions & 0 deletions lib/PasswordPolicyConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,19 @@ public function getHistorySize(): int {
);
}


public function setMaximumLoginAttempts(int $attempts) {
$this->config->setAppValue('password_policy', 'maximumLoginAttempts', $attempts);
}

/**
* @return int if 0 then there is no limit
*/
public function getMaximumLoginAttempts(): int {
return (int)$this->config->getAppValue(
'password_policy',
'maximumLoginAttempts',
0
);
}
}
38 changes: 38 additions & 0 deletions lib/Validator/UserNameValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?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 OCA\Password_Policy\Validator;

use OC\HintException;

class UserNameValidator implements IValidator {

public function __construct() {
}

public function validate(string $password): void {
// TODO: Implement validate() method.
}

}

0 comments on commit a5b11ed

Please sign in to comment.