--- /dev/null
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\AppFramework\Http;
+
+use OCP\AppFramework\Http\EmptyFeaturePolicy;
+
+class EmptyFeaturePolicyTest extends \Test\TestCase {
+
+ /** @var EmptyFeaturePolicy */
+ private $policy;
+
+ public function setUp() {
+ parent::setUp();
+ $this->policy = new EmptyFeaturePolicy();
+ }
+
+ public function testGetPolicyDefault() {
+ $defaultPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'";
+ $this->assertSame($defaultPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyAutoplayDomainValid() {
+ $expectedPolicy = "autoplay www.nextcloud.com;camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyAutoplayDomainValidMultiple() {
+ $expectedPolicy = "autoplay www.nextcloud.com www.nextcloud.org;camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.com');
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyCameraDomainValid() {
+ $expectedPolicy = "autoplay 'none';camera www.nextcloud.com;fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedCameraDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyCameraDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'none';camera www.nextcloud.com www.nextcloud.org;fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedCameraDomain('www.nextcloud.com');
+ $this->policy->addAllowedCameraDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyFullScreenDomainValid() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen www.nextcloud.com;geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyFullScreenDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen www.nextcloud.com www.nextcloud.org;geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.com');
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyGeoLocationDomainValid() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation www.nextcloud.com;microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyGeoLocationDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation www.nextcloud.com www.nextcloud.org;microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.com');
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyMicrophoneDomainValid() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone www.nextcloud.com;payment 'none'";
+
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyMicrophoneDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone www.nextcloud.com www.nextcloud.org;payment 'none'";
+
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.com');
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyPaymentDomainValid() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment www.nextcloud.com";
+
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyPaymentDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment www.nextcloud.com www.nextcloud.org";
+
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.com');
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+}
--- /dev/null
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\AppFramework\Http;
+
+use OCP\AppFramework\Http\FeaturePolicy;
+
+class FeaturePolicyTest extends \Test\TestCase {
+
+ /** @var EmptyFeaturePolicy */
+ private $policy;
+
+ public function setUp() {
+ parent::setUp();
+ $this->policy = new FeaturePolicy();
+ }
+
+ public function testGetPolicyDefault() {
+ $defaultPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation 'none';microphone 'none';payment 'none'";
+ $this->assertSame($defaultPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyAutoplayDomainValid() {
+ $expectedPolicy = "autoplay 'self' www.nextcloud.com;camera 'none';fullscreen 'self';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyAutoplayDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self' www.nextcloud.com www.nextcloud.org;camera 'none';fullscreen 'self';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.com');
+ $this->policy->addAllowedAutoplayDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyCameraDomainValid() {
+ $expectedPolicy = "autoplay 'self';camera www.nextcloud.com;fullscreen 'self';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedCameraDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyCameraDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self';camera www.nextcloud.com www.nextcloud.org;fullscreen 'self';geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedCameraDomain('www.nextcloud.com');
+ $this->policy->addAllowedCameraDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyFullScreenDomainValid() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self' www.nextcloud.com;geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyFullScreenDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self' www.nextcloud.com www.nextcloud.org;geolocation 'none';microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.com');
+ $this->policy->addAllowedFullScreenDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyGeoLocationDomainValid() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation www.nextcloud.com;microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyGeoLocationDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation www.nextcloud.com www.nextcloud.org;microphone 'none';payment 'none'";
+
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.com');
+ $this->policy->addAllowedGeoLocationDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyMicrophoneDomainValid() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation 'none';microphone www.nextcloud.com;payment 'none'";
+
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyMicrophoneDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation 'none';microphone www.nextcloud.com www.nextcloud.org;payment 'none'";
+
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.com');
+ $this->policy->addAllowedMicrophoneDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyPaymentDomainValid() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation 'none';microphone 'none';payment www.nextcloud.com";
+
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+
+ public function testGetPolicyPaymentDomainValidMultiple() {
+ $expectedPolicy = "autoplay 'self';camera 'none';fullscreen 'self';geolocation 'none';microphone 'none';payment www.nextcloud.com www.nextcloud.org";
+
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.com');
+ $this->policy->addAllowedPaymentDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->policy->buildPolicy());
+ }
+}
--- /dev/null
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\AppFramework\Middleware\Security;
+
+use OC\AppFramework\Middleware\Security\FeaturePolicyMiddleware;
+use OC\Security\CSP\ContentSecurityPolicy;
+use OC\Security\CSRF\CsrfToken;
+use OC\Security\FeaturePolicy\FeaturePolicy;
+use OC\Security\FeaturePolicy\FeaturePolicyManager;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
+use OCP\AppFramework\Http\EmptyFeaturePolicy;
+use OCP\AppFramework\Http\Response;
+use PHPUnit\Framework\MockObject\MockObject;
+
+class FeaturePolicyMiddlewareTest extends \Test\TestCase {
+
+ /** @var FeaturePolicyMiddleware|MockObject */
+ private $middleware;
+ /** @var Controller|MockObject */
+ private $controller;
+ /** @var FeaturePolicyManager|MockObject */
+ private $manager;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->controller = $this->createMock(Controller::class);
+ $this->manager = $this->createMock(FeaturePolicyManager::class);
+ $this->middleware = new FeaturePolicyMiddleware(
+ $this->manager
+ );
+ }
+
+ public function testAfterController() {
+ $response = $this->createMock(Response::class);
+ $defaultPolicy = new FeaturePolicy();
+ $defaultPolicy->addAllowedCameraDomain('defaultpolicy');
+ $currentPolicy = new FeaturePolicy();
+ $currentPolicy->addAllowedAutoplayDomain('currentPolicy');
+ $mergedPolicy = new FeaturePolicy();
+ $mergedPolicy->addAllowedGeoLocationDomain('mergedPolicy');
+ $response->method('getFeaturePolicy')
+ ->willReturn($currentPolicy);
+ $this->manager->method('getDefaultPolicy')
+ ->willReturn($defaultPolicy);
+ $this->manager->method('mergePolicies')
+ ->with($defaultPolicy, $currentPolicy)
+ ->willReturn($mergedPolicy);
+ $response->expects($this->once())
+ ->method('setFeaturePolicy')
+ ->with($mergedPolicy);
+
+ $this->middleware->afterController($this->controller, 'test', $response);
+ }
+
+ public function testAfterControllerEmptyCSP() {
+ $response = $this->createMock(Response::class);
+ $emptyPolicy = new EmptyFeaturePolicy();
+ $response->method('getFeaturePolicy')
+ ->willReturn($emptyPolicy);
+ $response->expects($this->never())
+ ->method('setFeaturePolicy');
+
+ $this->middleware->afterController($this->controller, 'test', $response);
+ }
+}
--- /dev/null
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Security\CSP;
+
+use OC\Security\FeaturePolicy\FeaturePolicyManager;
+use OCP\AppFramework\Http\FeaturePolicy;
+use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent;
+use Test\TestCase;
+
+class AddFeaturePolicyEventTest extends TestCase {
+ public function testAddEvent() {
+ $manager = $this->createMock(FeaturePolicyManager::class);
+ $policy = $this->createMock(FeaturePolicy::class);
+ $event = new AddFeaturePolicyEvent($manager);
+
+ $manager->expects($this->once())
+ ->method('addDefaultPolicy')
+ ->with($policy);
+
+ $event->addPolicy($policy);
+ }
+}
--- /dev/null
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Security\CSP;
+
+use OC\Security\CSP\ContentSecurityPolicyManager;
+use OC\Security\FeaturePolicy\FeaturePolicyManager;
+use OCP\AppFramework\Http\FeaturePolicy;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Security\CSP\AddContentSecurityPolicyEvent;
+use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent;
+use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Test\TestCase;
+
+class FeaturePolicyManagerTest extends TestCase {
+ /** @var EventDispatcherInterface */
+ private $dispatcher;
+
+ /** @var FeaturePolicyManager */
+ private $manager;
+
+ public function setUp() {
+ parent::setUp();
+ $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
+ $this->manager = new FeaturePolicyManager($this->dispatcher);
+ }
+
+ public function testAddDefaultPolicy() {
+ $this->manager->addDefaultPolicy(new FeaturePolicy());
+ $this->addToAssertionCount(1);
+ }
+
+ public function testGetDefaultPolicyWithPoliciesViaEvent() {
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function(AddFeaturePolicyEvent $e) {
+ $policy = new FeaturePolicy();
+ $policy->addAllowedMicrophoneDomain('mydomain.com');
+ $policy->addAllowedPaymentDomain('mypaymentdomain.com');
+
+ $e->addPolicy($policy);
+ });
+
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function(AddFeaturePolicyEvent $e) {
+ $policy = new FeaturePolicy();
+ $policy->addAllowedPaymentDomain('mydomainother.com');
+ $policy->addAllowedGeoLocationDomain('mylocation.here');
+
+ $e->addPolicy($policy);
+ });
+
+ $this->dispatcher->addListener(AddFeaturePolicyEvent::class, function(AddFeaturePolicyEvent $e) {
+ $policy = new FeaturePolicy();
+ $policy->addAllowedAutoplayDomain('youtube.com');
+
+ $e->addPolicy($policy);
+ });
+
+ $expected = new \OC\Security\FeaturePolicy\FeaturePolicy();
+ $expected->addAllowedMicrophoneDomain('mydomain.com');
+ $expected->addAllowedPaymentDomain('mypaymentdomain.com');
+ $expected->addAllowedPaymentDomain('mydomainother.com');
+ $expected->addAllowedGeoLocationDomain('mylocation.here');
+ $expected->addAllowedAutoplayDomain('youtube.com');
+
+ $expectedStringPolicy = "autoplay 'self' youtube.com;camera 'none';fullscreen 'self';geolocation mylocation.here;microphone mydomain.com;payment mypaymentdomain.com mydomainother.com";
+
+ $this->assertEquals($expected, $this->manager->getDefaultPolicy());
+ $this->assertSame($expectedStringPolicy, $this->manager->getDefaultPolicy()->buildPolicy());
+ }
+
+}