]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix(caldav): limit vevent size 46421/head
authorSebastianKrupinski <krupinskis05@gmail.com>
Thu, 4 Jul 2024 22:56:27 +0000 (18:56 -0400)
committerSebastianKrupinski <krupinskis05@gmail.com>
Wed, 10 Jul 2024 19:07:06 +0000 (15:07 -0400)
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
apps/dav/appinfo/v1/caldav.php
apps/dav/composer/composer/autoload_classmap.php
apps/dav/composer/composer/autoload_static.php
apps/dav/lib/CalDAV/Validation/CalDavValidatePlugin.php [new file with mode: 0644]
apps/dav/lib/Server.php
apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php [new file with mode: 0644]

index 29f161344dac9532e58ed3490651c64a424b0cc2..55046409b5830990caab306be24bf00a8ffb142e 100644 (file)
@@ -30,6 +30,7 @@ use OC\KnownUser\KnownUserService;
 use OCA\DAV\CalDAV\CalDavBackend;
 use OCA\DAV\CalDAV\CalendarRoot;
 use OCA\DAV\CalDAV\Security\RateLimitingPlugin;
+use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
 use OCA\DAV\Connector\LegacyDAVACL;
 use OCA\DAV\Connector\Sabre\Auth;
 use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
@@ -118,6 +119,7 @@ if ($sendInvitations) {
 }
 $server->addPlugin(new ExceptionLoggerPlugin('caldav', $logger));
 $server->addPlugin(\OCP\Server::get(RateLimitingPlugin::class));
+$server->addPlugin(\OCP\Server::get(CalDavValidatePlugin::class));
 
 // And off we go!
 $server->exec();
index e4695c93f26894b525fda483c451572bdf96c056..6a7b711e5d098dc96d507d92e600cca7de1dc906 100644 (file)
@@ -110,6 +110,7 @@ return array(
     'OCA\\DAV\\CalDAV\\Trashbin\\Plugin' => $baseDir . '/../lib/CalDAV/Trashbin/Plugin.php',
     'OCA\\DAV\\CalDAV\\Trashbin\\RestoreTarget' => $baseDir . '/../lib/CalDAV/Trashbin/RestoreTarget.php',
     'OCA\\DAV\\CalDAV\\Trashbin\\TrashbinHome' => $baseDir . '/../lib/CalDAV/Trashbin/TrashbinHome.php',
+    'OCA\\DAV\\CalDAV\\Validation\\CalDavValidatePlugin' => $baseDir . '/../lib/CalDAV/Validation/CalDavValidatePlugin.php',
     'OCA\\DAV\\CalDAV\\WebcalCaching\\Plugin' => $baseDir . '/../lib/CalDAV/WebcalCaching/Plugin.php',
     'OCA\\DAV\\CalDAV\\WebcalCaching\\RefreshWebcalService' => $baseDir . '/../lib/CalDAV/WebcalCaching/RefreshWebcalService.php',
     'OCA\\DAV\\Capabilities' => $baseDir . '/../lib/Capabilities.php',
index 3fa6cbf585e4df60a8c2720bb258f1106a3c588d..ab24c1de3c9f0394c0fdaf09e6933308e21a980f 100644 (file)
@@ -125,6 +125,7 @@ class ComposerStaticInitDAV
         'OCA\\DAV\\CalDAV\\Trashbin\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/Plugin.php',
         'OCA\\DAV\\CalDAV\\Trashbin\\RestoreTarget' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/RestoreTarget.php',
         'OCA\\DAV\\CalDAV\\Trashbin\\TrashbinHome' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/TrashbinHome.php',
+        'OCA\\DAV\\CalDAV\\Validation\\CalDavValidatePlugin' => __DIR__ . '/..' . '/../lib/CalDAV/Validation/CalDavValidatePlugin.php',
         'OCA\\DAV\\CalDAV\\WebcalCaching\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/WebcalCaching/Plugin.php',
         'OCA\\DAV\\CalDAV\\WebcalCaching\\RefreshWebcalService' => __DIR__ . '/..' . '/../lib/CalDAV/WebcalCaching/RefreshWebcalService.php',
         'OCA\\DAV\\Capabilities' => __DIR__ . '/..' . '/../lib/Capabilities.php',
diff --git a/apps/dav/lib/CalDAV/Validation/CalDavValidatePlugin.php b/apps/dav/lib/CalDAV/Validation/CalDavValidatePlugin.php
new file mode 100644 (file)
index 0000000..a893a48
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\CalDAV\Validation;
+
+use OCA\DAV\AppInfo\Application;
+use OCP\IConfig;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class CalDavValidatePlugin extends ServerPlugin {
+
+       public function __construct(
+               private IConfig $config
+       ) {
+       }
+
+       public function initialize(Server $server): void {
+               $server->on('beforeMethod:PUT', [$this, 'beforePut']);
+       }
+
+       public function beforePut(RequestInterface $request, ResponseInterface $response): bool {
+               // evaluate if card size exceeds defined limit
+               $eventSizeLimit = $this->config->getAppValue(Application::APP_ID, 'event_size_limit', '10485760');
+               if ((int) $request->getRawServerValue('CONTENT_LENGTH') > $eventSizeLimit) {
+                       throw new Forbidden("VEvent or VTodo object exceeds $eventSizeLimit bytes");
+               }
+               // all tests passed return true
+               return true;
+       }
+
+}
index 53adeeecf467225f694abb7a6047bb729717ab25..402e54b92242564c505b0ddc3452b82b6f749224 100644 (file)
@@ -40,6 +40,7 @@ use OCA\DAV\AppInfo\PluginManager;
 use OCA\DAV\BulkUpload\BulkUploadPlugin;
 use OCA\DAV\CalDAV\BirthdayService;
 use OCA\DAV\CalDAV\Security\RateLimitingPlugin;
+use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
 use OCA\DAV\CardDAV\HasPhotoPlugin;
 use OCA\DAV\CardDAV\ImageExportPlugin;
 use OCA\DAV\CardDAV\MultiGetExportPlugin;
@@ -198,6 +199,7 @@ class Server {
                        ));
 
                        $this->server->addPlugin(\OCP\Server::get(RateLimitingPlugin::class));
+                       $this->server->addPlugin(\OCP\Server::get(CalDavValidatePlugin::class));
                }
 
                // addressbook plugins
diff --git a/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php b/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
new file mode 100644 (file)
index 0000000..384ddec
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV\Validation;
+
+use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
+use OCP\IConfig;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Test\TestCase;
+
+class CalDavValidatePluginTest extends TestCase {
+
+       private CalDavValidatePlugin $plugin;
+       private IConfig|MockObject $config;
+       private RequestInterface|MockObject $request;
+       private ResponseInterface|MockObject $response;
+
+       protected function setUp(): void {
+               parent::setUp();
+               // construct mock objects
+               $this->config = $this->createMock(IConfig::class);
+               $this->request = $this->createMock(RequestInterface::class);
+               $this->response = $this->createMock(ResponseInterface::class);
+               $this->plugin = new CalDavValidatePlugin(
+                       $this->config,
+               );
+       }
+
+       public function testPutSizeLessThenLimit(): void {
+               
+               // construct method responses
+               $this->config
+                       ->method('getAppValue')
+                       ->with('dav', 'event_size_limit', '10485760')
+                       ->willReturn(10485760);
+               $this->request
+                       ->method('getRawServerValue')
+                       ->with('CONTENT_LENGTH')
+                       ->willReturn('1024');
+               // test condition
+               $this->assertTrue(
+                       $this->plugin->beforePut($this->request, $this->response)
+               );
+               
+       }
+
+       public function testPutSizeMoreThenLimit(): void {
+               
+               // construct method responses
+               $this->config
+                       ->method('getAppValue')
+                       ->with('dav', 'event_size_limit', '10485760')
+                       ->willReturn(10485760);
+               $this->request
+                       ->method('getRawServerValue')
+                       ->with('CONTENT_LENGTH')
+                       ->willReturn('16242880');
+               $this->expectException(Forbidden::class);
+               // test condition
+               $this->plugin->beforePut($this->request, $this->response);
+               
+       }
+
+}