From 91f78ecd0f3ff7a2ae225a835b3c87b8a7224fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Tue, 5 May 2020 14:16:22 -0700 Subject: [PATCH 01/25] added "whitelist" under [traffic] --- cfg/conf.sample.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index d2d285de..e2d7fec8 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -127,6 +127,10 @@ markdown = "Markdown" ; Set this to 0 to disable rate limiting. limit = 10 +; (optional) if you only want some source IP addresses to create pastes +; enter their IPv4 address(es) here, separated by commas +; whitelist = "12.34.56.78,99.88.77.66" + ; (optional) if your website runs behind a reverse proxy or load balancer, ; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR ; header = "X_FORWARDED_FOR" From 5644001c5377b5a0791e136cb67436a77490db6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Tue, 5 May 2020 14:17:15 -0700 Subject: [PATCH 02/25] added "whitelist" under [traffic] --- lib/Configuration.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Configuration.php b/lib/Configuration.php index 06edf68b..aa6d15d0 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -78,6 +78,7 @@ class Configuration ), 'traffic' => array( 'limit' => 10, + 'whitelist' => null, 'header' => null, 'dir' => 'data', ), From 9327c9b58bc70709ce27ca30d29f63e4d801bd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Tue, 5 May 2020 14:18:52 -0700 Subject: [PATCH 03/25] added whitelist check --- lib/Controller.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/Controller.php b/lib/Controller.php index 21a27b27..5db14c22 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -196,6 +196,19 @@ class Controller */ private function _create() { + // Check whitelist if allowed to create + $whitelist = explode(',', $this->_conf->getKey('whitelist', 'traffic')); + if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { + $httpHeader = 'HTTP_' . $option; + if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { + $remoteip = $_SERVER[$httpHeader]; + } + } + if( !in_array($remoteip, $whitelist) ) { + $this->_return_message(1, I18n::_('Your IP is not authorized')); + return; + } + // Ensure last paste from visitors IP address was more than configured amount of seconds ago. TrafficLimiter::setConfiguration($this->_conf); if (!TrafficLimiter::canPass()) { From 9ca041fa068e9ecb30a8924b91778ffc9f9c396a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 15:53:56 -0700 Subject: [PATCH 04/25] Update lib/Controller.php Co-authored-by: rugk --- lib/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller.php b/lib/Controller.php index 5db14c22..c202f391 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -205,7 +205,7 @@ class Controller } } if( !in_array($remoteip, $whitelist) ) { - $this->_return_message(1, I18n::_('Your IP is not authorized')); + $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); return; } From ef9780707a941780bf13caa29e9ef28858f4b56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 15:54:13 -0700 Subject: [PATCH 05/25] Update lib/Controller.php Co-authored-by: rugk --- lib/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller.php b/lib/Controller.php index c202f391..4f3cbdf9 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -204,7 +204,7 @@ class Controller $remoteip = $_SERVER[$httpHeader]; } } - if( !in_array($remoteip, $whitelist) ) { + if(!in_array($remoteip, $whitelist)) { $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); return; } From cea96ee12a1e3e91c72f6efe6cac636cca6a80a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 15:55:09 -0700 Subject: [PATCH 06/25] Update cfg/conf.sample.php Co-authored-by: rugk --- cfg/conf.sample.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index e2d7fec8..52f152e5 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -129,7 +129,7 @@ limit = 10 ; (optional) if you only want some source IP addresses to create pastes ; enter their IPv4 address(es) here, separated by commas -; whitelist = "12.34.56.78,99.88.77.66" +; whitelist_paste_creation = "12.34.56.78,99.88.77.66" ; (optional) if your website runs behind a reverse proxy or load balancer, ; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR From 819d25a74cfdde26be18d592e827ab24e49e2b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 16:13:25 -0700 Subject: [PATCH 07/25] change to whitelist_paste_creation --- lib/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller.php b/lib/Controller.php index 4f3cbdf9..45b6dacd 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -197,7 +197,7 @@ class Controller private function _create() { // Check whitelist if allowed to create - $whitelist = explode(',', $this->_conf->getKey('whitelist', 'traffic')); + $whitelist = explode(',', $this->_conf->getKey('whitelist_paste_creation', 'traffic')); if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { $httpHeader = 'HTTP_' . $option; if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { From c152f85b50cf38c83562bd9e7dfde543cce0d49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 16:45:24 -0700 Subject: [PATCH 08/25] removed $remoteip that the audit didn't like --- lib/Controller.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Controller.php b/lib/Controller.php index 45b6dacd..00bd981b 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -201,13 +201,13 @@ class Controller if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { $httpHeader = 'HTTP_' . $option; if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { - $remoteip = $_SERVER[$httpHeader]; + // compare source IP from web server with whitelist + if(!in_array($_SERVER[$httpHeader], $whitelist)) { + $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); + return; + } } } - if(!in_array($remoteip, $whitelist)) { - $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); - return; - } // Ensure last paste from visitors IP address was more than configured amount of seconds ago. TrafficLimiter::setConfiguration($this->_conf); From d847e2fcf22d72fe62b9e9c78972bf20c7b85f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 16:46:31 -0700 Subject: [PATCH 09/25] alignment --- lib/Configuration.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Configuration.php b/lib/Configuration.php index aa6d15d0..95f54253 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -77,10 +77,10 @@ class Configuration 'markdown' => 'Markdown', ), 'traffic' => array( - 'limit' => 10, + 'limit' => 10, 'whitelist' => null, - 'header' => null, - 'dir' => 'data', + 'header' => null, + 'dir' => 'data', ), 'purge' => array( 'limit' => 300, From b8594c174a1027bb6cd449e4cb50f99617055ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Thu, 7 May 2020 16:48:17 -0700 Subject: [PATCH 10/25] whitelist_paste_creation description --- cfg/conf.sample.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index 52f152e5..6b266a7c 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -128,7 +128,8 @@ markdown = "Markdown" limit = 10 ; (optional) if you only want some source IP addresses to create pastes -; enter their IPv4 address(es) here, separated by commas +; enter their IPv4 address(es) here, separated by commas. This does not +; currently support CIDR notation, only individual IPv4 addresses. ; whitelist_paste_creation = "12.34.56.78,99.88.77.66" ; (optional) if your website runs behind a reverse proxy or load balancer, From 8fbdb69d8a2daf48c96ce39bc91bafbc2febb451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Fri, 8 May 2020 11:36:19 -0700 Subject: [PATCH 11/25] added check for null whitelist --- lib/Controller.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/Controller.php b/lib/Controller.php index 00bd981b..6b1dbcb5 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -196,16 +196,21 @@ class Controller */ private function _create() { - // Check whitelist if allowed to create - $whitelist = explode(',', $this->_conf->getKey('whitelist_paste_creation', 'traffic')); - if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { - $httpHeader = 'HTTP_' . $option; - if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { - // compare source IP from web server with whitelist - if(!in_array($_SERVER[$httpHeader], $whitelist)) { - $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); - return; - } + // Check if whitelist feature is enabled + if (($option = $this->_conf->getKey('whitelist', 'traffic')) !== null) { + // Parse whitelist into array + $whitelist = explode(',', $this->_conf->getKey('whitelist_paste_creation', 'traffic')); + // Check for source IP in HTTP header + if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { + $httpHeader = 'HTTP_' . $option; + // Grab source IP from HTTP header (if it exists) + if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { + // Check if source IP reported from HTTP header is in whitelist array + if (!in_array($_SERVER[$httpHeader], $whitelist)) { + $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); + return; + } + } } } From effe6ad3e55201d7999c20873a28ab1bba8bc3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Fri, 8 May 2020 11:37:21 -0700 Subject: [PATCH 12/25] fixed spacing to please StyleCI --- lib/Controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Controller.php b/lib/Controller.php index 6b1dbcb5..2c08b308 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -209,11 +209,11 @@ class Controller if (!in_array($_SERVER[$httpHeader], $whitelist)) { $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); return; - } + } } } } - + // Ensure last paste from visitors IP address was more than configured amount of seconds ago. TrafficLimiter::setConfiguration($this->_conf); if (!TrafficLimiter::canPass()) { From 3f75c81a2feaa1c2350f2d674c86e5a0dc936471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Andr=C3=A9s?= Date: Fri, 8 May 2020 12:18:20 -0700 Subject: [PATCH 13/25] fixed duplicated getKey() --- lib/Controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Controller.php b/lib/Controller.php index 2c08b308..0aa3fe1a 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -197,9 +197,9 @@ class Controller private function _create() { // Check if whitelist feature is enabled - if (($option = $this->_conf->getKey('whitelist', 'traffic')) !== null) { + if (($option = $this->_conf->getKey('whitelist_paste_creation', 'traffic')) !== null) { // Parse whitelist into array - $whitelist = explode(',', $this->_conf->getKey('whitelist_paste_creation', 'traffic')); + $whitelist = explode(',', $option); // Check for source IP in HTTP header if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { $httpHeader = 'HTTP_' . $option; From 91041d8c59d81e5c2675d8c3c5021e471da0cfcb Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 09:09:20 +0100 Subject: [PATCH 14/25] simplify/unify naming & wording of the two types of IP lists for the traffic limiter --- cfg/conf.sample.php | 17 ++++++++++------- lib/Configuration.php | 8 ++++---- lib/Controller.php | 2 +- lib/Persistence/TrafficLimiter.php | 20 ++++++++++---------- tst/Persistence/TrafficLimiterTest.php | 4 ++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index d7e21f86..3bc4ec66 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -135,14 +135,17 @@ markdown = "Markdown" ; Set this to 0 to disable rate limiting. limit = 10 -; Set ips (v4|v6) which should be exempted for the rate-limit. CIDR also supported. Needed to be comma separated. -; Unset for enabling and invalid values will be ignored -; eg: exemptedIp = '1.2.3.4,10.10.10/24' +; (optional) Set IPs adresses (v4 or v6) or subnets (CIDR) which are exempted +; from the rate-limit. Invalid IPs will be ignored. If multiple values are to +; be exempted, the list needs to be comma separated. Leave unset to disable +; exemptions. +; exempted = "1.2.3.4,10.10.10/24" -; (optional) if you only want some source IP addresses to create pastes -; enter their IPv4 address(es) here, separated by commas. This does not -; currently support CIDR notation, only individual IPv4 addresses. -; whitelist_paste_creation = "12.34.56.78,99.88.77.66" +; (optional) If you want only some source IP addresses (v4 or v6) or subnets +; (CIDR) to be allowed to create pastes, set these here. Invalid IPs will be +; ignored. If multiple values are to be exempted, the list needs to be comma +; separated. Leave unset to allow anyone to create pastes. +; creators = "1.2.3.4,10.10.10/24" ; (optional) if your website runs behind a reverse proxy or load balancer, ; set the HTTP header containing the visitors IP address, i.e. X_FORWARDED_FOR diff --git a/lib/Configuration.php b/lib/Configuration.php index c3a6fa25..130eecf6 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -78,10 +78,10 @@ class Configuration 'markdown' => 'Markdown', ), 'traffic' => array( - 'limit' => 10, - 'header' => null, - 'exemptedIp' => null, - 'whitelist' => null, + 'limit' => 10, + 'header' => '', + 'exempted' => '', + 'creators' => '', ), 'purge' => array( 'limit' => 300, diff --git a/lib/Controller.php b/lib/Controller.php index b150691a..8ead8848 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -196,7 +196,7 @@ class Controller private function _create() { // Check if whitelist feature is enabled - if (($option = $this->_conf->getKey('whitelist_paste_creation', 'traffic')) !== null) { + if (($option = $this->_conf->getKey('creators', 'traffic')) !== '') { // Parse whitelist into array $whitelist = explode(',', $option); // Check for source IP in HTTP header diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 9e896c1d..168b46c0 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -33,13 +33,13 @@ class TrafficLimiter extends AbstractPersistence private static $_limit = 10; /** - * listed ips are exempted from limits, defaults to null + * listed IPs are exempted from limits, defaults to null * * @access private * @static * @var string|null */ - private static $_exemptedIp = null; + private static $_exempted = null; /** * key to fetch IP address @@ -63,15 +63,15 @@ class TrafficLimiter extends AbstractPersistence } /** - * set a list of ip(ranges) as string + * set a list of IP(-ranges) as string * * @access public * @static - * @param string $exemptedIps + * @param string $exempted */ - public static function setExemptedIp($exemptedIp) + public static function setExempted($exempted) { - self::$_exemptedIp = $exemptedIp; + self::$_exempted = $exempted; } /** @@ -84,9 +84,9 @@ class TrafficLimiter extends AbstractPersistence public static function setConfiguration(Configuration $conf) { self::setLimit($conf->getKey('limit', 'traffic')); - self::setExemptedIp($conf->getKey('exemptedIp', 'traffic')); + self::setExempted($conf->getKey('exempted', 'traffic')); - if (($option = $conf->getKey('header', 'traffic')) !== null) { + if (($option = $conf->getKey('header', 'traffic')) !== '') { $httpHeader = 'HTTP_' . $option; if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { self::$_ipKey = $httpHeader; @@ -152,8 +152,8 @@ class TrafficLimiter extends AbstractPersistence } // Check if $_ipKey is exempted from ratelimiting - if (!is_null(self::$_exemptedIp)) { - $exIp_array = explode(',', self::$_exemptedIp); + if (!empty(self::$_exempted)) { + $exIp_array = explode(',', self::$_exempted); foreach ($exIp_array as $ipRange) { if (self::matchIp($ipRange) === true) { return true; diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index aedbf889..8c83f0b5 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -47,7 +47,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertFalse(TrafficLimiter::canPass(), 'fifth request is to fast, may not pass'); // exempted IPs configuration - TrafficLimiter::setExemptedIp('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); + TrafficLimiter::setExempted('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); $this->assertFalse(TrafficLimiter::canPass(), 'still too fast and not exempted'); $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in exempted range'); @@ -55,7 +55,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in exempted range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in exempted range'); - TrafficLimiter::setExemptedIp('127.*,foobar'); + TrafficLimiter::setExempted('127.*,foobar'); $this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, invalid range'); $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); From 190a35a53bdd29aedbf0331fc300fe89819a8465 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 09:30:41 +0100 Subject: [PATCH 15/25] small unit test refactoring, comment wording --- lib/Persistence/TrafficLimiter.php | 2 +- tst/Persistence/TrafficLimiterTest.php | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index 168b46c0..f5f8e7a8 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -161,7 +161,7 @@ class TrafficLimiter extends AbstractPersistence } } - // this hash is used as an array key, hence a shorter algo is used + // used as array key, which are limited in length, hence using algo with shorter range $hash = self::getHash('sha256'); $now = time(); $tl = (int) self::$_store->getValue('traffic_limiter', $hash); diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 8c83f0b5..289598ef 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -45,10 +45,14 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertTrue(TrafficLimiter::canPass(), 'fourth request has different ip and may pass'); $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $this->assertFalse(TrafficLimiter::canPass(), 'fifth request is to fast, may not pass'); + } - // exempted IPs configuration + public function testTrafficLimitExempted() + { TrafficLimiter::setExempted('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); - $this->assertFalse(TrafficLimiter::canPass(), 'still too fast and not exempted'); + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $this->assertTrue(TrafficLimiter::canPass(), 'first request may pass'); + $this->assertFalse(TrafficLimiter::canPass(), 'not exempted'); $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in exempted range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in exempted range'); @@ -56,6 +60,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in exempted range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in exempted range'); TrafficLimiter::setExempted('127.*,foobar'); + $this->assertTrue(TrafficLimiter::canPass(), 'first cached request may pass'); $this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, invalid range'); $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); From dbe8debe306c2453ed00ea381269ce044c889e44 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 09:35:05 +0100 Subject: [PATCH 16/25] add creator unit tests for refactoring target, currently failing --- tst/Persistence/TrafficLimiterTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 289598ef..4e56b8a3 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -66,4 +66,23 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches exempted range'); } + + public function testTrafficLimitCreators() + { + TrafficLimiter::setCreators('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $this->assertFalse(TrafficLimiter::canPass(), 'not a creator'); + $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; + $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in creator range'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in creator range'); + $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; + $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in creator range'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in creator range'); + TrafficLimiter::setExempted('127.*,foobar'); + $this->assertTrue(TrafficLimiter::canPass(), 'first cached request may pass'); + $this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, not a creator'); + $_SERVER['REMOTE_ADDR'] = 'foobar'; + $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches creator'); + } } From 1034d4038e6c59b5b4d69b3b9e8a9b0b35a6fc18 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 11:25:19 +0100 Subject: [PATCH 17/25] unify IP-related logic into traffic limiter --- lib/Controller.php | 29 ++------ lib/Persistence/TrafficLimiter.php | 93 ++++++++++++++++++-------- tst/Persistence/TrafficLimiterTest.php | 39 ++++++++--- 3 files changed, 101 insertions(+), 60 deletions(-) diff --git a/lib/Controller.php b/lib/Controller.php index 8ead8848..56f424c0 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -195,35 +195,14 @@ class Controller */ private function _create() { - // Check if whitelist feature is enabled - if (($option = $this->_conf->getKey('creators', 'traffic')) !== '') { - // Parse whitelist into array - $whitelist = explode(',', $option); - // Check for source IP in HTTP header - if (($option = $this->_conf->getKey('header', 'traffic')) !== null) { - $httpHeader = 'HTTP_' . $option; - // Grab source IP from HTTP header (if it exists) - if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { - // Check if source IP reported from HTTP header is in whitelist array - if (!in_array($_SERVER[$httpHeader], $whitelist)) { - $this->_return_message(1, I18n::_('Your IP is not authorized to create pastes.')); - return; - } - } - } - } - // Ensure last paste from visitors IP address was more than configured amount of seconds ago. ServerSalt::setStore($this->_model->getStore()); TrafficLimiter::setConfiguration($this->_conf); TrafficLimiter::setStore($this->_model->getStore()); - if (!TrafficLimiter::canPass()) { - $this->_return_message( - 1, I18n::_( - 'Please wait %d seconds between each post.', - $this->_conf->getKey('limit', 'traffic') - ) - ); + try { + TrafficLimiter::canPass(); + } catch (Exception $e) { + $this->_return_message(1, $e->getMessage()); return; } diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index f5f8e7a8..fab33c41 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -13,8 +13,10 @@ namespace PrivateBin\Persistence; +use Exception; use IPLib\Factory; use PrivateBin\Configuration; +use PrivateBin\I18n; /** * TrafficLimiter @@ -24,13 +26,13 @@ use PrivateBin\Configuration; class TrafficLimiter extends AbstractPersistence { /** - * time limit in seconds, defaults to 10s + * listed IPs are the only ones allowed to create, defaults to null * * @access private * @static - * @var int + * @var string|null */ - private static $_limit = 10; + private static $_creators = null; /** * listed IPs are exempted from limits, defaults to null @@ -51,19 +53,49 @@ class TrafficLimiter extends AbstractPersistence private static $_ipKey = 'REMOTE_ADDR'; /** - * set the time limit in seconds + * time limit in seconds, defaults to 10s + * + * @access private + * @static + * @var int + */ + private static $_limit = 10; + + /** + * set configuration options of the traffic limiter * * @access public * @static - * @param int $limit + * @param Configuration $conf */ - public static function setLimit($limit) + public static function setConfiguration(Configuration $conf) { - self::$_limit = $limit; + self::setCreators($conf->getKey('creators', 'traffic')); + self::setExempted($conf->getKey('exempted', 'traffic')); + self::setLimit($conf->getKey('limit', 'traffic')); + + if (($option = $conf->getKey('header', 'traffic')) !== '') { + $httpHeader = 'HTTP_' . $option; + if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { + self::$_ipKey = $httpHeader; + } + } } /** - * set a list of IP(-ranges) as string + * set a list of creator IP(-ranges) as string + * + * @access public + * @static + * @param string $creators + */ + public static function setCreators($creators) + { + self::$_creators = $creators; + } + + /** + * set a list of exempted IP(-ranges) as string * * @access public * @static @@ -75,23 +107,15 @@ class TrafficLimiter extends AbstractPersistence } /** - * set configuration options of the traffic limiter + * set the time limit in seconds * * @access public * @static - * @param Configuration $conf + * @param int $limit */ - public static function setConfiguration(Configuration $conf) + public static function setLimit($limit) { - self::setLimit($conf->getKey('limit', 'traffic')); - self::setExempted($conf->getKey('exempted', 'traffic')); - - if (($option = $conf->getKey('header', 'traffic')) !== '') { - $httpHeader = 'HTTP_' . $option; - if (array_key_exists($httpHeader, $_SERVER) && !empty($_SERVER[$httpHeader])) { - self::$_ipKey = $httpHeader; - } - } + self::$_limit = $limit; } /** @@ -108,7 +132,7 @@ class TrafficLimiter extends AbstractPersistence } /** - * Validate $_ipKey against configured ipranges. If matched we will ignore the ip + * validate $_ipKey against configured ipranges. If matched we will ignore the ip * * @access private * @static @@ -136,22 +160,33 @@ class TrafficLimiter extends AbstractPersistence } /** - * traffic limiter - * - * Make sure the IP address makes at most 1 request every 10 seconds. + * make sure the IP address is allowed to perfom a request * * @access public * @static - * @return bool + * @throws Exception + * @return true */ public static function canPass() { + // if creators are defined, the traffic limiter will only allow creation + // for these, with no limits, and skip any other rules + if (!empty(self::$_creators)) { + $creatorIps = explode(',', self::$_creators); + foreach ($creatorIps as $ipRange) { + if (self::matchIp($ipRange) === true) { + return true; + } + } + throw new Exception(I18n::_('Your IP is not authorized to create pastes.')); + } + // disable limits if set to less then 1 if (self::$_limit < 1) { return true; } - // Check if $_ipKey is exempted from ratelimiting + // check if $_ipKey is exempted from ratelimiting if (!empty(self::$_exempted)) { $exIp_array = explode(',', self::$_exempted); foreach ($exIp_array as $ipRange) { @@ -175,6 +210,10 @@ class TrafficLimiter extends AbstractPersistence if (!self::$_store->setValue((string) $tl, 'traffic_limiter', $hash)) { error_log('failed to store the traffic limiter, it probably contains outdated information'); } - return $result; + if ($result) return true; + throw new Exception(I18n::_( + 'Please wait %d seconds between each post.', + self::$_limit + )); } } diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 4e56b8a3..e5256c74 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -38,13 +38,21 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $this->assertTrue(TrafficLimiter::canPass(), 'first request may pass'); sleep(1); - $this->assertFalse(TrafficLimiter::canPass(), 'second request is to fast, may not pass'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'second request is to fast, may not pass'); + } sleep(4); $this->assertTrue(TrafficLimiter::canPass(), 'third request waited long enough and may pass'); $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; $this->assertTrue(TrafficLimiter::canPass(), 'fourth request has different ip and may pass'); $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - $this->assertFalse(TrafficLimiter::canPass(), 'fifth request is to fast, may not pass'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'fifth request is to fast, may not pass'); + } } public function testTrafficLimitExempted() @@ -52,7 +60,11 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase TrafficLimiter::setExempted('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; $this->assertTrue(TrafficLimiter::canPass(), 'first request may pass'); - $this->assertFalse(TrafficLimiter::canPass(), 'not exempted'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'not exempted'); + } $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in exempted range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in exempted range'); @@ -61,7 +73,11 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in exempted range'); TrafficLimiter::setExempted('127.*,foobar'); $this->assertTrue(TrafficLimiter::canPass(), 'first cached request may pass'); - $this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, invalid range'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'request is to fast, invalid range'); + } $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches exempted range'); @@ -71,16 +87,23 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase { TrafficLimiter::setCreators('1.2.3.4,10.10.10.0/24,2001:1620:2057::/48'); $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - $this->assertFalse(TrafficLimiter::canPass(), 'not a creator'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Your IP is not authorized to create pastes.', 'not a creator'); + } $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in creator range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in creator range'); $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in creator range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in creator range'); - TrafficLimiter::setExempted('127.*,foobar'); - $this->assertTrue(TrafficLimiter::canPass(), 'first cached request may pass'); - $this->assertFalse(TrafficLimiter::canPass(), 'request is to fast, not a creator'); + TrafficLimiter::setCreators('127.*,foobar'); + try { + $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Your IP is not authorized to create pastes.', 'request is to fast, not a creator'); + } $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches creator'); From 6b59d4f3806e27b483ae0d4521e7dd46073fe0af Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 11:51:41 +0100 Subject: [PATCH 18/25] document change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c3f8045..f861baa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * ADDED: Configuration option to exempt IPs from the rate-limiter (#787) * ADDED: Google Cloud Storage backend support (#795) * ADDED: Oracle database support (#868) + * ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883) * CHANGED: Language selection cookie only transmitted over HTTPS (#472) * CHANGED: Upgrading libraries to: random_compat 2.0.20 * CHANGED: Removed automatic `.ini` configuration file migration (#808) From 1054319313610579f773016c12e184b5c62bd12d Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 12:22:34 +0100 Subject: [PATCH 19/25] add new translation string --- i18n/ar.json | 3 ++- i18n/bg.json | 3 ++- i18n/ca.json | 3 ++- i18n/cs.json | 3 ++- i18n/de.json | 3 ++- i18n/el.json | 3 ++- i18n/en.json | 3 ++- i18n/es.json | 3 ++- i18n/et.json | 3 ++- i18n/fi.json | 3 ++- i18n/fr.json | 3 ++- i18n/he.json | 3 ++- i18n/hi.json | 3 ++- i18n/hu.json | 3 ++- i18n/id.json | 3 ++- i18n/it.json | 3 ++- i18n/ja.json | 3 ++- i18n/jbo.json | 3 ++- i18n/ku.json | 3 ++- i18n/la.json | 3 ++- i18n/lt.json | 3 ++- i18n/nl.json | 3 ++- i18n/no.json | 3 ++- i18n/oc.json | 3 ++- i18n/pl.json | 3 ++- i18n/pt.json | 3 ++- i18n/ru.json | 3 ++- i18n/sl.json | 3 ++- i18n/sv.json | 3 ++- i18n/tr.json | 3 ++- i18n/uk.json | 3 ++- i18n/zh.json | 3 ++- 32 files changed, 64 insertions(+), 32 deletions(-) diff --git a/i18n/ar.json b/i18n/ar.json index ddca0d62..1827ddf2 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/bg.json b/i18n/bg.json index 4a025389..717c5f18 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/ca.json b/i18n/ca.json index 02b48d73..245b884f 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/cs.json b/i18n/cs.json index e6eff88a..886e9c32 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Šifrovaná poznámka ve službě PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Navštivte tento odkaz pro zobrazení poznámky. Přeposláním URL umožníte také jiným lidem přístup.", "URL shortener may expose your decrypt key in URL.": "Zkracovač URL může odhalit váš dešifrovací klíč v URL.", - "Save paste": "Uložit příspěvek" + "Save paste": "Uložit příspěvek", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/de.json b/i18n/de.json index 0c4cd70e..c60c1563 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Verschlüsselte Notiz auf PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besuche diesen Link um das Dokument zu sehen. Wird die URL an eine andere Person gegeben, so kann diese Person ebenfalls auf dieses Dokument zugreifen.", "URL shortener may expose your decrypt key in URL.": "Der URL-Verkürzer kann den Schlüssel in der URL enthüllen.", - "Save paste": "Text speichern" + "Save paste": "Text speichern", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/el.json b/i18n/el.json index 6e33978d..acfca8f9 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/en.json b/i18n/en.json index a96bab5d..2ba6068f 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/es.json b/i18n/es.json index 5aa2b380..909b32cf 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Nota cifrada en PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite este enlace para ver la nota. Dar la URL a cualquier persona también les permite acceder a la nota.", "URL shortener may expose your decrypt key in URL.": "El acortador de URL puede exponer su clave de descifrado en el URL.", - "Save paste": "Guardar \"paste\"" + "Save paste": "Guardar \"paste\"", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/et.json b/i18n/et.json index 9ab2840c..f02cefba 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Krüpteeritud kiri PrivateBin-is", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kirja nägemiseks külasta seda linki. Teistele URL-i andmine lubab ka neil ligi pääseda kirjale.", "URL shortener may expose your decrypt key in URL.": "URL-i lühendaja võib paljastada sinu dekrüpteerimisvõtme URL-is.", - "Save paste": "Salvesta kleebe" + "Save paste": "Salvesta kleebe", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/fi.json b/i18n/fi.json index aea2b63c..0ad8c410 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Salattu viesti PrivateBinissä", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Käy tässä linkissä nähdäksesi viestin. URL:n antaminen kenellekään antaa heidänkin päästä katsomeen viestiä. ", "URL shortener may expose your decrypt key in URL.": "URL-lyhentäjä voi paljastaa purkuavaimesi URL:ssä.", - "Save paste": "Tallenna paste" + "Save paste": "Tallenna paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/fr.json b/i18n/fr.json index 0e14d799..b5767f70 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Message chiffré sur PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visiter ce lien pour voir la note. Donner l'URL à une autre personne lui permet également d'accéder à la note.", "URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.", - "Save paste": "Sauver le paste" + "Save paste": "Sauver le paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/he.json b/i18n/he.json index 046874e2..503dbc16 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "הערה מוצפנת ב־PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "נא לבקר בקישור כדי לצפות בהערה. מסירת הקישור לאנשים כלשהם תאפשר גם להם לגשת להערה.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/hi.json b/i18n/hi.json index 0cd2787a..4df6aa71 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/hu.json b/i18n/hu.json index 1cff1a6f..c9acb042 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Titkosított jegyzet a PrivateBinen", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Látogasd meg ezt a hivatkozást a bejegyzés megtekintéséhez. Ha mások számára is megadod ezt a linket, azzal hozzáférnek ők is.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/id.json b/i18n/id.json index e58900a9..1edeb997 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Catatan ter-ekrip di PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Kunjungi tautan ini untuk melihat catatan. Memberikan alamat URL pada siapapun juga, akan mengizinkan mereka untuk mengakses catatan, so pasti gitu loh Kaka.", "URL shortener may expose your decrypt key in URL.": "Pemendek URL mungkin akan menampakkan kunci dekrip Anda dalam URL.", - "Save paste": "Simpan paste" + "Save paste": "Simpan paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/it.json b/i18n/it.json index 659816e4..8b9f391f 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Nota crittografata su PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visita questo collegamento per vedere la nota. Dare l'URL a chiunque consente anche a loro di accedere alla nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener può esporre la tua chiave decrittografata nell'URL.", - "Save paste": "Salva il messagio" + "Save paste": "Salva il messagio", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/ja.json b/i18n/ja.json index 807a38c0..330032fd 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/jbo.json b/i18n/jbo.json index 10925d0f..82cea900 100644 --- a/i18n/jbo.json +++ b/i18n/jbo.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": ".i lo lo notci ku mifra cu zvati sivlolnitvanku'a", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "rejgau fukpi" + "Save paste": "rejgau fukpi", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/ku.json b/i18n/ku.json index ae72ebd8..bca43477 100644 --- a/i18n/ku.json +++ b/i18n/ku.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/la.json b/i18n/la.json index 2098982d..fe6c4001 100644 --- a/i18n/la.json +++ b/i18n/la.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/lt.json b/i18n/lt.json index 10b62d84..195fab06 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Šifruoti užrašai ties PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Norėdami matyti užrašus, aplankykite šį tinklalapį. Pasidalinus šiuo URL adresu su kitais žmonėmis, jiems taip pat bus leidžiama prieiga prie šių užrašų.", "URL shortener may expose your decrypt key in URL.": "URL trumpinimo įrankis gali atskleisti URL adrese jūsų iššifravimo raktą.", - "Save paste": "Įrašyti įdėjimą" + "Save paste": "Įrašyti įdėjimą", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/nl.json b/i18n/nl.json index 65c4e37c..b20416ae 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/no.json b/i18n/no.json index b0ca95a0..eda1e4c5 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Kryptert notat på PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Besøk denne lenken for å se notatet. Hvis lenken deles med andre, vil de også kunne se notatet.", "URL shortener may expose your decrypt key in URL.": "URL forkorter kan avsløre dekrypteringsnøkkelen.", - "Save paste": "Lagre utklipp" + "Save paste": "Lagre utklipp", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/oc.json b/i18n/oc.json index 6a0a69ce..1bb4de67 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Nòtas chifradas sus PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visitatz aqueste ligam per veire la nòta. Fornir lo ligam a qualqu’un mai li permet tanben d’accedir a la nòta.", "URL shortener may expose your decrypt key in URL.": "Los espleches d’acorchiment d’URL pòdon expausar la clau de deschiframent dins l’URL.", - "Save paste": "Enregistrar lo tèxt" + "Save paste": "Enregistrar lo tèxt", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/pl.json b/i18n/pl.json index 4b4a67be..b6127cad 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/pt.json b/i18n/pt.json index 0f6c1333..72d0250f 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Nota criptografada no PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visite esse link para ver a nota. Dar a URL para qualquer um permite que eles também acessem a nota.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/ru.json b/i18n/ru.json index a9112330..2d3edb9a 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Зашифрованная запись на PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Посетите эту ссылку чтобы просмотреть запись. Передача ссылки кому либо позволит им получить доступ к записи тоже.", "URL shortener may expose your decrypt key in URL.": "Сервис сокращения ссылок может получить ваш ключ расшифровки из ссылки.", - "Save paste": "Сохранить запись" + "Save paste": "Сохранить запись", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/sl.json b/i18n/sl.json index c4bb0cb7..27c43611 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/sv.json b/i18n/sv.json index f2286e02..bb613296 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/tr.json b/i18n/tr.json index 0abbc37d..c2c380e1 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/uk.json b/i18n/uk.json index 1916a244..52e97233 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "Encrypted note on PrivateBin", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.", "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.", - "Save paste": "Save paste" + "Save paste": "Save paste", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } diff --git a/i18n/zh.json b/i18n/zh.json index 2ab63bf4..e90627fb 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -185,5 +185,6 @@ "Encrypted note on PrivateBin": "PrivateBin 上的加密笔记", "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "访问此链接来查看该笔记。将此 URL 发送给任何人即可允许其访问该笔记。", "URL shortener may expose your decrypt key in URL.": "短链接服务可能会暴露您在 URL 中的解密密钥。", - "Save paste": "保存内容" + "Save paste": "保存内容", + "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes." } From f987e96d4b1edc336009062a7e31549886f540ef Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sun, 20 Feb 2022 12:25:55 +0100 Subject: [PATCH 20/25] apply StyleCI recommendation --- lib/Persistence/TrafficLimiter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index fab33c41..d0b82be9 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -210,7 +210,9 @@ class TrafficLimiter extends AbstractPersistence if (!self::$_store->setValue((string) $tl, 'traffic_limiter', $hash)) { error_log('failed to store the traffic limiter, it probably contains outdated information'); } - if ($result) return true; + if ($result) { + return true; + } throw new Exception(I18n::_( 'Please wait %d seconds between each post.', self::$_limit From 77153a9b493102fc5edbc7875ea11a862ae3b1fd Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 06:58:41 +0100 Subject: [PATCH 21/25] Update tst/Persistence/TrafficLimiterTest.php Co-authored-by: rugk --- tst/Persistence/TrafficLimiterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index e5256c74..6fe7de04 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -76,7 +76,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase try { $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); } catch (Exception $e) { - $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'request is to fast, invalid range'); + $this->assertEquals($e->getMessage(), 'Please wait 4 seconds between each post.', 'request is too fast, invalid range'); } $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); From 247992fbcad07e0639bb441f4f51790b1d630358 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 06:58:54 +0100 Subject: [PATCH 22/25] Update tst/Persistence/TrafficLimiterTest.php Co-authored-by: rugk --- tst/Persistence/TrafficLimiterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 6fe7de04..efa5746f 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -80,7 +80,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase } $_SERVER['REMOTE_ADDR'] = 'foobar'; $this->assertTrue(TrafficLimiter::canPass(), 'non-IP address'); - $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but non-IP address matches exempted range'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but non-IP address matches exempted range'); } public function testTrafficLimitCreators() From 094c96afc60a41c06aa6ddd00c542950caba45e8 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 06:59:02 +0100 Subject: [PATCH 23/25] Update tst/Persistence/TrafficLimiterTest.php Co-authored-by: rugk --- tst/Persistence/TrafficLimiterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index efa5746f..22463568 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -94,7 +94,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase } $_SERVER['REMOTE_ADDR'] = '10.10.10.10'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv4 in creator range'); - $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv4 in creator range'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but IPv4 in creator range'); $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in creator range'); $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in creator range'); From d544d5e763b3777c99035d77dd4b25cee02d70bf Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 06:59:11 +0100 Subject: [PATCH 24/25] Update tst/Persistence/TrafficLimiterTest.php Co-authored-by: rugk --- tst/Persistence/TrafficLimiterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tst/Persistence/TrafficLimiterTest.php b/tst/Persistence/TrafficLimiterTest.php index 22463568..a8b8040c 100644 --- a/tst/Persistence/TrafficLimiterTest.php +++ b/tst/Persistence/TrafficLimiterTest.php @@ -97,7 +97,7 @@ class TrafficLimiterTest extends PHPUnit_Framework_TestCase $this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but IPv4 in creator range'); $_SERVER['REMOTE_ADDR'] = '2001:1620:2057:dead:beef::cafe:babe'; $this->assertTrue(TrafficLimiter::canPass(), 'IPv6 in creator range'); - $this->assertTrue(TrafficLimiter::canPass(), 'request is to fast, but IPv6 in creator range'); + $this->assertTrue(TrafficLimiter::canPass(), 'request is too fast, but IPv6 in creator range'); TrafficLimiter::setCreators('127.*,foobar'); try { $this->assertFalse(TrafficLimiter::canPass(), 'expected an exception'); From fe89161848298f9583384e62ed3d769dcce2eda1 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Sat, 26 Feb 2022 07:18:59 +0100 Subject: [PATCH 25/25] replace deprecated function calls --- lib/Persistence/TrafficLimiter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Persistence/TrafficLimiter.php b/lib/Persistence/TrafficLimiter.php index d0b82be9..f071562b 100644 --- a/lib/Persistence/TrafficLimiter.php +++ b/lib/Persistence/TrafficLimiter.php @@ -15,6 +15,7 @@ namespace PrivateBin\Persistence; use Exception; use IPLib\Factory; +use IPLib\ParseStringFlag; use PrivateBin\Configuration; use PrivateBin\I18n; @@ -144,8 +145,8 @@ class TrafficLimiter extends AbstractPersistence if (is_string($ipRange)) { $ipRange = trim($ipRange); } - $address = Factory::addressFromString($_SERVER[self::$_ipKey]); - $range = Factory::rangeFromString($ipRange); + $address = Factory::parseAddressString($_SERVER[self::$_ipKey]); + $range = Factory::parseRangeString($ipRange, ParseStringFlag::IPV4_MAYBE_NON_DECIMAL); // address could not be parsed, we might not be in IP space and try a string comparison instead if (is_null($address)) {