summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2017-09-18 14:25:44 +0200
committerGitHub <noreply@github.com>2017-09-18 14:25:44 +0200
commit53057f2bd0fd1e7239ebd5cb6f82eb2766f642ee (patch)
tree11726c07a58e3ead653e6551b2448ad689a39c95
parent8b1eaba417553410871ebec64f78a96cefaa6f6d (diff)
parenteb51c46549d1fe01fe8fdbefd2303bf597c88b54 (diff)
downloadnextcloud-server-53057f2bd0fd1e7239ebd5cb6f82eb2766f642ee.tar.gz
nextcloud-server-53057f2bd0fd1e7239ebd5cb6f82eb2766f642ee.zip
Merge pull request #5462 from nextcloud/add-frameancestor-support
Add CSP frame-ancestors support
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicy.php14
-rw-r--r--lib/public/AppFramework/Http/ContentSecurityPolicy.php3
-rw-r--r--lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php31
-rw-r--r--tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php41
4 files changed, 89 insertions, 0 deletions
diff --git a/lib/private/Security/CSP/ContentSecurityPolicy.php b/lib/private/Security/CSP/ContentSecurityPolicy.php
index 47314609498..a6892505520 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicy.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicy.php
@@ -197,4 +197,18 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
$this->allowedChildSrcDomains = $allowedChildSrcDomains;
}
+ /**
+ * @return array
+ */
+ public function getAllowedFrameAncestors() {
+ return $this->allowedFrameAncestors;
+ }
+
+ /**
+ * @param array $allowedFrameAncestors
+ */
+ public function setAllowedFrameAncestors($allowedFrameAncestors) {
+ $this->allowedFrameAncestors = $allowedFrameAncestors;
+ }
+
}
diff --git a/lib/public/AppFramework/Http/ContentSecurityPolicy.php b/lib/public/AppFramework/Http/ContentSecurityPolicy.php
index 17844497f94..b17dc070fe1 100644
--- a/lib/public/AppFramework/Http/ContentSecurityPolicy.php
+++ b/lib/public/AppFramework/Http/ContentSecurityPolicy.php
@@ -84,4 +84,7 @@ class ContentSecurityPolicy extends EmptyContentSecurityPolicy {
];
/** @var array Domains from which web-workers and nested browsing content can load elements */
protected $allowedChildSrcDomains = [];
+
+ /** @var array Domains which can embed this Nextcloud instance */
+ protected $allowedFrameAncestors = [];
}
diff --git a/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php b/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php
index 64d4eb6e5d0..5902d4ddbeb 100644
--- a/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php
+++ b/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php
@@ -68,6 +68,8 @@ class EmptyContentSecurityPolicy {
protected $allowedFontDomains = null;
/** @var array Domains from which web-workers and nested browsing content can load elements */
protected $allowedChildSrcDomains = null;
+ /** @var array Domains which can embed this Nextcloud instance */
+ protected $allowedFrameAncestors = null;
/**
* Whether inline JavaScript snippets are allowed or forbidden
@@ -327,6 +329,30 @@ class EmptyContentSecurityPolicy {
}
/**
+ * Domains which can embed an iFrame of the Nextcloud instance
+ *
+ * @param string $domain
+ * @return $this
+ * @since 13.0.0
+ */
+ public function addAllowedFrameAncestorDomain($domain) {
+ $this->allowedFrameAncestors[] = $domain;
+ return $this;
+ }
+
+ /**
+ * Domains which can embed an iFrame of the Nextcloud instance
+ *
+ * @param string $domain
+ * @return $this
+ * @since 13.0.0
+ */
+ public function disallowFrameAncestorDomain($domain) {
+ $this->allowedFrameAncestors = array_diff($this->allowedFrameAncestors, [$domain]);
+ return $this;
+ }
+
+ /**
* Get the generated Content-Security-Policy as a string
* @return string
* @since 8.1.0
@@ -405,6 +431,11 @@ class EmptyContentSecurityPolicy {
$policy .= ';';
}
+ if(!empty($this->allowedFrameAncestors)) {
+ $policy .= 'frame-ancestors ' . implode(' ', $this->allowedFrameAncestors);
+ $policy .= ';';
+ }
+
return rtrim($policy, ';');
}
}
diff --git a/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php
index 503148d633a..90dcf99d008 100644
--- a/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php
+++ b/tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php
@@ -426,4 +426,45 @@ class ContentSecurityPolicyTest extends \Test\TestCase {
$this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com');
$this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
}
+
+
+
+ public function testGetAllowedFrameAncestorDomain() {
+ $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-ancestors sub.nextcloud.com";
+
+ $this->contentSecurityPolicy->addAllowedFrameAncestorDomain('sub.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
+ }
+
+ public function testGetPolicyFrameAncestorValidMultiple() {
+ $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-ancestors sub.nextcloud.com foo.nextcloud.com";
+
+ $this->contentSecurityPolicy->addAllowedFrameAncestorDomain('sub.nextcloud.com');
+ $this->contentSecurityPolicy->addAllowedFrameAncestorDomain('foo.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
+ }
+
+ public function testGetPolicyDisallowFrameAncestorDomain() {
+ $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'";
+
+ $this->contentSecurityPolicy->addAllowedFrameAncestorDomain('www.nextcloud.com');
+ $this->contentSecurityPolicy->disallowFrameAncestorDomain('www.nextcloud.com');
+ $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
+ }
+
+ public function testGetPolicyDisallowFrameAncestorDomainMultiple() {
+ $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self';frame-ancestors www.nextcloud.com";
+
+ $this->contentSecurityPolicy->addAllowedFrameAncestorDomain('www.nextcloud.com');
+ $this->contentSecurityPolicy->disallowFrameAncestorDomain('www.nextcloud.org');
+ $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
+ }
+
+ public function testGetPolicyDisallowFrameAncestorDomainMultipleStakes() {
+ $expectedPolicy = "default-src 'none';base-uri 'none';manifest-src 'self';script-src 'self' 'unsafe-eval';style-src 'self' 'unsafe-inline';img-src 'self' data: blob:;font-src 'self';connect-src 'self';media-src 'self'";
+
+ $this->contentSecurityPolicy->addAllowedChildSrcDomain('www.owncloud.com');
+ $this->contentSecurityPolicy->disallowChildSrcDomain('www.owncloud.org')->disallowChildSrcDomain('www.owncloud.com');
+ $this->assertSame($expectedPolicy, $this->contentSecurityPolicy->buildPolicy());
+ }
}