| 1 |
<?php
|
| 2 |
// $Id: login_security.module,v 1.19 2009/06/24 10:45:03 ilo Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Login Security
|
| 7 |
*
|
| 8 |
* GPL published.. if you don't have a copy of the license, search for it, it's free
|
| 9 |
* Copyrighted by ilo@reversing.org
|
| 10 |
* Thanks to christefano for the module tips and strings
|
| 11 |
*/
|
| 12 |
|
| 13 |
define('LOGIN_SECURITY_TRACK_TIME', 0);
|
| 14 |
define('LOGIN_SECURITY_BASE_TIME', 0);
|
| 15 |
define('LOGIN_SECURITY_DELAY_INCREASE', 0);
|
| 16 |
define('LOGIN_SECURITY_USER_WRONG_COUNT', 0);
|
| 17 |
define('LOGIN_SECURITY_HOST_WRONG_COUNT', 0);
|
| 18 |
define('LOGIN_SECURITY_HOST_WRONG_COUNT_HARD', 0);
|
| 19 |
define('LOGIN_SECURITY_DISABLE_CORE_LOGIN_ERROR', 0);
|
| 20 |
define('LOGIN_SECURITY_NOTICE_ATTEMPTS_AVAILABLE', 0);
|
| 21 |
define('LOGIN_SECURITY_NOTICE_ATTEMPTS_MESSAGE', "You have used %user_current_count out of %user_block_attempts login attempts. After all %user_block_attempts have been used, you will be unable to login.");
|
| 22 |
define('LOGIN_SECURITY_HOST_SOFT_BANNED', "This host is not allowed to log in to %site. Please contact your site administrator.");
|
| 23 |
define('LOGIN_SECURITY_HOST_HARD_BANNED', "The IP address <em>%ip</em> is banned at %site, and will not be able to access any of its content from now on. Please contact the site administrator.");
|
| 24 |
define('LOGIN_SECURITY_USER_BLOCKED', "The user <em>%username</em> has been blocked due to failed login attempts.");
|
| 25 |
define('LOGIN_SECURITY_USER_BLOCKED_EMAIL', FALSE);
|
| 26 |
define('LOGIN_SECURITY_USER_BLOCKED_EMAIL_SUBJECT', "Security action: The user %username has been blocked.");
|
| 27 |
define('LOGIN_SECURITY_USER_BLOCKED_EMAIL_BODY', "The user %username (%edit_uri) has been blocked at %site due to the amount of failed login attempts. Please check the logs for more information.");
|
| 28 |
|
| 29 |
/**
|
| 30 |
* Implementation of hook_cron().
|
| 31 |
*/
|
| 32 |
function login_security_cron() {
|
| 33 |
// calc expiring time of login security tracked entries
|
| 34 |
$time = time() - (variable_get('login_security_track_time', LOGIN_SECURITY_TRACK_TIME) * 3600);
|
| 35 |
db_query("DELETE FROM {login_security_track} WHERE timestamp < %d", $time);
|
| 36 |
return;
|
| 37 |
}
|
| 38 |
|
| 39 |
/**
|
| 40 |
* Implementation of hook_user().
|
| 41 |
*/
|
| 42 |
function login_security_user($op, &$edit, &$account, $category = NULL) {
|
| 43 |
switch ($op) {
|
| 44 |
case 'login':
|
| 45 |
// On success login remove any temporary protection for the IP address and the username
|
| 46 |
db_query("DELETE FROM {login_security_track} WHERE name = '%s' AND host = '%s'", check_plain($edit['name']), check_plain(ip_address()));
|
| 47 |
break;
|
| 48 |
case 'update':
|
| 49 |
// The update case can be launched by the user or by any user administrator
|
| 50 |
// On update, remove only the unser information tracked
|
| 51 |
db_query("DELETE FROM {login_security_track} WHERE name = '%s'", check_plain($edit['name']));
|
| 52 |
break;
|
| 53 |
// Cron will clean the forgotten tracking entries, including the deleted users.
|
| 54 |
}
|
| 55 |
}
|
| 56 |
|
| 57 |
/**
|
| 58 |
* Implementation of hook_form_alter().
|
| 59 |
*/
|
| 60 |
function login_security_form_alter(&$form, $form_state, $form_id) {
|
| 61 |
switch ($form_id) {
|
| 62 |
case 'user_login':
|
| 63 |
case 'user_login_block':
|
| 64 |
// Put login_security first or the capture of the previous login timestamp won't work
|
| 65 |
// and core's validation will update to the current login instance before login_security
|
| 66 |
// can read the old timestamp.
|
| 67 |
$form['#validate'] = array_merge(array('login_security_soft_block_validate', 'login_security_set_login_timestamp'), $form['#validate']);
|
| 68 |
$form['#validate'][] = 'login_security_validate';
|
| 69 |
break;
|
| 70 |
case 'user_admin_settings':
|
| 71 |
if (user_access('administer users')) {
|
| 72 |
$form['login_security'] = array(
|
| 73 |
'#type' => 'fieldset',
|
| 74 |
'#title' => t('Login Security settings'),
|
| 75 |
'#weight' => 0,
|
| 76 |
'#collapsible' => FALSE,
|
| 77 |
);
|
| 78 |
$form['login_security'][] = login_security_build_admin_form();
|
| 79 |
}
|
| 80 |
break;
|
| 81 |
}
|
| 82 |
}
|
| 83 |
|
| 84 |
/**
|
| 85 |
* Build a form body for the configuration settings.
|
| 86 |
*/
|
| 87 |
function login_security_build_admin_form() {
|
| 88 |
$form = array();
|
| 89 |
|
| 90 |
$form['login_security_track_time'] = array(
|
| 91 |
'#type' => 'textfield',
|
| 92 |
'#title' => t('Track time'),
|
| 93 |
'#default_value' => variable_get('login_security_track_time', LOGIN_SECURITY_TRACK_TIME),
|
| 94 |
'#size' => 3,
|
| 95 |
'#maxlength' => 3,
|
| 96 |
'#description' => t('Enter the time that each failed login attempt is kept for future computing.'),
|
| 97 |
'#field_suffix' => '<kbd>'. t('Hours') .'</kbd>'
|
| 98 |
);
|
| 99 |
$form['login_security_delay_base_time'] = array(
|
| 100 |
'#type' => 'textfield',
|
| 101 |
'#title' => t('Login delay base time'),
|
| 102 |
'#default_value' => variable_get('login_security_delay_base_time', LOGIN_SECURITY_BASE_TIME),
|
| 103 |
'#size' => 3,
|
| 104 |
'#maxlength' => 3,
|
| 105 |
'#description' => t('Enter the base time for login delay'),
|
| 106 |
'#field_suffix' => '<kbd>'. t('Seconds') .'</kbd>'
|
| 107 |
);
|
| 108 |
$form['login_security_delay_increase'] = array(
|
| 109 |
'#type' => 'radios',
|
| 110 |
'#title' => t('Increase delay for each attempt?'),
|
| 111 |
'#default_value' => variable_get('login_security_delay_increase', LOGIN_SECURITY_DELAY_INCREASE),
|
| 112 |
'#options' => array(1 => 'Yes', 0 => 'No'),
|
| 113 |
'#description' => t('Computed as (base time) x (login attempts) for that user.'),
|
| 114 |
);
|
| 115 |
$form['login_security_user_wrong_count'] = array(
|
| 116 |
'#type' => 'textfield',
|
| 117 |
'#title' => t('Maximum number of login failures before blocking a user'),
|
| 118 |
'#default_value' => variable_get('login_security_user_wrong_count', LOGIN_SECURITY_USER_WRONG_COUNT),
|
| 119 |
'#size' => 3,
|
| 120 |
'#maxlength' => 3,
|
| 121 |
'#description' => t('Enter the number of login failures a user is allowed. After that amount is reached, the user will be blocked, no matter the host attempting to log in. Use this option carefully on public sites, as an attacker may block your site users.'),
|
| 122 |
'#field_suffix' => '<kbd>'. t('Failed attempts') .'</kbd>'
|
| 123 |
);
|
| 124 |
$form['login_security_host_wrong_count'] = array(
|
| 125 |
'#type' => 'textfield',
|
| 126 |
'#title' => t('Maximum number of login failures before soft blocking a host'),
|
| 127 |
'#default_value' => variable_get('login_security_host_wrong_count', LOGIN_SECURITY_HOST_WRONG_COUNT),
|
| 128 |
'#size' => 3,
|
| 129 |
'#maxlength' => 3,
|
| 130 |
'#description' => t('Enter the number of login failures a host is allowed. After that amount is reached, the host will not be able to log in but can still browse the site contents as an anonymous user.'),
|
| 131 |
'#field_suffix' => '<kbd>'. t('Failed attempts') .'</kbd>'
|
| 132 |
);
|
| 133 |
$form['login_security_host_wrong_count_hard'] = array(
|
| 134 |
'#type' => 'textfield',
|
| 135 |
'#title' => t('Maximum number of login failures before blocking a host'),
|
| 136 |
'#default_value' => variable_get('login_security_host_wrong_count_hard', LOGIN_SECURITY_HOST_WRONG_COUNT_HARD),
|
| 137 |
'#size' => 3,
|
| 138 |
'#maxlength' => 3,
|
| 139 |
'#description' => t('Enter the number of login failures a host is allowed. After that number is reached, the host will be blocked, no matter the username attempting to log in.'),
|
| 140 |
'#field_suffix' => '<kbd>'. t('Failed attempts') .'</kbd>'
|
| 141 |
);
|
| 142 |
|
| 143 |
$form['login_messages'] = array(
|
| 144 |
'#type' => 'fieldset',
|
| 145 |
'#title' => t('Notifications'),
|
| 146 |
);
|
| 147 |
$form['login_messages']['login_security_disable_core_login_error'] = array(
|
| 148 |
'#type' => 'checkbox',
|
| 149 |
'#title' => t('Disable login failure error message'),
|
| 150 |
'#description' => t('Sorry, unrecognized username or password. Have you forgotten your password?'),
|
| 151 |
'#default_value' => variable_get('login_security_disable_core_login_error', LOGIN_SECURITY_DISABLE_CORE_LOGIN_ERROR)
|
| 152 |
);
|
| 153 |
$form['login_messages']['login_security_notice_attempts_available'] = array(
|
| 154 |
'#type' => 'checkbox',
|
| 155 |
'#title' => t('Notify the user about the number of remaining login attempts'),
|
| 156 |
'#default_value' => variable_get('login_security_notice_attempts_available', LOGIN_SECURITY_NOTICE_ATTEMPTS_AVAILABLE),
|
| 157 |
'#description' => t('Security tip: If you enable this option, try to not disclose as much of your login policies as possible in the message shown on any failed login attempt.'),
|
| 158 |
);
|
| 159 |
$form['login_messages']['login_security_last_login_timestamp'] = array(
|
| 160 |
'#type' => 'checkbox',
|
| 161 |
'#title' => t('Display last login timestamp'),
|
| 162 |
'#description' => t('The last login timestamp will be displayed as a status message when users login.'),
|
| 163 |
'#default_value' => variable_get('login_security_last_login_timestamp', 0)
|
| 164 |
);
|
| 165 |
$form['login_messages']['login_security_last_access_timestamp'] = array(
|
| 166 |
'#type' => 'checkbox',
|
| 167 |
'#title' => t('Display last access timestamp'),
|
| 168 |
'#description' => t('The last access timestamp will be displayed as a status message when users login.'),
|
| 169 |
'#default_value' => variable_get('login_security_last_access_timestamp', 0)
|
| 170 |
);
|
| 171 |
$form['login_messages']['login_security_user_blocked_email'] = array(
|
| 172 |
'#type' => 'checkbox',
|
| 173 |
'#title' => t('Send email message to the admin (uid 1) when a user is blocked'),
|
| 174 |
'#default_value' => variable_get('login_security_user_blocked_email', LOGIN_SECURITY_USER_BLOCKED_EMAIL),
|
| 175 |
);
|
| 176 |
|
| 177 |
|
| 178 |
$form['login_security']['Notifications'] = array(
|
| 179 |
'#type' => 'fieldset',
|
| 180 |
'#title' => t('Edit notification texts'),
|
| 181 |
'#weight' => 3,
|
| 182 |
'#collapsible' => TRUE,
|
| 183 |
'#collapsed' => TRUE,
|
| 184 |
'#description' => t("Allowed placeholders for notifications include the following: %date, %ip, %username, %email, %uid, %site, %uri, %edit_uri, %hard_block_attempts, %soft_block_attempts, %user_block_attempts, %user_ip_current_count, %ip_current_count, %user_current_count, %tracking_time")
|
| 185 |
);
|
| 186 |
|
| 187 |
$form['login_security']['Notifications']['login_security_notice_attempts_message'] = array(
|
| 188 |
'#type' => 'textarea',
|
| 189 |
'#title' => t('Message to be shown on each failed login attempt'),
|
| 190 |
'#rows' => 2,
|
| 191 |
'#default_value' => variable_get('login_security_notice_attempts_message', LOGIN_SECURITY_NOTICE_ATTEMPTS_MESSAGE),
|
| 192 |
'#description' => t('Enter the message string to be shown if the login fails after the form is submitted. You can use any of the placeholders here.'),
|
| 193 |
);
|
| 194 |
$form['login_security']['Notifications']['login_security_host_soft_banned'] = array(
|
| 195 |
'#type' => 'textarea',
|
| 196 |
'#title' => t('Message for banned host (Soft IP ban)'),
|
| 197 |
'#rows' => 2,
|
| 198 |
'#default_value' => variable_get('login_security_host_soft_banned', LOGIN_SECURITY_HOST_SOFT_BANNED),
|
| 199 |
'#description' => t('Enter the soft IP ban message to be shown when a host attempts to log in too many times.'),
|
| 200 |
);
|
| 201 |
$form['login_security']['Notifications']['login_security_host_hard_banned'] = array(
|
| 202 |
'#type' => 'textarea',
|
| 203 |
'#rows' => 2,
|
| 204 |
'#title' => t('Message for banned host (Hard IP ban)'),
|
| 205 |
'#default_value' => variable_get('login_security_host_hard_banned', LOGIN_SECURITY_HOST_HARD_BANNED),
|
| 206 |
'#description' => t('Enter the hard IP ban message to be shown when a host attempts to log in too many times.'),
|
| 207 |
);
|
| 208 |
$form['login_security']['Notifications']['login_security_user_blocked'] = array(
|
| 209 |
'#type' => 'textarea',
|
| 210 |
'#rows' => 2,
|
| 211 |
'#title' => t('Message when user is blocked by uid'),
|
| 212 |
'#default_value' => variable_get('login_security_user_blocked', LOGIN_SECURITY_USER_BLOCKED),
|
| 213 |
'#description' => t('Enter the message to be shown when a user gets blocked due to enough failed login attempts.'),
|
| 214 |
);
|
| 215 |
$form['login_security']['Notifications']['login_security_user_blocked_email_subject'] = array(
|
| 216 |
'#type' => 'textfield',
|
| 217 |
'#title' => t('Email subject'),
|
| 218 |
'#default_value' => variable_get('login_security_user_blocked_email_subject', LOGIN_SECURITY_USER_BLOCKED_EMAIL_SUBJECT),
|
| 219 |
);
|
| 220 |
$form['login_security']['Notifications']['login_security_user_blocked_email_body'] = array(
|
| 221 |
'#type' => 'textarea',
|
| 222 |
'#title' => t('Email body'),
|
| 223 |
'#default_value' => variable_get('login_security_user_blocked_email_body', LOGIN_SECURITY_USER_BLOCKED_EMAIL_BODY),
|
| 224 |
'#description' => t('Enter the message to be sent to the administrator informing a user has been blocked.'),
|
| 225 |
);
|
| 226 |
|
| 227 |
return $form;
|
| 228 |
}
|
| 229 |
|
| 230 |
/**
|
| 231 |
* Previous incarnations of this code put it in hook_submit or hook_user, but since
|
| 232 |
* Drupal core validation updates the login timestamp, we have to set the message before
|
| 233 |
* it gets updated with the current login instance.
|
| 234 |
*/
|
| 235 |
function login_security_set_login_timestamp($form, &$form_state) {
|
| 236 |
$account = user_load(array('name' => $form_state['values']['name'], 'pass' => trim($form_state['values']['pass']), 'status' => 1));
|
| 237 |
if (variable_get('login_security_last_login_timestamp', 0) && $account->login > 0) {
|
| 238 |
drupal_set_message(t('Your last login was !stamp', array('!stamp' => format_date($account->login, 'large'))), 'status');
|
| 239 |
}
|
| 240 |
if (variable_get('login_security_last_access_timestamp', 0) && $account->access > 0) {
|
| 241 |
drupal_set_message(t('Your last page access (site activity) was !stamp', array('!stamp' => format_date($account->access, 'large'))), 'status');
|
| 242 |
}
|
| 243 |
}
|
| 244 |
|
| 245 |
/**
|
| 246 |
* Temprarily deny validation to users with excess invalid login attempts.
|
| 247 |
*
|
| 248 |
* @url http://drupal.org/node/493164
|
| 249 |
*/
|
| 250 |
function login_security_soft_block_validate($form, &$form_state) {
|
| 251 |
$variables = _login_security_get_variables_by_name(check_plain($form['name']['#value']));
|
| 252 |
// Check for host login attempts: Soft
|
| 253 |
if ($variables['%soft_block_attempts'] >= 1) {
|
| 254 |
if ($variables['%ip_current_count'] >= $variables['%soft_block_attempts']) {
|
| 255 |
// this loop is instead of doing t() because t() can only translate static strings, not variables.
|
| 256 |
foreach ($variables as $key => $value) {
|
| 257 |
$variables[$key] = theme('placeholder', $value);
|
| 258 |
}
|
| 259 |
form_set_error('submit', strtr(variable_get('login_security_host_soft_banned', LOGIN_SECURITY_HOST_SOFT_BANNED), $variables));
|
| 260 |
}
|
| 261 |
}
|
| 262 |
}
|
| 263 |
|
| 264 |
/**
|
| 265 |
* Implementation of form validate. This functions does more than just validating, but it's main
|
| 266 |
* Intention is to break the login form flow.
|
| 267 |
*
|
| 268 |
* @param $form_item
|
| 269 |
* The status of the name field in the form field after being submitted by the user.
|
| 270 |
*
|
| 271 |
*/
|
| 272 |
function login_security_validate($form, &$form_state) {
|
| 273 |
// Sanitize user input
|
| 274 |
$name = check_plain($form_state['values']['name']);
|
| 275 |
// Null username should not be tracked
|
| 276 |
if (!strlen($name)) {
|
| 277 |
return;
|
| 278 |
}
|
| 279 |
|
| 280 |
// Save entry in security log, Username and IP Address
|
| 281 |
_login_security_add_event($name, check_plain(ip_address()));
|
| 282 |
|
| 283 |
// Populate variables to be used in any module message or login operation
|
| 284 |
$variables = _login_security_get_variables_by_name($name);
|
| 285 |
|
| 286 |
// Start with login Delay
|
| 287 |
if ($delay = variable_get('login_security_delay_base_time', LOGIN_SECURITY_BASE_TIME)) {
|
| 288 |
$secs = (variable_get('login_security_delay_increase', LOGIN_SECURITY_DELAY_INCREASE) == 1) ? intval($variables['%user_ip_current_count']-1) * intval($delay) : intval($delay);
|
| 289 |
if ($secs >= ini_get('max_execution_time')) {
|
| 290 |
$secs = ini_get('max_execution_time') - 3;
|
| 291 |
}
|
| 292 |
|
| 293 |
@sleep($secs);
|
| 294 |
}
|
| 295 |
|
| 296 |
// Check for host login attempts: Hard
|
| 297 |
if ($variables['%hard_block_attempts'] >= 1) {
|
| 298 |
if ($variables['%ip_current_count'] > $variables['%hard_block_attempts']) {
|
| 299 |
// block the host check_plain(ip_address())
|
| 300 |
login_user_block_ip($variables);
|
| 301 |
}
|
| 302 |
}
|
| 303 |
|
| 304 |
// Check for user login attempts
|
| 305 |
if ($variables['%user_block_attempts'] >= 1) {
|
| 306 |
if ($variables['%user_current_count'] > $variables['%user_block_attempts']) {
|
| 307 |
// Block the account $name
|
| 308 |
login_user_block_user_name($variables);
|
| 309 |
}
|
| 310 |
}
|
| 311 |
|
| 312 |
// at this point, they're either logged in or not by Drupal core's abuse of the validation hook to login users completely
|
| 313 |
global $user;
|
| 314 |
|
| 315 |
// login failed
|
| 316 |
if ($user->uid == 0) {
|
| 317 |
if (variable_get('login_security_disable_core_login_error', LOGIN_SECURITY_DISABLE_CORE_LOGIN_ERROR)) {
|
| 318 |
// resets the form error status so no form fields are highlighted in red
|
| 319 |
form_set_error(NULL, '', TRUE);
|
| 320 |
|
| 321 |
// removes "Sorry, unrecognized username or password. Have you forgotten your password?"
|
| 322 |
// and any other errors that might be helpful to an attacker
|
| 323 |
// it should not reset the attempts message because it is a warning, not an error
|
| 324 |
unset($_SESSION['messages']['error']);
|
| 325 |
}
|
| 326 |
|
| 327 |
// Should the user be advised about the remaining login attempts?
|
| 328 |
$notice_user = variable_get('login_security_notice_attempts_available', LOGIN_SECURITY_NOTICE_ATTEMPTS_AVAILABLE);
|
| 329 |
if (($notice_user == TRUE) && ($variables['%user_block_attempts'] > 0)) {
|
| 330 |
// this loop is instead of doing t() because t() can only translate static strings, not variables.
|
| 331 |
foreach ($variables as $key => $value) {
|
| 332 |
$variables[$key] = theme('placeholder', $value);
|
| 333 |
}
|
| 334 |
drupal_set_message(strtr(variable_get('login_security_notice_attempts_message', LOGIN_SECURITY_NOTICE_ATTEMPTS_MESSAGE), $variables), 'warning');
|
| 335 |
}
|
| 336 |
}
|
| 337 |
}
|
| 338 |
|
| 339 |
/**
|
| 340 |
* Save the login attempt in the tracking database: user name and ip address.
|
| 341 |
*
|
| 342 |
* @param $name
|
| 343 |
* user name to be tracked.
|
| 344 |
*
|
| 345 |
* @param $ip
|
| 346 |
* IP Address of the pair.
|
| 347 |
*/
|
| 348 |
function _login_security_add_event($name, $ip) {
|
| 349 |
//Each attempt is kept for future minning of advanced bruteforcing like multiple
|
| 350 |
//IP or X-Forwarded-for usage and automated track data cleanup
|
| 351 |
$event = new stdClass();
|
| 352 |
$event->host = $ip;
|
| 353 |
$event->name = $name;
|
| 354 |
$event->timestamp = time();
|
| 355 |
drupal_write_record('login_security_track', $event);
|
| 356 |
}
|
| 357 |
|
| 358 |
/**
|
| 359 |
* Create a Deny entry for the IP address. If IP address is not especified then block current IP.
|
| 360 |
*
|
| 361 |
* @param $ip
|
| 362 |
* Optional. Add a deny rule in the access control to this IP Address.
|
| 363 |
*/
|
| 364 |
function login_user_block_ip($variables) {
|
| 365 |
// There is no need to check if the host has been banned, we can't get here twice.
|
| 366 |
$block = new stdClass();
|
| 367 |
$block->mask = $variables['%ip'];
|
| 368 |
$block->type = 'host';
|
| 369 |
$block->status = 0;
|
| 370 |
drupal_write_record('access', $block);
|
| 371 |
watchdog('login_security', 'Banned IP address %ip due to security configuration.', $variables, WATCHDOG_NOTICE, l(t('edit rule'), "admin/user/rules/edit/{$block->aid}", array('query' => array('destination' => 'admin/user/rules'))));
|
| 372 |
form_set_error('void', t(variable_get('login_security_host_hard_banned', LOGIN_SECURITY_HOST_HARD_BANNED), $variables));
|
| 373 |
}
|
| 374 |
|
| 375 |
/**
|
| 376 |
* Block a user by user name. If no user id then block current user.
|
| 377 |
*
|
| 378 |
* @param $name
|
| 379 |
* Optional. The unique string identifying the user.
|
| 380 |
*
|
| 381 |
*/
|
| 382 |
function login_user_block_user_name($variables) {
|
| 383 |
// If the user exists
|
| 384 |
if ($variables['%uid'] > 1) {
|
| 385 |
// Modifying the user table is not an option so it disables the user hooks. Need to do
|
| 386 |
// firing the hook so user_notifications can be used.
|
| 387 |
// db_query("UPDATE {users} SET status = 0 WHERE uid = %d", $uid);
|
| 388 |
$uid = $variables['%uid'];
|
| 389 |
$account = user_load(array("uid" => $uid));
|
| 390 |
|
| 391 |
// Block account if is active.
|
| 392 |
if ($account->status == 1) {
|
| 393 |
user_save($account, array('status' => 0), NULL);
|
| 394 |
// remove user from site now.
|
| 395 |
sess_destroy_uid($uid);
|
| 396 |
// The watchdog alert is set to 'user' so it will show with other blocked user messages.
|
| 397 |
watchdog('user', 'Blocked user %username due to security configuration.', $variables, WATCHDOG_NOTICE, l(t('edit user'), "user/{$variables['%uid']}/edit", array('query' => array('destination' => 'admin/user/user'))));
|
| 398 |
// Also notify the user that account has been blocked.
|
| 399 |
form_set_error('void', t(variable_get('login_security_user_blocked', LOGIN_SECURITY_USER_BLOCKED), $variables));
|
| 400 |
|
| 401 |
// Send admin email
|
| 402 |
if (variable_get('login_security_user_blocked_email', LOGIN_SECURITY_USER_BLOCKED_EMAIL)) {
|
| 403 |
$from = variable_get('site_mail', ini_get('sendmail_from'));
|
| 404 |
$admin_mail = db_result(db_query("SELECT mail FROM {users} WHERE uid = 1"));
|
| 405 |
$subject = strtr(variable_get('login_security_user_blocked_email_subject', LOGIN_SECURITY_USER_BLOCKED_EMAIL_SUBJECT), $variables);
|
| 406 |
$body = strtr(variable_get('login_security_user_blocked_email_mody', LOGIN_SECURITY_USER_BLOCKED_EMAIL_BODY), $variables);
|
| 407 |
|
| 408 |
return drupal_mail('login_security', 'notify', $admin_mail, language_default(), $variables, $from, TRUE);
|
| 409 |
}
|
| 410 |
}
|
| 411 |
|
| 412 |
}
|
| 413 |
}
|
| 414 |
|
| 415 |
|
| 416 |
/**
|
| 417 |
* Helper function to get the variable array for the messages.
|
| 418 |
*/
|
| 419 |
function _login_security_get_variables_by_name($name) {
|
| 420 |
$account = user_load(array("name" => $name));
|
| 421 |
$ipaddress = check_plain(ip_address());
|
| 422 |
global $base_url;
|
| 423 |
$variables = array(
|
| 424 |
'%date' => format_date(time()),
|
| 425 |
'%ip' => $ipaddress,
|
| 426 |
'%username' => $account->name,
|
| 427 |
'%email' => $account->mail,
|
| 428 |
'%uid' => $account->uid,
|
| 429 |
'%site' => variable_get('site_name', 'drupal'),
|
| 430 |
'%uri' => $base_url,
|
| 431 |
'%edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)),
|
| 432 |
'%hard_block_attempts' => variable_get('login_security_host_wrong_count_hard', LOGIN_SECURITY_HOST_WRONG_COUNT_HARD),
|
| 433 |
'%soft_block_attempts' => variable_get('login_security_host_wrong_count', LOGIN_SECURITY_USER_WRONG_COUNT),
|
| 434 |
'%user_block_attempts' => variable_get('login_security_user_wrong_count', LOGIN_SECURITY_USER_WRONG_COUNT),
|
| 435 |
'%user_ip_current_count' => db_result(db_query("SELECT COUNT(id) FROM {login_security_track} WHERE name = '%s' AND host = '%s'", $name, $ipaddress)),
|
| 436 |
'%ip_current_count' => db_result(db_query("SELECT COUNT(id) FROM {login_security_track} WHERE host = '%s'", $ipaddress)),
|
| 437 |
'%user_current_count' => db_result(db_query("SELECT COUNT(id) FROM {login_security_track} WHERE name = '%s'", $name)),
|
| 438 |
'%tracking_time' => variable_get('login_security_track_time', LOGIN_SECURITY_TRACK_TIME),
|
| 439 |
);
|
| 440 |
return $variables;
|
| 441 |
}
|
| 442 |
|
| 443 |
function login_security_mail($key, &$message, $variables) {
|
| 444 |
switch ($key) {
|
| 445 |
case 'notify':
|
| 446 |
$message['subject'] = strtr(variable_get('login_security_user_blocked_email_subject', LOGIN_SECURITY_USER_BLOCKED_EMAIL_SUBJECT), $variables);
|
| 447 |
$message['body'] = strtr(variable_get('login_security_user_blocked_email_mody', LOGIN_SECURITY_USER_BLOCKED_EMAIL_BODY), $variables);
|
| 448 |
break;
|
| 449 |
}
|
| 450 |
}
|
| 451 |
|