46f98b3142
The core plugins whose version was attached to GS's were reseted to 2.0.0. 2.0.0 was chosen as reset version for plugins because it is higher than the one that was set by inheriting GS version. Furthermore, it's a major change from prior plugin versioning system thus it also makes semantic sense. Justification for version bump: == GS == 9a4ab31f26 1.19.0c13b935201
1.18.3c13b935201
1.18.218fc39d2cf
1.18.1c083a8bcc2
1.18.0e8783d46d0
1.17.1d9a42550ff
1.17.01536d3ef29
1.16.0c03ed457a6
1.15.0d2e6519bad
1.14.2fe411e8138
1.14.1b17e0b4169
1.14.0daa5f87fd4
1.13.0d75b5d2f4a
1.11.7f6dbf66983
1.11.66cf674f8f8
1.11.57845a09b34
1.11.4e4d432295d
1.11.3339204f1ee
1.11.2a4e679a118
1.11.17967db6ff5
1.11.0bc030da320
1.10.19cc7df51d6
1.10.0bf7f17474d
1.9.28a07edec5f
1.9.10042971d74
1.9.06b5450b7e6
1.8.05dcc98d1c6
1.7.0e6667db0cd
1.6.03290227b50
1.5.0a59c439b46
1.4.0496ab8c920
1.3.10986030060b
1.3.91d529c021a
1.3.8f89c052cf8
1.3.738f2ecefac
1.3.6e473937cb9
1.3.59a39ebe66f
1.3.4ddc3cecfc0
1.3.32b43d484eb
1.3.2e8e487187e
1.3.1 == Plugins == XMPP plugine0887220b0
bump patche186ad57d0
bump patch OStatuse186ad57d0
bump patch Nodeinfoceae66a30f
bump minor586fb5a517
bump major195296846e
bump minor
84 lines
3.5 KiB
PHP
84 lines
3.5 KiB
PHP
<?php
|
|
|
|
if (!defined('GNUSOCIAL')) { exit(1); }
|
|
|
|
class AntiBrutePlugin extends Plugin {
|
|
const PLUGIN_VERSION = '2.0.0';
|
|
protected $failed_attempts = 0;
|
|
protected $unauthed_user = null;
|
|
protected $client_ip = null;
|
|
|
|
const FAILED_LOGIN_IP_SECTION = 'failed_login_ip';
|
|
|
|
public function initialize()
|
|
{
|
|
// This probably needs some work. For example with IPv6 you can easily generate new IPs...
|
|
$client_ip = common_client_ip();
|
|
$this->client_ip = $client_ip[0] ?: $client_ip[1]; // [0] is proxy, [1] should be the real IP
|
|
}
|
|
|
|
public function onStartCheckPassword($nickname, $password, &$authenticatedUser)
|
|
{
|
|
if (common_is_email($nickname)) {
|
|
$this->unauthed_user = User::getKV('email', common_canonical_email($nickname));
|
|
} else {
|
|
$this->unauthed_user = User::getKV('nickname', Nickname::normalize($nickname));
|
|
}
|
|
|
|
if (!$this->unauthed_user instanceof User) {
|
|
// Unknown username continue processing StartCheckPassword (maybe uninitialized LDAP user etc?)
|
|
return true;
|
|
}
|
|
|
|
$this->failed_attempts = (int)$this->unauthed_user->getPref(self::FAILED_LOGIN_IP_SECTION, $this->client_ip);
|
|
switch (true) {
|
|
case $this->failed_attempts >= 5:
|
|
common_log(LOG_WARNING, sprintf('Multiple failed login attempts for user %s from IP %s - brute force attack?',
|
|
$this->unauthed_user->getNickname(), $this->client_ip));
|
|
// 5 seconds is a good max waiting time anyway...
|
|
sleep($this->failed_attempts % 5 + 1);
|
|
break;
|
|
case $this->failed_attempts > 0:
|
|
common_debug(sprintf('Previously failed login on user %s from IP %s - sleeping %u seconds.',
|
|
$this->unauthed_user->getNickname(), $this->client_ip, $this->failed_attempts));
|
|
sleep($this->failed_attempts);
|
|
break;
|
|
default:
|
|
// No sleeping if it's our first failed attempt.
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function onEndCheckPassword($nickname, $password, $authenticatedUser)
|
|
{
|
|
if ($authenticatedUser instanceof User) {
|
|
// We'll trust this IP for this user and remove failed logins for the database..
|
|
$authenticatedUser->delPref(self::FAILED_LOGIN_IP_SECTION, $this->client_ip);
|
|
return true;
|
|
}
|
|
|
|
// See if we have an unauthed user from before. If not, it might be because the User did
|
|
// not exist yet (such as autoregistering with LDAP, OpenID etc.).
|
|
if ($this->unauthed_user instanceof User) {
|
|
// And if the login failed, we'll increment the attempt count.
|
|
common_debug(sprintf('Failed login tests for user %s from IP %s',
|
|
$this->unauthed_user->getNickname(), $this->client_ip));
|
|
$this->unauthed_user->setPref(self::FAILED_LOGIN_IP_SECTION, $this->client_ip, ++$this->failed_attempts);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function onPluginVersion(array &$versions)
|
|
{
|
|
$versions[] = array('name' => 'AntiBrute',
|
|
'version' => self::PLUGIN_VERSION,
|
|
'author' => 'Mikael Nordfeldth',
|
|
'homepage' => 'http://gnu.io/',
|
|
'description' =>
|
|
// TRANS: Plugin description.
|
|
_m('Anti bruteforce method(s).'));
|
|
return true;
|
|
}
|
|
}
|