This adds the events and the classes to modify the feature policy. It also adds a default restricted feature policy. Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>pull/16613/head
parent
5d94590cee
commit
b8c5008acf
@ -0,0 +1,70 @@ |
||||
<?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 OC\AppFramework\Middleware\Security; |
||||
|
||||
use OC\Security\CSP\ContentSecurityPolicyManager; |
||||
use OC\Security\CSP\ContentSecurityPolicyNonceManager; |
||||
use OC\Security\CSRF\CsrfTokenManager; |
||||
use OC\Security\FeaturePolicy\FeaturePolicy; |
||||
use OC\Security\FeaturePolicy\FeaturePolicyManager; |
||||
use OCP\AppFramework\Controller; |
||||
use OCP\AppFramework\Http\ContentSecurityPolicy; |
||||
use OCP\AppFramework\Http\EmptyContentSecurityPolicy; |
||||
use OCP\AppFramework\Http\EmptyFeaturePolicy; |
||||
use OCP\AppFramework\Http\Response; |
||||
use OCP\AppFramework\Middleware; |
||||
|
||||
class FeaturePolicyMiddleware extends Middleware { |
||||
|
||||
/** @var FeaturePolicyManager */ |
||||
private $policyManager; |
||||
|
||||
public function __construct(FeaturePolicyManager $policyManager) { |
||||
$this->policyManager = $policyManager; |
||||
} |
||||
|
||||
/** |
||||
* Performs the default FeaturePolicy modifications that may be injected by other |
||||
* applications |
||||
* |
||||
* @param Controller $controller |
||||
* @param string $methodName |
||||
* @param Response $response |
||||
* @return Response |
||||
*/ |
||||
public function afterController($controller, $methodName, Response $response): Response { |
||||
$policy = !is_null($response->getFeaturePolicy()) ? $response->getFeaturePolicy() : new FeaturePolicy(); |
||||
|
||||
if (get_class($policy) === EmptyFeaturePolicy::class) { |
||||
return $response; |
||||
} |
||||
|
||||
$defaultPolicy = $this->policyManager->getDefaultPolicy(); |
||||
$defaultPolicy = $this->policyManager->mergePolicies($defaultPolicy, $policy); |
||||
$response->setFeaturePolicy($defaultPolicy); |
||||
|
||||
return $response; |
||||
} |
||||
} |
@ -0,0 +1,76 @@ |
||||
<?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 OC\Security\FeaturePolicy; |
||||
|
||||
class FeaturePolicy extends \OCP\AppFramework\Http\FeaturePolicy { |
||||
|
||||
public function getAutoplayDomains(): array { |
||||
return $this->autoplayDomains; |
||||
} |
||||
|
||||
public function setAutoplayDomains(array $autoplayDomains): void { |
||||
$this->autoplayDomains = $autoplayDomains; |
||||
} |
||||
|
||||
public function getCameraDomains(): array { |
||||
return $this->cameraDomains; |
||||
} |
||||
|
||||
public function setCameraDomains(array $cameraDomains): void { |
||||
$this->cameraDomains = $cameraDomains; |
||||
} |
||||
|
||||
public function getFullscreenDomains(): array { |
||||
return $this->fullscreenDomains; |
||||
} |
||||
|
||||
public function setFullscreenDomains(array $fullscreenDomains): void { |
||||
$this->fullscreenDomains = $fullscreenDomains; |
||||
} |
||||
|
||||
public function getGeolocationDomains(): array { |
||||
return $this->geolocationDomains; |
||||
} |
||||
|
||||
public function setGeolocationDomains(array $geolocationDomains): void { |
||||
$this->geolocationDomains = $geolocationDomains; |
||||
} |
||||
|
||||
public function getMicrophoneDomains(): array { |
||||
return $this->microphoneDomains; |
||||
} |
||||
|
||||
public function setMicrophoneDomains(array $microphoneDomains): void { |
||||
$this->microphoneDomains = $microphoneDomains; |
||||
} |
||||
|
||||
public function getPaymentDomains(): array { |
||||
return $this->paymentDomains; |
||||
} |
||||
|
||||
public function setPaymentDomains(array $paymentDomains): void { |
||||
$this->paymentDomains = $paymentDomains; |
||||
} |
||||
} |
@ -0,0 +1,76 @@ |
||||
<?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 OC\Security\FeaturePolicy; |
||||
|
||||
use OCP\AppFramework\Http\EmptyFeaturePolicy; |
||||
use OCP\EventDispatcher\IEventDispatcher; |
||||
use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent; |
||||
|
||||
class FeaturePolicyManager { |
||||
/** @var EmptyFeaturePolicy[] */ |
||||
private $policies = []; |
||||
|
||||
/** @var IEventDispatcher */ |
||||
private $dispatcher; |
||||
|
||||
public function __construct(IEventDispatcher $dispatcher) { |
||||
$this->dispatcher = $dispatcher; |
||||
} |
||||
|
||||
public function addDefaultPolicy(EmptyFeaturePolicy $policy): void { |
||||
$this->policies[] = $policy; |
||||
} |
||||
|
||||
public function getDefaultPolicy(): FeaturePolicy { |
||||
$event = new AddFeaturePolicyEvent($this); |
||||
$this->dispatcher->dispatch(AddFeaturePolicyEvent::class, $event); |
||||
|
||||
$defaultPolicy = new FeaturePolicy(); |
||||
foreach ($this->policies as $policy) { |
||||
$defaultPolicy = $this->mergePolicies($defaultPolicy, $policy); |
||||
} |
||||
return $defaultPolicy; |
||||
} |
||||
|
||||
/** |
||||
* Merges the first given policy with the second one |
||||
* |
||||
*/ |
||||
public function mergePolicies(FeaturePolicy $defaultPolicy, |
||||
EmptyFeaturePolicy $originalPolicy): FeaturePolicy { |
||||
foreach ((object)(array)$originalPolicy as $name => $value) { |
||||
$setter = 'set' . ucfirst($name); |
||||
if (\is_array($value)) { |
||||
$getter = 'get' . ucfirst($name); |
||||
$currentValues = \is_array($defaultPolicy->$getter()) ? $defaultPolicy->$getter() : []; |
||||
$defaultPolicy->$setter(\array_values(\array_unique(\array_merge($currentValues, $value)))); |
||||
} elseif (\is_bool($value)) { |
||||
$defaultPolicy->$setter($value); |
||||
} |
||||
} |
||||
|
||||
return $defaultPolicy; |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
<?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 OCP\AppFramework\Http; |
||||
|
||||
/** |
||||
* Class FeaturePolicy is a simple helper which allows applications to |
||||
* modify the Feature-Policy sent by Nextcloud. Per default only autoplay is allowed |
||||
* from the same domain and full screen as well from the same domain. |
||||
* |
||||
* Even if a value gets modified above defaults will still get appended. Please |
||||
* notice that Nextcloud ships already with sensible defaults and those policies |
||||
* should require no modification at all for most use-cases. |
||||
* |
||||
* @package OCP\AppFramework\Http |
||||
* @since 17.0.0 |
||||
*/ |
||||
class FeaturePolicy extends EmptyFeaturePolicy { |
||||
protected $autoplayDomains = [ |
||||
'\'self\'', |
||||
]; |
||||
|
||||
/** @var string[] of allowed domains that can access the camera */ |
||||
protected $cameraDomains = []; |
||||
|
||||
protected $fullscreenDomains = [ |
||||
'\'self\'', |
||||
]; |
||||
|
||||
/** @var string[] of allowed domains that can use the geolocation of the device */ |
||||
protected $geolocationDomains = []; |
||||
|
||||
/** @var string[] of allowed domains that can use the microphone */ |
||||
protected $microphoneDomains = []; |
||||
|
||||
/** @var string[] of allowed domains that can use the payment API */ |
||||
protected $paymentDomains = []; |
||||
} |
@ -0,0 +1,52 @@ |
||||
<?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 OCP\Security\FeaturePolicy; |
||||
|
||||
use OC\Security\FeaturePolicy\FeaturePolicyManager; |
||||
use OCP\AppFramework\Http\EmptyFeaturePolicy; |
||||
use OCP\EventDispatcher\Event; |
||||
|
||||
/** |
||||
* @since 17.0.0 |
||||
*/ |
||||
class AddFeaturePolicyEvent extends Event { |
||||
|
||||
/** @var FeaturePolicyManager */ |
||||
private $policyManager; |
||||
|
||||
/** |
||||
* @since 17.0.0 |
||||
*/ |
||||
public function __construct(FeaturePolicyManager $policyManager) { |
||||
$this->policyManager = $policyManager; |
||||
} |
||||
|
||||
/** |
||||
* @since 17.0.0 |
||||
*/ |
||||
public function addPolicy(EmptyFeaturePolicy $policy) { |
||||
$this->policyManager->addDefaultPolicy($policy); |
||||
} |
||||
} |
Loading…
Reference in new issue