Commit ff4df099 authored by Dries's avatar Dries

Issue #1777490 by kim.pepper: convert failed login settings to new configuration system.

parent e81a2d35
uid_only: false
ip_limit: 50
ip_window: 3600
user_limit: 5
user_window: 21600
......@@ -25,10 +25,11 @@ public static function getInfo() {
* Test the global login flood control.
*/
function testGlobalLoginFloodControl() {
// Set the global login limit.
variable_set('user_failed_login_ip_limit', 10);
// Set a high per-user limit out so that it is not relevant in the test.
variable_set('user_failed_login_user_limit', 4000);
config('user.flood')
->set('ip_limit', 10)
// Set a high per-user limit out so that it is not relevant in the test.
->set('user_limit', 4000)
->save();
$user1 = $this->drupalCreateUser(array());
$incorrect_user1 = clone $user1;
......@@ -61,10 +62,11 @@ function testGlobalLoginFloodControl() {
* Test the per-user login flood control.
*/
function testPerUserLoginFloodControl() {
// Set a high global limit out so that it is not relevant in the test.
variable_set('user_failed_login_ip_limit', 4000);
// Set the per-user login limit.
variable_set('user_failed_login_user_limit', 3);
config('user.flood')
// Set a high global limit out so that it is not relevant in the test.
->set('ip_limit', 4000)
->set('user_limit', 3)
->save();
$user1 = $this->drupalCreateUser(array());
$incorrect_user1 = clone $user1;
......@@ -139,7 +141,7 @@ function assertFailedLogin($account, $flood_trigger = NULL) {
$this->assertNoFieldByXPath("//input[@name='pass' and @value!='']", NULL, t('Password value attribute is blank.'));
if (isset($flood_trigger)) {
if ($flood_trigger == 'user') {
$this->assertRaw(format_plural(variable_get('user_failed_login_user_limit', 5), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
$this->assertRaw(format_plural(config('user.flood')->get('user_limit'), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
}
else {
// No uid, so the limit is IP-based.
......
......@@ -551,6 +551,22 @@ function user_update_8006() {
'status_canceled_body' => 'status_canceled.body',
));
}
/**
* Moves login flood settings from variable to config.
*
* @ingroup config_upgrade
*/
function user_update_8007() {
update_variables_to_config('user.flood', array(
'user_failed_login_identifier_uid_only' => 'uid_only',
'user_failed_login_ip_limit' => 'ip_limit',
'user_failed_login_ip_window' => 'ip_window',
'user_failed_login_user_limit' => 'user_limit',
'user_failed_login_user_window' => 'user_window',
));
}
/**
* @} End of "addtogroup updates-7.x-to-8.x".
*/
......@@ -1621,19 +1621,20 @@ function user_login_name_validate($form, &$form_state) {
*/
function user_login_authenticate_validate($form, &$form_state) {
$password = trim($form_state['values']['pass']);
$flood_config = config('user.flood');
if (!empty($form_state['values']['name']) && !empty($password)) {
// Do not allow any login from the current user's IP if the limit has been
// reached. Default is 50 failed attempts allowed in one hour. This is
// independent of the per-user limit to catch attempts from one IP to log
// in to many different user accounts. We have a reasonably high limit
// since there may be only one apparent IP for all users at an institution.
if (!flood_is_allowed('failed_login_attempt_ip', variable_get('user_failed_login_ip_limit', 50), variable_get('user_failed_login_ip_window', 3600))) {
if (!flood_is_allowed('failed_login_attempt_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) {
$form_state['flood_control_triggered'] = 'ip';
return;
}
$account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $form_state['values']['name']))->fetchObject();
if ($account) {
if (variable_get('user_failed_login_identifier_uid_only', FALSE)) {
if ($flood_config->get('uid_only')) {
// Register flood events based on the uid only, so they apply for any
// IP address. This is the most secure option.
$identifier = $account->uid;
......@@ -1648,7 +1649,7 @@ function user_login_authenticate_validate($form, &$form_state) {
// Don't allow login if the limit for this user has been reached.
// Default is to allow 5 failed attempts every 6 hours.
if (!flood_is_allowed('failed_login_attempt_user', variable_get('user_failed_login_user_limit', 5), variable_get('user_failed_login_user_window', 21600), $identifier)) {
if (!flood_is_allowed('failed_login_attempt_user', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) {
$form_state['flood_control_triggered'] = 'user';
return;
}
......@@ -1667,17 +1668,18 @@ function user_login_authenticate_validate($form, &$form_state) {
* be the last one.
*/
function user_login_final_validate($form, &$form_state) {
$flood_config = config('user.flood');
if (empty($form_state['uid'])) {
// Always register an IP-based failed login event.
flood_register_event('failed_login_attempt_ip', variable_get('user_failed_login_ip_window', 3600));
flood_register_event('failed_login_attempt_ip', $flood_config->get('ip_window'));
// Register a per-user failed login event.
if (isset($form_state['flood_control_user_identifier'])) {
flood_register_event('failed_login_attempt_user', variable_get('user_failed_login_user_window', 21600), $form_state['flood_control_user_identifier']);
flood_register_event('failed_login_attempt_user', $flood_config->get('user_window'), $form_state['flood_control_user_identifier']);
}
if (isset($form_state['flood_control_triggered'])) {
if ($form_state['flood_control_triggered'] == 'user') {
form_set_error('name', format_plural(variable_get('user_failed_login_user_limit', 5), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
form_set_error('name', format_plural($flood_config->get('user_limit'), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
}
else {
// We did not find a uid, so the limit is IP-based.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment