diff --git a/html/inc/util.inc b/html/inc/util.inc
index 46c48cfd84..6bea3280c8 100644
--- a/html/inc/util.inc
+++ b/html/inc/util.inc
@@ -72,6 +72,11 @@ if (!defined('LDAP_HOST')) {
define('LDAP_HOST', null);
}
+// sleep this long on any login failure
+// (slow the rate of hacker attacks)
+//
+define('LOGIN_FAIL_SLEEP_SEC', 5);
+
$caching = false;
// if set, we're writing to a file rather than to client
$did_page_head = false;
diff --git a/html/user/login_action.php b/html/user/login_action.php
index 57c4cceff7..5383bff9cb 100644
--- a/html/user/login_action.php
+++ b/html/user/login_action.php
@@ -36,6 +36,7 @@ check_get_args(array("id", "t", "h", "key"));
function login_with_email($email_addr, $passwd, $next_url, $perm) {
$user = BoincUser::lookup_email_addr($email_addr);
if (!$user) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
page_head("No such account");
echo "No account with email address $email_addr exists.
Please go back and try again.
@@ -44,12 +45,14 @@ function login_with_email($email_addr, $passwd, $next_url, $perm) {
exit;
}
if (substr($user->authenticator, 0, 1) == 'x'){
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page("This account has been administratively disabled.");
}
// allow authenticator as password
if ($passwd != $user->authenticator) {
$passwd_hash = md5($passwd.$email_addr);
if ($passwd_hash != $user->passwd_hash) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
page_head("Password incorrect");
echo "The password you entered is incorrect. Please go back and try again.\n";
page_tail();
@@ -66,6 +69,7 @@ function login_with_email($email_addr, $passwd, $next_url, $perm) {
function login_via_link($id, $t, $h) {
$user = BoincUser::lookup_id($id);
if (!$user) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page("Invalid user ID.
Please make sure you visited the complete URL;
it may have been split across lines by your email reader."
@@ -75,12 +79,14 @@ function login_via_link($id, $t, $h) {
$x = md5($x);
$x = substr($x, 0, 16);
if ($x != $h) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page("Invalid authenticator.
Please make sure you visited the complete URL;
it may have been split across lines by your email reader."
);
}
if (time() - $t > 86400) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page("Link has expired;
go here to
get a new login link by email."
@@ -93,12 +99,14 @@ function login_via_link($id, $t, $h) {
function login_with_auth($authenticator, $next_url, $perm) {
$user = BoincUser::lookup_auth($authenticator);
if (!$user) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
page_head("Login failed");
echo "There is no account with that authenticator.
Please try again.
";
page_tail();
} else if (substr($user->authenticator, 0, 1) == 'x'){
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page("This account has been administratively disabled.");
} else {
Header("Location: $next_url");
@@ -109,6 +117,7 @@ function login_with_auth($authenticator, $next_url, $perm) {
function login_with_ldap($uid, $passwd, $next_url, $perm) {
list ($ldap_user, $error_msg) = ldap_auth($uid, $passwd);
if ($error_msg) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
error_page($error_msg);
}
$x = ldap_email_string($uid);
diff --git a/html/user/lookup_account.php b/html/user/lookup_account.php
index 67e53c6613..eb52987b01 100644
--- a/html/user/lookup_account.php
+++ b/html/user/lookup_account.php
@@ -37,6 +37,7 @@ if (LDAP_HOST && $ldap_auth) {
$passwd = get_str("passwd");
list ($ldap_user, $error_msg) = ldap_auth($ldap_uid, $passwd);
if ($error_msg) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
xml_error(ERR_BAD_USER_NAME, $error_msg);
}
$x = ldap_email_string($ldap_uid);
@@ -55,6 +56,7 @@ if (LDAP_HOST && $ldap_auth) {
$email_addr = BoincDb::escape_string($email_addr);
$user = BoincUser::lookup("email_addr='$email_addr'");
if (!$user) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
xml_error(ERR_DB_NOT_FOUND);
}
@@ -77,6 +79,7 @@ if (LDAP_HOST && $ldap_auth) {
// if the given password hash matches (auth+email), accept it
//
if ($user->passwd_hash != $passwd_hash && $auth_hash != $passwd_hash) {
+ sleep(LOGIN_FAIL_SLEEP_SEC);
xml_error(ERR_BAD_PASSWD);
}
}