openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 3bd26295ceee2eec1c228302288f4196539aff9f
parent cac54ffa874b7ef4e2ad59d336b3cd84a2429768
Author: dankert <openrat@jandankert.de>
Date:   Mon,  7 Feb 2022 22:52:12 +0100

Password lock check is moved into "InternalAuth", because it must be called on all authentication requests.

Diffstat:
Mmodules/cms/action/login/LoginLoginAction.class.php | 35-----------------------------------
Mmodules/cms/auth/InternalAuth.class.php | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mmodules/cms/model/User.class.php | 12------------
Mmodules/language/Language_CN.class.php | 3++-
Mmodules/language/Language_DE.class.php | 1+
Mmodules/language/Language_EN.class.php | 3++-
Mmodules/language/Language_ES.class.php | 5+++--
Mmodules/language/Language_FR.class.php | 5+++--
Mmodules/language/Language_IT.class.php | 5+++--
Mmodules/language/Language_RU.class.php | 5+++--
Mmodules/language/Messages.class.php | 1+
Mmodules/language/language.yml | 13++++---------
12 files changed, 80 insertions(+), 67 deletions(-)

diff --git a/modules/cms/action/login/LoginLoginAction.class.php b/modules/cms/action/login/LoginLoginAction.class.php @@ -134,40 +134,6 @@ class LoginLoginAction extends LoginAction implements Method { ] )); - // Increase fail counter - $user = User::loadWithName($loginName,User::AUTH_TYPE_INTERNAL); - - if ( $authResult & Auth::STATUS_ACCOUNT_LOCKED ) { - ; - // the account is locked, so the login failed. - // we are NOT informing the UI about this. The user is already informed about the lock. - } - else { - // Increase password fail counter - $user->increaseFailedPasswordCounter(); - // $user->passwordFailedCount is now at least 1. - - $lockAfter = Configuration::subset(['security','password'])->get('lock_after_fail_count',10); - if ( $lockAfter && $user->passwordFailedCount % $lockAfter == 0 ) { - // exponentially increase the lock duration. - $factor = pow(2, intval($user->passwordFailedCount/$lockAfter) - 1 ) ; - $lockedDuration = Configuration::subset(['security','password'])->get('lock_duration',120) * $factor * 60; - - $lockedUntil = Startup::getStartTime() + $lockedDuration; - $user->passwordLockedUntil = $lockedUntil; - $user->persist(); - - // Inform the user about the lock. - if ( $user->mail ) { - $mail = new Mail( $user->mail,Messages::MAIL_PASSWORD_LOCKED_SUBJECT,Messages::MAIL_PASSWORD_LOCKED); - $mail->setVar('username',$user->name); - $mail->setVar('name',$user->getName() ); - $mail->setVar('until',date( \cms\base\Language::lang(Messages::DATE_FORMAT ), $lockedUntil ) ); - $mail->send(); - } - } - } - // Login failed. throw new ValidationException('login_password',Messages::LOGIN_FAILED, ['name' => $loginName] ); } @@ -184,7 +150,6 @@ class LoginLoginAction extends LoginAction implements Method { $user = User::loadWithName($loginName, User::AUTH_TYPE_INTERNAL, null); $user->setCurrent(); $user->updateLoginTimestamp(); - $user->resetFailedPasswordCounter(); if ($user->passwordAlgo != Password::bestAlgoAvailable()) // Re-Hash the password with a better hash algo. diff --git a/modules/cms/auth/InternalAuth.class.php b/modules/cms/auth/InternalAuth.class.php @@ -6,8 +6,10 @@ use cms\base\Configuration; use cms\base\DB as Db; use cms\base\Startup; use cms\model\User; +use language\Messages; use LogicException; use security\Password; +use util\mail\Mail; /** * Authentifizierungsmodul für die interne Benutzerdatenbank. @@ -48,15 +50,70 @@ SQL // Pruefen ob Kennwort mit Datenbank uebereinstimmt. if (!Password::check(User::pepperPassword($password), $row_user['password_hash'], $row_user['password_algo'])) { + // Password does NOT match. + + // Increase password fail counter + $sql = Db::sql(<<<SQL +UPDATE {{user}} + SET password_fail_count=password_fail_count+1 + WHERE name={name} +SQL + ); + $sql->setString('name', $username); + $sql->execute(); + + $row_user['password_fail_count']++; + + $lockAfter = Configuration::subset(['security','password'])->get('lock_after_fail_count',10); + if ( $lockAfter && $row_user['password_fail_count'] % $lockAfter == 0 ) { + // exponentially increase the lock duration. + $factor = pow(2, intval($row_user['password_fail_count']/$lockAfter) - 1 ) ; + $lockedDuration = Configuration::subset(['security','password'])->get('lock_duration',120) * $factor * 60; + + $lockedUntil = Startup::getStartTime() + $lockedDuration; + + $sql = Db::sql(<<<SQL +UPDATE {{user}} + SET password_locked_until={locked_until} + WHERE name={name} +SQL + ); + $sql->setString('name' , $username ); + $sql->setInt ('locked_until',$lockedUntil); + $sql->execute(); + + // Inform the user about the lock. + if ( $row_user['mail'] ) { + $mail = new Mail( $row_user['mail'],Messages::MAIL_PASSWORD_LOCKED_SUBJECT,Messages::MAIL_PASSWORD_LOCKED); + $mail->setVar('username',$row_user['name' ] ); + $mail->setVar('name' ,$row_user['fullname'] ); + $mail->setVar('until' ,date( \cms\base\Language::lang(Messages::DATE_FORMAT_FULL ), $lockedUntil ) ); + $mail->send(); + } + } + Db::get()->commit(); + return Auth::STATUS_FAILED; } + // Password match :) + + // Clear password fail counter + $sql = Db::sql(<<<SQL +UPDATE {{user}} + SET password_fail_count=0 + WHERE name={name} +SQL + ); + $sql->setString('name', $username); + $sql->execute(); + // Behandeln von Klartext-Kennwoertern (Igittigitt). if ($row_user['password_algo'] == Password::ALGO_PLAIN) { if (Configuration::subset(['security', 'password'] )->is('force_change_if_cleartext',true)) // Kennwort steht in der Datenbank im Klartext. // Das Kennwort muss geaendert werden - return Auth::STATUS_PW_EXPIRED; + return Auth::STATUS_FAILED + Auth::STATUS_PW_EXPIRED; // Anderenfalls ist das Login zwar moeglich, aber das Kennwort wird automatisch neu gehasht, weil der beste Algo erzwungen wird. // Das Klartextkennwort waere danach ueberschrieben. diff --git a/modules/cms/model/User.class.php b/modules/cms/model/User.class.php @@ -1162,18 +1162,6 @@ SQL } - public function increaseFailedPasswordCounter() { - $this->passwordFailedCount++; - $this->save(); - } - - - public function resetFailedPasswordCounter() { - $this->passwordFailedCount = 0; - $this->save(); - } - - public function getId() { return $this->userid; diff --git a/modules/language/Language_CN.class.php b/modules/language/Language_CN.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creation-User', 'DATE_ANSI'=>'Date ANSI notation', 'DATE'=>'Date', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', 'DATE_FORMAT_TODAY'=>'H:i:s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'Last month', 'DATE_LAST_YEAR'=>'Last year', 'DATE_MONTH10'=>'October', diff --git a/modules/language/Language_DE.class.php b/modules/language/Language_DE.class.php @@ -121,6 +121,7 @@ public function get() { return [ 'CREATE_USER'=>'Erstellungsautor', 'DATE_ANSI'=>'Datum gemäß ANSI-Notation', 'DATE'=>'Datum', +'DATE_FORMAT_FULL'=>'d.m.Y H:i', 'DATE_FORMAT'=>'d.m.Y', 'DATE_FORMAT_TODAY'=>'H:i', 'DATE_FORMAT_LONG'=>'{weekday}\, d. {month} Y \u\m H:i:s', diff --git a/modules/language/Language_EN.class.php b/modules/language/Language_EN.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creation-User', 'DATE_ANSI'=>'Date ANSI notation', 'DATE'=>'Date', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', 'DATE_FORMAT_TODAY'=>'H:i:s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'Last month', 'DATE_LAST_YEAR'=>'Last year', 'DATE_MONTH10'=>'October', diff --git a/modules/language/Language_ES.class.php b/modules/language/Language_ES.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creationuser', 'DATE_ANSI'=>'Fechar la notación del ANSI', 'DATE'=>'Fechar', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', -'DATE_FORMAT_TODAY'=>'H: i: s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_TODAY'=>'H:i:s', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'El mes pasado', 'DATE_LAST_YEAR'=>'El año pasado', 'DATE_MONTH10'=>'Octubre', diff --git a/modules/language/Language_FR.class.php b/modules/language/Language_FR.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creationuser', 'DATE_ANSI'=>'Dater la notation de norme ANSI', 'DATE'=>'Dater', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', -'DATE_FORMAT_TODAY'=>'H : i : s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_TODAY'=>'H:i:s', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'Le mois dernier', 'DATE_LAST_YEAR'=>'L\'année dernière', 'DATE_MONTH10'=>'Octobre', diff --git a/modules/language/Language_IT.class.php b/modules/language/Language_IT.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creationuser', 'DATE_ANSI'=>'Date ANSI notation', 'DATE'=>'la notazione dell\'ANSI della data della data', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', -'DATE_FORMAT_TODAY'=>'H: i:s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_TODAY'=>'H:i:s', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'Last month', 'DATE_LAST_YEAR'=>'l\'anno scorso', 'DATE_MONTH10'=>'di ottobre', diff --git a/modules/language/Language_RU.class.php b/modules/language/Language_RU.class.php @@ -121,9 +121,10 @@ public function get() { return [ 'CREATE_USER'=>'Creationuser', 'DATE_ANSI'=>'Дата ANSI счисления', 'DATE'=>'Дата', +'DATE_FORMAT_FULL'=>'m/d Y H:i', 'DATE_FORMAT'=>'m/d Y', -'DATE_FORMAT_TODAY'=>'H: i:s', -'DATE_FORMAT_LONG'=>'l F jS Y, H:i', +'DATE_FORMAT_TODAY'=>'H:i:s', +'DATE_FORMAT_LONG'=>'m/d Y H:i', 'DATE_LAST_MONTH'=>'За последний месяц За последний', 'DATE_LAST_YEAR'=>'Last year', 'DATE_MONTH10'=>'October', diff --git a/modules/language/Messages.class.php b/modules/language/Messages.class.php @@ -121,6 +121,7 @@ class Messages { const CREATE_USER = 'CREATE_USER'; const DATE_ANSI = 'DATE_ANSI'; const DATE = 'DATE'; + const DATE_FORMAT_FULL = 'DATE_FORMAT_FULL'; const DATE_FORMAT = 'DATE_FORMAT'; const DATE_FORMAT_TODAY = 'DATE_FORMAT_TODAY'; const DATE_FORMAT_LONG = 'DATE_FORMAT_LONG'; diff --git a/modules/language/language.yml b/modules/language/language.yml @@ -481,23 +481,18 @@ DATE: fr: Dater it: "la notazione dell'ANSI della data della data" ru: Дата +DATE_FORMAT_FULL: + de: "d.m.Y H:i" + en: "m/d Y H:i" DATE_FORMAT: de: "d.m.Y" en: "m/d Y" - es: 'm/d Y' - fr: 'm/d Y' - it: "m/d Y" - ru: 'm/d Y' DATE_FORMAT_TODAY: de: "H:i" en: "H:i:s" - es: "H: i: s" - fr: "H : i : s" - it: "H: i:s" - ru: "H: i:s" DATE_FORMAT_LONG: de: '{weekday}\, d. {month} Y \u\m H:i:s' - en: "l F jS Y, H:i" + en: "m/d Y H:i" DATE_LAST_MONTH: de: Letzter Monat en: Last month