Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ActionProtector
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 setHeaders
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 setDefaultHeaders
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 setFrameAncestorsHeader
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 setStrictTransportHeader
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2015 – 2020 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22declare(strict_types=1);
23
24namespace oat\tao\model\security;
25
26use oat\tao\model\security\Business\Contract\SecuritySettingsRepositoryInterface;
27use oat\tao\model\security\Business\Domain\SettingsCollection;
28use oat\tao\model\service\InjectionAwareService;
29
30/**
31 * Service that can be used to protect actions.
32 *
33 * @author Martijn Swinkels <martijn@taotesting.com>
34 */
35class ActionProtector extends InjectionAwareService
36{
37    public const SERVICE_ID = 'tao/actionProtection';
38
39    /** @var SecuritySettingsRepositoryInterface */
40    private $repository;
41
42    /** @var string */
43    private $defaultHeaders;
44
45    /** @noinspection MagicMethodsValidityInspection */
46    /** @noinspection PhpMissingParentConstructorInspection */
47    public function __construct(SecuritySettingsRepositoryInterface $repository, array $defaultHeaders = [])
48    {
49        $this->repository     = $repository;
50        $this->defaultHeaders = $defaultHeaders;
51    }
52
53    public function setHeaders(): void
54    {
55        $settings = $this->repository->findAll();
56
57        $this->setDefaultHeaders();
58        $this->setFrameAncestorsHeader($settings);
59        $this->setStrictTransportHeader($settings);
60    }
61
62    public function setDefaultHeaders(): void
63    {
64        foreach ($this->defaultHeaders as $defaultHeader) {
65            header($defaultHeader);
66        }
67    }
68
69    /**
70     * Set the header that defines which sources are allowed to embed the pages.
71     *
72     * @param SettingsCollection $settings
73     */
74    public function setFrameAncestorsHeader(SettingsCollection $settings): void
75    {
76        $whitelistedSources = $settings->findContentSecurityPolicy()->getValue();
77
78        if (!$whitelistedSources) {
79            $whitelistedSources = ["'none'"];
80        }
81
82        // Wrap directives in quotes
83        if (in_array($whitelistedSources, ['self', 'none'], true)) {
84            $whitelistedSources = ["'" . $whitelistedSources . "'"];
85        }
86
87        if ($whitelistedSources === 'list') {
88            $whitelistedSources = explode("\n", $settings->findContentSecurityPolicyWhitelist()->getValue());
89        }
90
91        header(
92            sprintf(
93                'Content-Security-Policy: frame-ancestors %s',
94                implode(' ', (array)$whitelistedSources)
95            )
96        );
97    }
98
99    private function setStrictTransportHeader(SettingsCollection $settings): void
100    {
101        header(
102            sprintf(
103                'Strict-Transport-Security: max-age=%u; includeSubDomains;',
104                $settings->findTransportSecurity()->getValue() ? 31536000 : 0
105            )
106        );
107    }
108}