function login_security_validate in Login Security 2.x
Same name and namespace in other branches
- 8 login_security.module \login_security_validate()
- 5 login_security.module \login_security_validate()
- 6 login_security.module \login_security_validate()
- 7 login_security.module \login_security_validate()
Implements hook_validate().
This functions does more than just validating, but it's main intention is to break the login form flow.
1 string reference to 'login_security_validate'
- login_security_form_alter in ./
login_security.module - Implements hook_form_alter().
File
- ./
login_security.module, line 136 - Login Security module hooks.
Code
function login_security_validate(array $form, FormStateInterface $form_state) {
$conf = \Drupal::config('login_security.settings');
// Sanitize user input.
$name = $form_state
->getValue('name');
// Null username should not be tracked.
if (!strlen($name)) {
return;
}
// Expire old tracked entries.
_login_security_remove_events();
// Populate variables to be used in any module message or login operation.
$variables = _login_security_get_variables_by_name($name);
// First, check if administrator should be notified of unexpected login
// activity.
// Only process if configured threshold > 1.
// see: http://drupal.org/node/583092.
if ($variables['@activity_threshold']) {
$threshold = \Drupal::state()
->get('login_security.threshold_notified', FALSE);
// Check if threshold has been reached.
if ($variables['@tracking_current_count'] > $variables['@activity_threshold']) {
// Check if admin has been already alerted.
if (!$threshold) {
// Mark alert status as notified and send the email.
\Drupal::logger('login_security')
->warning('Ongoing attack detected: Suspicious activity detected in login form submissions. Too many invalid login attempts threshold reached: currently @tracking_current_count events are tracked, and threshold is configured for @activity_threshold attempts.', $variables);
\Drupal::state()
->set('login_security.threshold_notified', TRUE);
// Send notification only if required.
$email_to = $conf
->get('login_activity_notification_emails');
if ($email_to !== '') {
$from = \Drupal::config('system.site')
->get('mail');
$language = \Drupal::languageManager()
->getDefaultLanguage();
\Drupal::service('plugin.manager.mail')
->mail('login_security', 'login_activity_notify', $email_to, $language, $variables, $from, TRUE);
}
}
}
elseif (\Drupal::state()
->get('login_security.threshold_notified', FALSE) && $variables['@tracking_current_count'] < $variables['@activity_threshold'] / 3) {
// Reset alert if currently tracked events is < threshold / 3.
\Drupal::logger('login_security')
->notice('Suspicious activity in login form submissions is no longer detected: currently @tracking_current_count events are being tracked, and threshold is configured for @activity_threshold maximum allowed attempts).', $variables);
\Drupal::state()
->set('login_security.threshold_notified', TRUE);
}
}
// Check for host login attempts: Hard.
if ($variables['@hard_block_attempts'] >= 1) {
if ($variables['@ip_current_count'] >= $variables['@hard_block_attempts']) {
// Block the host ip_address().
login_user_block_ip($variables, $form_state);
}
}
// Check for user login attempts.
if ($variables['@user_block_attempts'] >= 1) {
if ($variables['@user_current_count'] >= $variables['@user_block_attempts']) {
// Block the account $name.
login_user_block_user_name($variables, $form_state);
}
}
// At this point, they're either logged in or not by Drupal core's abuse of
// the validation hook to login users completely.
if ($form_state
->hasAnyErrors()) {
$errors = $form_state
->getErrors();
$password_message = preg_grep("/<a href=\"\\/user\\/password\\?name={$name}\">Have you forgotten your password\\?<\\/a>/", $errors);
$block_message = preg_grep("/The username <em class=\"placeholder\">{$name}<\\/em> has not been activated or is blocked./", $errors);
if (!count($password_message) || !count($block_message)) {
if ($conf
->get('disable_core_login_error')) {
// Resets the form error status so no form fields are highlighted in
// red.
$form_state
->setRebuild();
$form_state
->clearErrors();
// Removes "Unrecognized username or password. Have you
// forgotten your password?" and "The username $name has not been
// activated or is blocked.", and any other errors that might be
// helpful to an attacker it should not reset the attempts message
// because it is a warning, not an error.
\Drupal::messenger()
->messagesByType('error', TRUE);
}
// Should the user be advised about the remaining login attempts?
$notice_user = $conf
->get('notice_attempts_available');
if ($notice_user == TRUE && $variables['@user_block_attempts'] > 0 && $variables['@user_block_attempts'] >= $variables['@user_current_count']) {
$message_raw = $conf
->get('notice_attempts_message');
// Simple flag that can be changed using hook_alter (see below).
$display_block_attempts = TRUE;
// Allow other module to change the flag, or even the message displayed,
// with a custom logic.
\Drupal::moduleHandler()
->alter('login_security_display_block_attempts', $message_raw, $display_block_attempts, $variables['@user_current_count']);
$message = [
'message' => $message_raw,
'variables' => $variables,
];
// This loop is used instead of doing t() because t() can only
// translate static strings, not variables.
// Ignoring Coder because $variables is sanitized by
// login_security_t().
// See https://drupal.org/node/1743996#comment-6421246.
// @ignore security_2
$message = new FormattableMarkup($message['message'], $message['variables']);
if ($display_block_attempts) {
\Drupal::messenger()
->addWarning($message, TRUE);
}
}
}
}
}