aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engine/lib/sessions.php76
-rw-r--r--languages/en.php2
2 files changed, 75 insertions, 3 deletions
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index f3d828ca4..9336f0059 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -181,23 +181,93 @@
*/
function pam_auth_userpass($credentials = NULL)
{
+ $max_in_period = 3; // max 3 login attempts in
+ $period_length = 5; // 5 minutes
+ $periods = array();
+
if (is_array($credentials) && ($credentials['username']) && ($credentials['password']))
{
//$dbpassword = md5($credentials['password']);
if ($user = get_user_by_username($credentials['username'])) {
+
// Let admins log in without validating their email, but normal users must have validated their email
if ((!$user->admin) && (!$user->validated) && (!$user->admin_created) && (!$user->isBanned()))
return false;
- if ($user->password == generate_user_password($user, $credentials['password'])) {
+ if ($user->password == generate_user_password($user, $credentials['password']))
+
return true;
- }
+ else
+ // Password failed, log.
+ log_login_failure($user->guid);
+
}
}
return false;
+ }
+
+ function log_login_failure($user_guid)
+ {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ $fails++;
+
+ $user->setPrivateSetting("login_failures", $fails);
+ $user->setPrivateSetting("login_failure_$fails", time());
+ }
+ }
+
+ function reset_login_failure_count($user_guid)
+ {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+
+ if ($fails) {
+ for ($n=1; $n <= $fails; $n++)
+ $user->removePrivateSetting("login_failure_$n");
+
+ $user->removePrivateSetting("login_failures");
+ }
+ }
+ }
+
+ function check_rate_limit_exceeded($user_guid)
+ {
+ $limit = 5;
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ if ($fails >= $limit)
+ {
+ $cnt = 0;
+ $time = time();
+ for ($n=$fails; $n>0; $n--)
+ {
+ $f = $user->getPrivateSetting("login_failure_$n");
+ if ($f > $time - (60*5))
+ $cnt++;
+
+ if ($cnt==$limit) return true; // Limit reached
+ }
+ }
+
+ }
+
+ return false;
}
/**
@@ -214,6 +284,7 @@
global $CONFIG;
if ($user->isBanned()) return false; // User is banned, return false.
+ if (check_rate_limit_exceeded($user->guid)) return false; // Check rate limit
$_SESSION['user'] = $user;
$_SESSION['guid'] = $user->getGUID();
@@ -246,6 +317,7 @@
// Update statistics
set_last_login($_SESSION['guid']);
+ reset_login_failure_count($user->guid); // Reset any previous failed login attempts
return true;
diff --git a/languages/en.php b/languages/en.php
index e08c07ece..3ab22dc5b 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -14,7 +14,7 @@
'login' => "Log in",
'loginok' => "You have been logged in.",
- 'loginerror' => "We couldn't log you in. This may be because you haven't validated your account yet, or the details you supplied were incorrect. Make sure your details are correct and please try again.",
+ 'loginerror' => "We couldn't log you in. This may be because you haven't validated your account yet, the details you supplied were incorrect, or you have made too many incorrect login attempts. Make sure your details are correct and please try again.",
'logout' => "Log out",
'logoutok' => "You have been logged out.",