Skip to content
Snippets Groups Projects
Unverified Commit be674c19 authored by Roeland Jago Douma's avatar Roeland Jago Douma
Browse files

Respect bruteforce settings in the Throttler

parent dca555b7
No related branches found
No related tags found
No related merge requests found
...@@ -185,6 +185,67 @@ class Throttler { ...@@ -185,6 +185,67 @@ class Throttler {
$qb->execute(); $qb->execute();
} }
/**
* Check if the IP is whitelisted
*
* @param string $ip
* @return bool
*/
private function isIPWhitelisted($ip) {
$keys = $this->config->getAppKeys('bruteForce');
$keys = array_filter($keys, function($key) {
$regex = '/^whitelist_/S';
return preg_match($regex, $key) === 1;
});
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$type = 4;
} else if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$type = 6;
} else {
return false;
}
$ip = inet_pton($ip);
foreach ($keys as $key) {
$cidr = $this->config->getAppValue('bruteForce', $key, null);
$cx = explode('/', $cidr);
$addr = $cx[0];
$mask = (int)$cx[1];
// Do not compare ipv4 to ipv6
if (($type === 4 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ||
($type === 6 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))) {
continue;
}
$addr = inet_pton($addr);
$valid = true;
for($i = 0; $i < $mask; $i++) {
$part = ord($addr[(int)($i/8)]);
$orig = ord($ip[(int)($i/8)]);
$part = $part & (15 << (1 - ($i % 2)));
$orig = $orig & (15 << (1 - ($i % 2)));
if ($part !== $orig) {
$valid = false;
break;
}
}
if ($valid === true) {
return true;
}
}
return false;
}
/** /**
* Get the throttling delay (in milliseconds) * Get the throttling delay (in milliseconds)
* *
...@@ -193,6 +254,10 @@ class Throttler { ...@@ -193,6 +254,10 @@ class Throttler {
* @return int * @return int
*/ */
public function getDelay($ip, $action = '') { public function getDelay($ip, $action = '') {
if ($this->isIPWhitelisted($ip)) {
return 0;
}
$cutoffTime = (new \DateTime()) $cutoffTime = (new \DateTime())
->sub($this->getCutoff(43200)) ->sub($this->getCutoff(43200))
->getTimestamp(); ->getTimestamp();
......
...@@ -40,7 +40,7 @@ class ThrottlerTest extends TestCase { ...@@ -40,7 +40,7 @@ class ThrottlerTest extends TestCase {
private $dbConnection; private $dbConnection;
/** @var ILogger */ /** @var ILogger */
private $logger; private $logger;
/** @var IConfig */ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config; private $config;
public function setUp() { public function setUp() {
...@@ -120,4 +120,92 @@ class ThrottlerTest extends TestCase { ...@@ -120,4 +120,92 @@ class ThrottlerTest extends TestCase {
$this->invokePrivate($this->throttler, 'getIPv6Subnet', ['2001:0db8:85a3:0000:0000:8a2e:0370:7334', 40]) $this->invokePrivate($this->throttler, 'getIPv6Subnet', ['2001:0db8:85a3:0000:0000:8a2e:0370:7334', 40])
); );
} }
public function dataIsIPWhitelisted() {
return [
[
'10.10.10.10',
[
'whitelist_0' => '10.10.10.0/24',
],
true,
],
[
'10.10.10.10',
[
'whitelist_0' => '192.168.0.0/16',
],
false,
],
[
'10.10.10.10',
[
'whitelist_0' => '192.168.0.0/16',
'whitelist_1' => '10.10.10.0/24',
],
true,
],
[
'dead:beef:cafe::1',
[
'whitelist_0' => '192.168.0.0/16',
'whitelist_1' => '10.10.10.0/24',
'whitelist_2' => 'deaf:beef:cafe:1234::/64'
],
false,
],
[
'dead:beef:cafe::1',
[
'whitelist_0' => '192.168.0.0/16',
'whitelist_1' => '10.10.10.0/24',
'whitelist_2' => 'deaf:beef::/64'
],
false,
],
[
'dead:beef:cafe::1',
[
'whitelist_0' => '192.168.0.0/16',
'whitelist_1' => '10.10.10.0/24',
'whitelist_2' => 'deaf:cafe::/8'
],
true,
],
[
'invalid',
[],
false,
],
];
}
/**
* @dataProvider dataIsIPWhitelisted
*
* @param string $ip
* @param string[] $whitelists
* @param bool $isWhiteListed
*/
public function testIsIPWhitelisted($ip, $whitelists, $isWhiteListed) {
$this->config->method('getAppKeys')
->with($this->equalTo('bruteForce'))
->willReturn(array_keys($whitelists));
$this->config->method('getAppValue')
->will($this->returnCallback(function($app, $key, $default) use ($whitelists) {
if ($app !== 'bruteForce') {
return $default;
}
if (isset($whitelists[$key])) {
return $whitelists[$key];
}
return $default;
}));
$this->assertSame(
$isWhiteListed,
$this->invokePrivate($this->throttler, 'isIPWhitelisted', [$ip])
);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment