Merge pull request #26945 from nextcloud/enh/shareinfo/throttle

Add bruteforce protection to the shareinfo endpoint
This commit is contained in:
Roeland Jago Douma 2021-05-12 10:07:28 +02:00 committed by GitHub
commit 024ed97e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 5 deletions

View File

@ -48,7 +48,7 @@ class ShareInfoController extends ApiController {
* @param IRequest $request * @param IRequest $request
* @param IManager $shareManager * @param IManager $shareManager
*/ */
public function __construct($appName, public function __construct(string $appName,
IRequest $request, IRequest $request,
IManager $shareManager) { IManager $shareManager) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
@ -59,26 +59,32 @@ class ShareInfoController extends ApiController {
/** /**
* @PublicPage * @PublicPage
* @NoCSRFRequired * @NoCSRFRequired
* @BruteForceProtection(action=shareinfo)
* *
* @param string $t * @param string $t
* @param null $password * @param null $password
* @param null $dir * @param null $dir
* @return JSONResponse * @return JSONResponse
* @throws ShareNotFound
*/ */
public function info($t, $password = null, $dir = null) { public function info($t, $password = null, $dir = null) {
try { try {
$share = $this->shareManager->getShareByToken($t); $share = $this->shareManager->getShareByToken($t);
} catch (ShareNotFound $e) { } catch (ShareNotFound $e) {
return new JSONResponse([], Http::STATUS_NOT_FOUND); $response = new JSONResponse([], Http::STATUS_NOT_FOUND);
$response->throttle(['token' => $t]);
return $response;
} }
if ($share->getPassword() && !$this->shareManager->checkPassword($share, $password)) { if ($share->getPassword() && !$this->shareManager->checkPassword($share, $password)) {
return new JSONResponse([], Http::STATUS_FORBIDDEN); $response = new JSONResponse([], Http::STATUS_FORBIDDEN);
$response->throttle(['token' => $t]);
return $response;
} }
if (!($share->getPermissions() & Constants::PERMISSION_READ)) { if (!($share->getPermissions() & Constants::PERMISSION_READ)) {
return new JSONResponse([], Http::STATUS_FORBIDDEN); $response = new JSONResponse([], Http::STATUS_FORBIDDEN);
$response->throttle(['token' => $t]);
return $response;
} }
$permissionMask = $share->getPermissions(); $permissionMask = $share->getPermissions();

View File

@ -66,6 +66,7 @@ class ShareInfoControllerTest extends TestCase {
->willThrowException(new ShareNotFound()); ->willThrowException(new ShareNotFound());
$expected = new JSONResponse([], Http::STATUS_NOT_FOUND); $expected = new JSONResponse([], Http::STATUS_NOT_FOUND);
$expected->throttle(['token' => 'token']);
$this->assertEquals($expected, $this->controller->info('token')); $this->assertEquals($expected, $this->controller->info('token'));
} }
@ -82,6 +83,7 @@ class ShareInfoControllerTest extends TestCase {
->willReturn(false); ->willReturn(false);
$expected = new JSONResponse([], Http::STATUS_FORBIDDEN); $expected = new JSONResponse([], Http::STATUS_FORBIDDEN);
$expected->throttle(['token' => 'token']);
$this->assertEquals($expected, $this->controller->info('token', 'pass')); $this->assertEquals($expected, $this->controller->info('token', 'pass'));
} }
@ -100,6 +102,7 @@ class ShareInfoControllerTest extends TestCase {
->willReturn(true); ->willReturn(true);
$expected = new JSONResponse([], Http::STATUS_FORBIDDEN); $expected = new JSONResponse([], Http::STATUS_FORBIDDEN);
$expected->throttle(['token' => 'token']);
$this->assertEquals($expected, $this->controller->info('token', 'pass')); $this->assertEquals($expected, $this->controller->info('token', 'pass'));
} }