diff options
author | Roeland Jago Douma <roeland@famdouma.nl> | 2019-08-12 22:35:56 +0300 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2019-08-27 15:52:50 +0300 |
commit | f503912e56eea8c9259d8a5e0260969d48ee0fce (patch) | |
tree | 649cec152e4d094f00dcc48fe8c1b2b85042d8c2 /lib | |
parent | 133ee794750cc2d68a7d676900a26470b3e510d2 (diff) |
Split all the validators
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PasswordValidator.php | 189 | ||||
-rw-r--r-- | lib/Validator/CommonPasswordsValidator.php | 60 | ||||
-rw-r--r-- | lib/Validator/HIBPValidator.php | 80 | ||||
-rw-r--r-- | lib/Validator/IValidator.php | 38 | ||||
-rw-r--r-- | lib/Validator/LengthValidator.php | 54 | ||||
-rw-r--r-- | lib/Validator/NumericCharacterValidator.php | 56 | ||||
-rw-r--r-- | lib/Validator/SpecialCharactersValidator.php | 54 | ||||
-rw-r--r-- | lib/Validator/UpperCaseLoweCaseValidator.php | 56 |
8 files changed, 427 insertions, 160 deletions
diff --git a/lib/PasswordValidator.php b/lib/PasswordValidator.php index c5293e9..fa8d081 100644 --- a/lib/PasswordValidator.php +++ b/lib/PasswordValidator.php @@ -25,33 +25,23 @@ namespace OCA\Password_Policy; use OC\HintException; -use OCP\Http\Client\IClientService; -use OCP\IL10N; +use OCA\Password_Policy\Validator\CommonPasswordsValidator; +use OCA\Password_Policy\Validator\HIBPValidator; +use OCA\Password_Policy\Validator\IValidator; +use OCA\Password_Policy\Validator\LengthValidator; +use OCA\Password_Policy\Validator\NumericCharacterValidator; +use OCA\Password_Policy\Validator\SpecialCharactersValidator; +use OCA\Password_Policy\Validator\UpperCaseLoweCaseValidator; +use OCP\AppFramework\IAppContainer; +use OCP\AppFramework\QueryException; class PasswordValidator { - /** @var PasswordPolicyConfig */ - private $config; + /** @var IAppContainer */ + private $container; - /** @var IL10N */ - private $l; - - /** @var IClientService */ - private $clientService; - - /** - * PasswordValidator constructor. - * - * @param PasswordPolicyConfig $config - * @param IL10N $l - * @param IClientService $clientService - */ - public function __construct(PasswordPolicyConfig $config, - IL10N $l, - IClientService $clientService) { - $this->config = $config; - $this->l = $l; - $this->clientService = $clientService; + public function __construct(IAppContainer $container) { + $this->container = $container; } /** @@ -60,146 +50,25 @@ class PasswordValidator { * @param string $password * @throws HintException */ - public function validate($password) { - $this->checkCommonPasswords($password); - $this->checkPasswordLength($password); - $this->checkNumericCharacters($password); - $this->checkUpperLowerCase($password); - $this->checkSpecialCharacters($password); - $this->checkHaveIBeenPwned($password); - } - - /** - * check if password matches the minimum length defined by the admin - * - * @param string $password - * @throws HintException - */ - protected function checkPasswordLength($password) { - $minLength = $this->config->getMinLength(); - if(strlen($password) < $minLength) { - $message = 'Password needs to be at least ' . $minLength . ' characters long'; - $message_t = $this->l->t( - 'Password needs to be at least %s characters long', [$minLength] - ); - throw new HintException($message, $message_t); - } - } - - /** - * check if password contain at least one upper and one lower case character - * - * @param string $password - * @throws HintException - */ - protected function checkUpperLowerCase($password) { - $enforceUpperLowerCase = $this->config->getEnforceUpperLowerCase(); - if($enforceUpperLowerCase) { - if (preg_match('/^(?=.*[a-z])(?=.*[A-Z]).+$/', $password) !== 1) { - $message = 'Password needs to contain at least one lower and one upper case character.'; - $message_t = $this->l->t( - 'Password needs to contain at least one lower and one upper case character.' - ); - throw new HintException($message, $message_t); - } - } - } - - /** - * check if password contain at least one numeric character - * - * @param string $password - * @throws HintException - */ - protected function checkNumericCharacters($password) { - $enforceNumericCharacters = $this->config->getEnforceNumericCharacters(); - if($enforceNumericCharacters) { - if (preg_match('/^(?=.*\d).+$/', $password) !== 1) { - $message = 'Password needs to contain at least one numeric character'; - $message_t = $this->l->t( - 'Password needs to contain at least one numeric character.' - ); - throw new HintException($message, $message_t); - } - } - } - - /** - * check if password contain at least one special character - * - * @param string $password - * @throws HintException - */ - protected function checkSpecialCharacters($password) { - $enforceSpecialCharacters = $this->config->getEnforceSpecialCharacters(); - if($enforceSpecialCharacters && ctype_alnum($password)) { - $message = 'Password needs to contain at least one special character.'; - $message_t = $this->l->t( - 'Password needs to contain at least one special character.' - ); - throw new HintException($message, $message_t); - } - } - - - /** - * Checks if password is within the 100,000 most used passwords. - * - * @param string $password - * @throws HintException - */ - protected function checkCommonPasswords($password) { - $enforceNonCommonPassword = $this->config->getEnforceNonCommonPassword(); - if($enforceNonCommonPassword) { - $passwordFile = __DIR__ . '/../lists/list-'.strlen($password).'.php'; - if(file_exists($passwordFile)) { - $commonPasswords = require_once $passwordFile; - if (isset($commonPasswords[strtolower($password)])) { - $message = 'Password is among the 1,000,000 most common ones. Please make it unique.'; - $message_t = $this->l->t( - 'Password is among the 1,000,000 most common ones. Please make it unique.' - ); - throw new HintException($message, $message_t); - } - } - } - } - - /** - * Check if a password is in the list of breached passwords from - * haveibeenpwned.com - * - * @param string $password - * @throws HintException - */ - protected function checkHaveIBeenPwned($password) { - if ($this->config->getEnforceHaveIBeenPwned()) { - $hash = sha1($password); - $range = substr($hash, 0, 5); - $needle = strtoupper(substr($hash, 5)); - - $client = $this->clientService->newClient(); - + public function validate(string $password): void { + $validators = [ + CommonPasswordsValidator::class, + LengthValidator::class, + NumericCharacterValidator::class, + UpperCaseLoweCaseValidator::class, + SpecialCharactersValidator::class, + HIBPValidator::class, + ]; + + foreach ($validators as $validator) { try { - $response = $client->get( - 'https://api.pwnedpasswords.com/range/' . $range, - [ - 'timeout' => 5 - ] - ); - } catch (\Exception $e) { - return; + /** @var IValidator $instance */ + $instance = $this->container->query($validator); + } catch (QueryException $e) { + //ignore and continue } - $result = $response->getBody(); - - if (strpos($result, $needle) !== false) { - $message = 'Password is present in compromised password list. Please choose a different password.'; - $message_t = $this->l->t( - 'Password is present in compromised password list. Please choose a different password.' - ); - throw new HintException($message, $message_t); - } + $instance->validate($password); } } diff --git a/lib/Validator/CommonPasswordsValidator.php b/lib/Validator/CommonPasswordsValidator.php new file mode 100644 index 0000000..0910f40 --- /dev/null +++ b/lib/Validator/CommonPasswordsValidator.php @@ -0,0 +1,60 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\IL10N; + +class CommonPasswordsValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + + public function __construct(PasswordPolicyConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + public function validate(string $password): void { + $enforceNonCommonPassword = $this->config->getEnforceNonCommonPassword(); + if($enforceNonCommonPassword) { + $passwordFile = __DIR__ . '/../../lists/list-'.strlen($password).'.php'; + if(file_exists($passwordFile)) { + $commonPasswords = require_once $passwordFile; + if (isset($commonPasswords[strtolower($password)])) { + $message = 'Password is among the 1,000,000 most common ones. Please make it unique.'; + $message_t = $this->l->t( + 'Password is among the 1,000,000 most common ones. Please make it unique.' + ); + throw new HintException($message, $message_t); + } + } + } + } + +} diff --git a/lib/Validator/HIBPValidator.php b/lib/Validator/HIBPValidator.php new file mode 100644 index 0000000..a534d68 --- /dev/null +++ b/lib/Validator/HIBPValidator.php @@ -0,0 +1,80 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\Http\Client\IClientService; +use OCP\IL10N; + +class HIBPValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + /** @var IClientService */ + private $clientService; + + public function __construct(PasswordPolicyConfig $config, + IL10N $l, + IClientService $clientService) { + $this->config = $config; + $this->l = $l; + $this->clientService = $clientService; + } + + public function validate(string $password): void { + if ($this->config->getEnforceHaveIBeenPwned()) { + $hash = sha1($password); + $range = substr($hash, 0, 5); + $needle = strtoupper(substr($hash, 5)); + + $client = $this->clientService->newClient(); + + try { + $response = $client->get( + 'https://api.pwnedpasswords.com/range/' . $range, + [ + 'timeout' => 5 + ] + ); + } catch (\Exception $e) { + return true; + } + + $result = $response->getBody(); + + if (strpos($result, $needle) !== false) { + $message = 'Password is present in compromised password list. Please choose a different password.'; + $message_t = $this->l->t( + 'Password is present in compromised password list. Please choose a different password.' + ); + throw new HintException($message, $message_t); + } + } + } + +} diff --git a/lib/Validator/IValidator.php b/lib/Validator/IValidator.php new file mode 100644 index 0000000..73f3cd2 --- /dev/null +++ b/lib/Validator/IValidator.php @@ -0,0 +1,38 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; + +interface IValidator { + + /** + * @param string $password + * @return bool + * + * @throws HintException + */ + public function validate(string $password): void; +} diff --git a/lib/Validator/LengthValidator.php b/lib/Validator/LengthValidator.php new file mode 100644 index 0000000..400d444 --- /dev/null +++ b/lib/Validator/LengthValidator.php @@ -0,0 +1,54 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\IL10N; + +class LengthValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + + public function __construct(PasswordPolicyConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + public function validate(string $password): void { + $minLength = $this->config->getMinLength(); + if(strlen($password) < $minLength) { + $message = 'Password needs to be at least ' . $minLength . ' characters long'; + $message_t = $this->l->t( + 'Password needs to be at least %s characters long', [$minLength] + ); + throw new HintException($message, $message_t); + } + } + +} diff --git a/lib/Validator/NumericCharacterValidator.php b/lib/Validator/NumericCharacterValidator.php new file mode 100644 index 0000000..1d0955e --- /dev/null +++ b/lib/Validator/NumericCharacterValidator.php @@ -0,0 +1,56 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\IL10N; + +class NumericCharacterValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + + public function __construct(PasswordPolicyConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + public function validate(string $password): void { + $enforceNumericCharacters = $this->config->getEnforceNumericCharacters(); + if($enforceNumericCharacters) { + if (preg_match('/^(?=.*\d).+$/', $password) !== 1) { + $message = 'Password needs to contain at least one numeric character'; + $message_t = $this->l->t( + 'Password needs to contain at least one numeric character.' + ); + throw new HintException($message, $message_t); + } + } + } + +} diff --git a/lib/Validator/SpecialCharactersValidator.php b/lib/Validator/SpecialCharactersValidator.php new file mode 100644 index 0000000..e6d9478 --- /dev/null +++ b/lib/Validator/SpecialCharactersValidator.php @@ -0,0 +1,54 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\IL10N; + +class SpecialCharactersValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + + public function __construct(PasswordPolicyConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + public function validate(string $password): void { + $enforceSpecialCharacters = $this->config->getEnforceSpecialCharacters(); + if($enforceSpecialCharacters && ctype_alnum($password)) { + $message = 'Password needs to contain at least one special character.'; + $message_t = $this->l->t( + 'Password needs to contain at least one special character.' + ); + throw new HintException($message, $message_t); + } + } + +} diff --git a/lib/Validator/UpperCaseLoweCaseValidator.php b/lib/Validator/UpperCaseLoweCaseValidator.php new file mode 100644 index 0000000..840007c --- /dev/null +++ b/lib/Validator/UpperCaseLoweCaseValidator.php @@ -0,0 +1,56 @@ +<?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 OCA\Password_Policy\Validator; + +use OC\HintException; +use OCA\Password_Policy\PasswordPolicyConfig; +use OCP\IL10N; + +class UpperCaseLoweCaseValidator implements IValidator { + + /** @var PasswordPolicyConfig */ + private $config; + /** @var IL10N */ + private $l; + + public function __construct(PasswordPolicyConfig $config, IL10N $l) { + $this->config = $config; + $this->l = $l; + } + + public function validate(string $password): void { + $enforceUpperLowerCase = $this->config->getEnforceUpperLowerCase(); + if($enforceUpperLowerCase) { + if (preg_match('/^(?=.*[a-z])(?=.*[A-Z]).+$/', $password) !== 1) { + $message = 'Password needs to contain at least one lower and one upper case character.'; + $message_t = $this->l->t( + 'Password needs to contain at least one lower and one upper case character.' + ); + throw new HintException($message, $message_t); + } + } + } + +} |