diff --git a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php index a5af02af2ad..0a9bda68189 100644 --- a/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php +++ b/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php @@ -7,6 +7,7 @@ namespace OCA\CloudFederationAPI\Controller; +use OC\AppFramework\Http\Attributes\FederationRateLimit; use OC\Authentication\Token\PublicKeyTokenProvider; use OC\OCM\OCMSignatoryManager; use OCA\CloudFederationAPI\Config; @@ -107,6 +108,7 @@ class RequestHandlerController extends Controller { #[PublicPage] #[NoCSRFRequired] #[BruteForceProtection(action: 'receiveFederatedShare')] + #[FederationRateLimit(limit: 5, period: 1200)] public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) { if (!$this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_DISABLED, lazy: true)) { try { diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php index 219aabaecb5..e420741fbb4 100644 --- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php +++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php @@ -8,6 +8,7 @@ namespace OCA\FederatedFileSharing\Controller; +use OC\AppFramework\Http\Attributes\FederationRateLimit; use OCA\FederatedFileSharing\FederatedShareProvider; use OCP\App\IAppManager; use OCP\AppFramework\Http; @@ -30,7 +31,6 @@ use OCP\IDBConnection; use OCP\IRequest; use OCP\Log\Audit\CriticalActionPerformedEvent; use OCP\Server; -use OCP\Share; use OCP\Share\Exceptions\ShareNotFound; use Psr\Log\LoggerInterface; @@ -70,6 +70,7 @@ class RequestHandlerController extends OCSController { */ #[NoCSRFRequired] #[PublicPage] + #[FederationRateLimit(limit: 5, period: 1200)] public function createShare( ?string $remote = null, ?string $token = null, diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 1e741f5a116..030046d24d6 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1127,6 +1127,7 @@ return array( 'OC\\AppFramework\\Bootstrap\\ServiceRegistration' => $baseDir . '/lib/private/AppFramework/Bootstrap/ServiceRegistration.php', 'OC\\AppFramework\\DependencyInjection\\DIContainer' => $baseDir . '/lib/private/AppFramework/DependencyInjection/DIContainer.php', 'OC\\AppFramework\\Http' => $baseDir . '/lib/private/AppFramework/Http.php', + 'OC\\AppFramework\\Http\\Attributes\\FederationRateLimit' => $baseDir . '/lib/private/AppFramework/Http/Attributes/FederationRateLimit.php', 'OC\\AppFramework\\Http\\Attributes\\TwoFactorSetUpDoneRequired' => $baseDir . '/lib/private/AppFramework/Http/Attributes/TwoFactorSetUpDoneRequired.php', 'OC\\AppFramework\\Http\\Dispatcher' => $baseDir . '/lib/private/AppFramework/Http/Dispatcher.php', 'OC\\AppFramework\\Http\\Output' => $baseDir . '/lib/private/AppFramework/Http/Output.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e12aefe6657..7d9b979f6c9 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1168,6 +1168,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\AppFramework\\Bootstrap\\ServiceRegistration' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Bootstrap/ServiceRegistration.php', 'OC\\AppFramework\\DependencyInjection\\DIContainer' => __DIR__ . '/../../..' . '/lib/private/AppFramework/DependencyInjection/DIContainer.php', 'OC\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http.php', + 'OC\\AppFramework\\Http\\Attributes\\FederationRateLimit' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Attributes/FederationRateLimit.php', 'OC\\AppFramework\\Http\\Attributes\\TwoFactorSetUpDoneRequired' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Attributes/TwoFactorSetUpDoneRequired.php', 'OC\\AppFramework\\Http\\Dispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Dispatcher.php', 'OC\\AppFramework\\Http\\Output' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Output.php', diff --git a/lib/private/AppFramework/Http/Attributes/FederationRateLimit.php b/lib/private/AppFramework/Http/Attributes/FederationRateLimit.php new file mode 100644 index 00000000000..98930adceca --- /dev/null +++ b/lib/private/AppFramework/Http/Attributes/FederationRateLimit.php @@ -0,0 +1,55 @@ +discoveryService = Server::get(OCMDiscoveryService::class); + $this->trustedServers = Server::get(TrustedServers::class); + } + + #[\Override] + public function shouldApply(IRequest $request): bool { + if ($this->trustedServers === null) { + return true; + } + + try { + $signedRequest = $this->discoveryService->getIncomingSignedRequest(); + if (!$signedRequest) { + return true; + } + $signedRequest->verify(); + return !$this->trustedServers->isTrustedServer($signedRequest->getOrigin()); + } catch (\Exception) { + // no or invalid signature + return true; + } + } +}