Browse Source

Merge pull request #5462 from nextcloud/add-frameancestor-support

Add CSP frame-ancestors support
tags/v13.0.0beta1
Lukas Reschke 6 years ago
parent
commit
53057f2bd0

+ 14
- 0
lib/private/Security/CSP/ContentSecurityPolicy.php View File

@@ -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;
}

}

+ 3
- 0
lib/public/AppFramework/Http/ContentSecurityPolicy.php View File

@@ -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 = [];
}

+ 31
- 0
lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php View File

@@ -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
@@ -326,6 +328,30 @@ class EmptyContentSecurityPolicy {
return $this;
}

/**
* 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
@@ -405,6 +431,11 @@ class EmptyContentSecurityPolicy {
$policy .= ';';
}

if(!empty($this->allowedFrameAncestors)) {
$policy .= 'frame-ancestors ' . implode(' ', $this->allowedFrameAncestors);
$policy .= ';';
}

return rtrim($policy, ';');
}
}

+ 41
- 0
tests/lib/AppFramework/Http/ContentSecurityPolicyTest.php View File

@@ -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());
}
}

Loading…
Cancel
Save