Skip to content

Commit 0da05fc

Browse files
authored
Merge pull request #41435 from nextcloud/feat/migrate-bruteforce-throttle-check
Migrate bruteforce throttle check
2 parents 753e7c2 + fe8b5d4 commit 0da05fc

8 files changed

Lines changed: 74 additions & 79 deletions

File tree

apps/settings/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
'OCA\\Settings\\Settings\\Personal\\Security\\TwoFactor' => $baseDir . '/../lib/Settings/Personal/Security/TwoFactor.php',
7474
'OCA\\Settings\\Settings\\Personal\\Security\\WebAuthn' => $baseDir . '/../lib/Settings/Personal/Security/WebAuthn.php',
7575
'OCA\\Settings\\Settings\\Personal\\ServerDevNotice' => $baseDir . '/../lib/Settings/Personal/ServerDevNotice.php',
76+
'OCA\\Settings\\SetupChecks\\BruteForceThrottler' => $baseDir . '/../lib/SetupChecks/BruteForceThrottler.php',
7677
'OCA\\Settings\\SetupChecks\\CheckUserCertificates' => $baseDir . '/../lib/SetupChecks/CheckUserCertificates.php',
7778
'OCA\\Settings\\SetupChecks\\DefaultPhoneRegionSet' => $baseDir . '/../lib/SetupChecks/DefaultPhoneRegionSet.php',
7879
'OCA\\Settings\\SetupChecks\\EmailTestSuccessful' => $baseDir . '/../lib/SetupChecks/EmailTestSuccessful.php',

apps/settings/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class ComposerStaticInitSettings
8888
'OCA\\Settings\\Settings\\Personal\\Security\\TwoFactor' => __DIR__ . '/..' . '/../lib/Settings/Personal/Security/TwoFactor.php',
8989
'OCA\\Settings\\Settings\\Personal\\Security\\WebAuthn' => __DIR__ . '/..' . '/../lib/Settings/Personal/Security/WebAuthn.php',
9090
'OCA\\Settings\\Settings\\Personal\\ServerDevNotice' => __DIR__ . '/..' . '/../lib/Settings/Personal/ServerDevNotice.php',
91+
'OCA\\Settings\\SetupChecks\\BruteForceThrottler' => __DIR__ . '/..' . '/../lib/SetupChecks/BruteForceThrottler.php',
9192
'OCA\\Settings\\SetupChecks\\CheckUserCertificates' => __DIR__ . '/..' . '/../lib/SetupChecks/CheckUserCertificates.php',
9293
'OCA\\Settings\\SetupChecks\\DefaultPhoneRegionSet' => __DIR__ . '/..' . '/../lib/SetupChecks/DefaultPhoneRegionSet.php',
9394
'OCA\\Settings\\SetupChecks\\EmailTestSuccessful' => __DIR__ . '/..' . '/../lib/SetupChecks/EmailTestSuccessful.php',

apps/settings/lib/AppInfo/Application.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
use OCA\Settings\Search\AppSearch;
4949
use OCA\Settings\Search\SectionSearch;
5050
use OCA\Settings\Search\UserSearch;
51+
use OCA\Settings\SetupChecks\BruteForceThrottler;
5152
use OCA\Settings\SetupChecks\CheckUserCertificates;
5253
use OCA\Settings\SetupChecks\DefaultPhoneRegionSet;
5354
use OCA\Settings\SetupChecks\EmailTestSuccessful;
@@ -156,6 +157,7 @@ public function register(IRegistrationContext $context): void {
156157
Util::getDefaultEmailAddress('no-reply')
157158
);
158159
});
160+
$context->registerSetupCheck(BruteForceThrottler::class);
159161
$context->registerSetupCheck(CheckUserCertificates::class);
160162
$context->registerSetupCheck(DefaultPhoneRegionSet::class);
161163
$context->registerSetupCheck(EmailTestSuccessful::class);

apps/settings/lib/Controller/CheckSetupController.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
use OCP\IURLGenerator;
7979
use OCP\Lock\ILockingProvider;
8080
use OCP\Notification\IManager;
81-
use OCP\Security\Bruteforce\IThrottler;
8281
use OCP\SetupCheck\ISetupCheckManager;
8382
use Psr\Log\LoggerInterface;
8483

@@ -108,8 +107,6 @@ class CheckSetupController extends Controller {
108107
private $iniGetWrapper;
109108
/** @var IDBConnection */
110109
private $connection;
111-
/** @var IThrottler */
112-
private $throttler;
113110
/** @var ITempManager */
114111
private $tempManager;
115112
/** @var IManager */
@@ -134,7 +131,6 @@ public function __construct($AppName,
134131
IDateTimeFormatter $dateTimeFormatter,
135132
IniGetWrapper $iniGetWrapper,
136133
IDBConnection $connection,
137-
IThrottler $throttler,
138134
ITempManager $tempManager,
139135
IManager $manager,
140136
IAppManager $appManager,
@@ -150,7 +146,6 @@ public function __construct($AppName,
150146
$this->logger = $logger;
151147
$this->dispatcher = $dispatcher;
152148
$this->db = $db;
153-
$this->throttler = $throttler;
154149
$this->lockingProvider = $lockingProvider;
155150
$this->dateTimeFormatter = $dateTimeFormatter;
156151
$this->iniGetWrapper = $iniGetWrapper;
@@ -725,8 +720,6 @@ public function check() {
725720
'cronInfo' => $this->getLastCronInfo(),
726721
'cronErrors' => $this->getCronErrors(),
727722
'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(),
728-
'isBruteforceThrottled' => $this->throttler->getAttempts($this->request->getRemoteAddress()) !== 0,
729-
'bruteforceRemoteAddress' => $this->request->getRemoteAddress(),
730723
'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
731724
'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
732725
'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright Copyright (c) 2023 Côme Chilliet <come.chilliet@nextcloud.com>
7+
*
8+
* @author Côme Chilliet <come.chilliet@nextcloud.com>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
namespace OCA\Settings\SetupChecks;
28+
29+
use OCP\IL10N;
30+
use OCP\IRequest;
31+
use OCP\IURLGenerator;
32+
use OCP\Security\Bruteforce\IThrottler;
33+
use OCP\SetupCheck\ISetupCheck;
34+
use OCP\SetupCheck\SetupResult;
35+
36+
class BruteForceThrottler implements ISetupCheck {
37+
public function __construct(
38+
private IL10N $l10n,
39+
private IURLGenerator $urlGenerator,
40+
private IRequest $request,
41+
private IThrottler $throttler,
42+
) {
43+
}
44+
45+
public function getCategory(): string {
46+
return 'system';
47+
}
48+
49+
public function getName(): string {
50+
return $this->l10n->t('Bruteforce Throttle');
51+
}
52+
53+
public function run(): SetupResult {
54+
$address = $this->request->getRemoteAddress();
55+
if ($address === '') {
56+
return SetupResult::info(
57+
$this->l10n->t('Your remote address could not be determined.')
58+
);
59+
} elseif ($this->throttler->showBruteforceWarning($address)) {
60+
return SetupResult::error(
61+
$this->l10n->t('Your remote address was identified as "%s" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly.', $address),
62+
$this->urlGenerator->linkToDocs('admin-reverse-proxy')
63+
);
64+
} else {
65+
return SetupResult::success(
66+
$this->l10n->t('Your remote address "%s" is not bruteforce throttled.', $address)
67+
);
68+
}
69+
}
70+
}

apps/settings/tests/Controller/CheckSetupControllerTest.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
use OCP\IURLGenerator;
5858
use OCP\Lock\ILockingProvider;
5959
use OCP\Notification\IManager;
60-
use OCP\Security\Bruteforce\IThrottler;
6160
use OCP\SetupCheck\ISetupCheckManager;
6261
use PHPUnit\Framework\MockObject\MockObject;
6362
use Psr\Http\Message\ResponseInterface;
@@ -91,7 +90,6 @@ class CheckSetupControllerTest extends TestCase {
9190
private $dispatcher;
9291
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject */
9392
private $db;
94-
private IThrottler $throttler;
9593
/** @var ILockingProvider|\PHPUnit\Framework\MockObject\MockObject */
9694
private $lockingProvider;
9795
/** @var IDateTimeFormatter|\PHPUnit\Framework\MockObject\MockObject */
@@ -142,7 +140,6 @@ protected function setUp(): void {
142140
$this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
143141
$this->db = $this->getMockBuilder(Connection::class)
144142
->disableOriginalConstructor()->getMock();
145-
$this->throttler = $this->createMock(IThrottler::class);
146143
$this->lockingProvider = $this->getMockBuilder(ILockingProvider::class)->getMock();
147144
$this->dateTimeFormatter = $this->getMockBuilder(IDateTimeFormatter::class)->getMock();
148145
$this->iniGetWrapper = $this->getMockBuilder(IniGetWrapper::class)->getMock();
@@ -169,7 +166,6 @@ protected function setUp(): void {
169166
$this->dateTimeFormatter,
170167
$this->iniGetWrapper,
171168
$this->connection,
172-
$this->throttler,
173169
$this->tempManager,
174170
$this->notificationManager,
175171
$this->appManager,
@@ -441,8 +437,6 @@ public function testCheck() {
441437
'imageMagickLacksSVGSupport' => false,
442438
'isFairUseOfFreePushService' => false,
443439
'temporaryDirectoryWritable' => false,
444-
'isBruteforceThrottled' => false,
445-
'bruteforceRemoteAddress' => '',
446440
'generic' => [],
447441
]
448442
);
@@ -466,7 +460,6 @@ public function testGetCurlVersion() {
466460
$this->dateTimeFormatter,
467461
$this->iniGetWrapper,
468462
$this->connection,
469-
$this->throttler,
470463
$this->tempManager,
471464
$this->notificationManager,
472465
$this->appManager,
@@ -1193,7 +1186,6 @@ public function testIsMysqlUsedWithoutUTF8MB4(string $db, bool $useUTF8MB4, bool
11931186
$this->dateTimeFormatter,
11941187
$this->iniGetWrapper,
11951188
$this->connection,
1196-
$this->throttler,
11971189
$this->tempManager,
11981190
$this->notificationManager,
11991191
$this->appManager,
@@ -1247,7 +1239,6 @@ public function testIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(string $m
12471239
$this->dateTimeFormatter,
12481240
$this->iniGetWrapper,
12491241
$this->connection,
1250-
$this->throttler,
12511242
$this->tempManager,
12521243
$this->notificationManager,
12531244
$this->appManager,

core/js/setupchecks.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,6 @@
180180
var afterCall = function(data, statusText, xhr) {
181181
var messages = [];
182182
if (xhr.status === 200 && data) {
183-
if (data.isBruteforceThrottled) {
184-
messages.push({
185-
msg: t('core', 'Your remote address was identified as "{remoteAddress}" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly. Further information can be found in the {linkstart}documentation ↗{linkend}.', { remoteAddress: data.bruteforceRemoteAddress })
186-
.replace('{linkstart}', '<a target="_blank" rel="noreferrer noopener" class="external" href="' + data.reverseProxyDocs + '">')
187-
.replace('{linkend}', '</a>'),
188-
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
189-
});
190-
}
191183
if (data.suggestedOverwriteCliURL !== '') {
192184
messages.push({
193185
msg: t('core', 'Please make sure to set the "overwrite.cli.url" option in your config.php file to the URL that your users mainly use to access this Nextcloud. Suggestion: "{suggestedOverwriteCliURL}". Otherwise there might be problems with the URL generation via cron. (It is possible though that the suggested URL is not the URL that your users mainly use to access this Nextcloud. Best is to double check this in any case.)', {suggestedOverwriteCliURL: data.suggestedOverwriteCliURL}),

core/js/tests/specs/setupchecksSpec.js

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -535,61 +535,6 @@ describe('OC.SetupChecks tests', function() {
535535
});
536536
});
537537

538-
it('should return an error if the admin IP is bruteforce throttled', function(done) {
539-
var async = OC.SetupChecks.checkSetup();
540-
541-
suite.server.requests[0].respond(
542-
200,
543-
{
544-
'Content-Type': 'application/json',
545-
},
546-
JSON.stringify({
547-
suggestedOverwriteCliURL: '',
548-
isFairUseOfFreePushService: true,
549-
isBruteforceThrottled: true,
550-
bruteforceRemoteAddress: '::1',
551-
forwardedForHeadersWorking: true,
552-
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
553-
isCorrectMemcachedPHPModuleInstalled: true,
554-
hasPassedCodeIntegrityCheck: true,
555-
OpcacheSetupRecommendations: [],
556-
isSettimelimitAvailable: true,
557-
missingIndexes: [],
558-
missingPrimaryKeys: [],
559-
missingColumns: [],
560-
cronErrors: [],
561-
cronInfo: {
562-
diffInSeconds: 0
563-
},
564-
appDirsWithDifferentOwner: [],
565-
isImagickEnabled: true,
566-
areWebauthnExtensionsEnabled: true,
567-
pendingBigIntConversionColumns: [],
568-
isMysqlUsedWithoutUTF8MB4: false,
569-
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
570-
reverseProxyGeneratedURL: 'https://server',
571-
temporaryDirectoryWritable: true,
572-
generic: {
573-
network: {
574-
"Internet connectivity": {
575-
severity: "success",
576-
description: null,
577-
linkToDoc: null
578-
}
579-
},
580-
},
581-
})
582-
);
583-
584-
async.done(function( data, s, x ){
585-
expect(data).toEqual([{
586-
msg: 'Your remote address was identified as "::1" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly. Further information can be found in the <a target="_blank" rel="noreferrer noopener" class="external" href="https://docs.nextcloud.com/foo/bar.html">documentation ↗</a>.',
587-
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
588-
}]);
589-
done();
590-
});
591-
});
592-
593538
it('should return an error if set_time_limit is unavailable', function(done) {
594539
var async = OC.SetupChecks.checkSetup();
595540

0 commit comments

Comments
 (0)