gnu-social/plugins/AntiBrute/AntiBrutePlugin.php
Diogo Cordeiro 46f98b3142 [VersionBump] 1.19.0, fairly late
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.0
c13b935201 1.18.3
c13b935201 1.18.2
18fc39d2cf 1.18.1
c083a8bcc2 1.18.0
e8783d46d0 1.17.1
d9a42550ff 1.17.0
1536d3ef29 1.16.0
c03ed457a6 1.15.0
d2e6519bad 1.14.2
fe411e8138 1.14.1
b17e0b4169 1.14.0
daa5f87fd4 1.13.0
d75b5d2f4a 1.11.7
f6dbf66983 1.11.6
6cf674f8f8 1.11.5
7845a09b34 1.11.4
e4d432295d 1.11.3
339204f1ee 1.11.2
a4e679a118 1.11.1
7967db6ff5 1.11.0
bc030da320 1.10.1
9cc7df51d6 1.10.0
bf7f17474d 1.9.2
8a07edec5f 1.9.1
0042971d74 1.9.0
6b5450b7e6 1.8.0
5dcc98d1c6 1.7.0
e6667db0cd 1.6.0
3290227b50 1.5.0
a59c439b46 1.4.0
496ab8c920 1.3.10
986030060b 1.3.9
1d529c021a 1.3.8
f89c052cf8 1.3.7
38f2ecefac 1.3.6
e473937cb9 1.3.5
9a39ebe66f 1.3.4
ddc3cecfc0 1.3.3
2b43d484eb 1.3.2
e8e487187e 1.3.1

== Plugins ==
XMPP plugin
e0887220b0 bump patch
e186ad57d0 bump patch

OStatus
e186ad57d0 bump patch

Nodeinfo
ceae66a30f bump minor
586fb5a517 bump major
195296846e bump minor
2019-06-07 15:02:08 +01:00

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;
}
}