diff --git a/appinfo/info.xml b/appinfo/info.xml index daef390dcb48cf81a2012d7b6386e4d1ccaf0832..7c1305a22391aa68e5cc126e0490147d51b01323 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -14,6 +14,9 @@ agpl Murena SAS EcloudAccounts + + + tools https://gitlab.e.foundation/e/management/issues diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 1beceac88e28707aaeaa730130a3730520d5f194..53af2ea3e3a488554c39b9e3c2c9ba9af510d317 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -27,6 +27,7 @@ declare(strict_types=1); namespace OCA\EcloudAccounts\AppInfo; use OC\Files\Filesystem; +use OCA\EcloudAccounts\Dav\CheckPlugin; use OCA\EcloudAccounts\Filesystem\StorageWrapper; use OCA\EcloudAccounts\Listeners\BeforeTemplateRenderedListener; use OCA\EcloudAccounts\Listeners\BeforeUserDeletedListener; @@ -41,8 +42,10 @@ use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Storage\IStorage; use OCP\IUserManager; +use OCP\SabrePluginEvent; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\PasswordUpdatedEvent; use OCP\User\Events\UserChangedEvent; @@ -67,6 +70,8 @@ class Application extends App implements IBootstrap { } public function boot(IBootContext $context): void { + $eventDispatcher = $context->getServerContainer()->get(IEventDispatcher::class); + $eventDispatcher->addListener('OCA\DAV\Connector\Sabre::addPlugin', [$this, 'registerDavPlugin']); $serverContainer = $context->getServerContainer(); $serverContainer->registerService('LDAPConnectionService', function ($c) { return new LDAPConnectionService( @@ -75,6 +80,18 @@ class Application extends App implements IBootstrap { }); } + /** + * Registers the CheckPlugin for DAV integration + */ + public function registerDavPlugin(SabrePluginEvent $event): void { + $eventServer = $event->getServer(); + + if ($eventServer !== null) { + $plugin = $this->getContainer()->get(CheckPlugin::class); + $eventServer->addPlugin($plugin); + } + } + /** * @internal */ diff --git a/lib/Dav/CheckPlugin.php b/lib/Dav/CheckPlugin.php new file mode 100644 index 0000000000000000000000000000000000000000..772e0201cbf2c0871669c026f881756be6194f72 --- /dev/null +++ b/lib/Dav/CheckPlugin.php @@ -0,0 +1,92 @@ +server = $server; + + $server->on('method:PROPFIND', [$this, 'blockNextcloudClients']); + $server->on('method:PROPPATCH', [$this, 'blockNextcloudClients']); + $server->on('method:GET', [$this, 'blockNextcloudClients']); + $server->on('method:POST', [$this, 'blockNextcloudClients']); + $server->on('method:PUT', [$this, 'blockNextcloudClients']); + $server->on('method:DELETE', [$this, 'blockNextcloudClients']); + $server->on('method:MKCOL', [$this, 'blockNextcloudClients']); + $server->on('method:MOVE', [$this, 'blockNextcloudClients']); + $server->on('method:COPY', [$this, 'blockNextcloudClients']); + $server->on('method:REPORT', [$this, 'blockNextcloudClients']); + } + + /** + * Block requests from Nextcloud clients based on User-Agent + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @return bool + * @throws Forbidden + */ + public function blockNextcloudClients(RequestInterface $request, ResponseInterface $response): bool { + $userAgent = $request->getHeader('User-Agent'); + + if (!$userAgent) { + throw new Forbidden('Missing User-Agent header.'); + } + + // Check if the User-Agent matches any of the blocked patterns + foreach ($this->blockedUserAgents as $pattern) { + if (preg_match($pattern, $userAgent)) { + throw new Forbidden('Access from Nextcloud clients is blocked.'); + } + } + + return true; // Allow other clients + } + + /** + * Returns a plugin name. + * + * @return string + */ + public function getPluginName(): string { + return Application::APP_ID; + } + + /** + * Returns a bunch of meta-data about the plugin. + * + * @return array + */ + public function getPluginInfo(): array { + return [ + 'name' => $this->getPluginName(), + 'description' => 'Block requests from Nextcloud clients based on User-Agent headers.', + ]; + } +}