Passed
Push — master ( ec0d02...c0f595 )
by Jan
06:31 queued 10s
created

InheritanceSecurityPolicy   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 108
rs 10
wmc 28

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A setAllowedProperties() 0 3 1
A setAllowedFilters() 0 3 1
A setAllowedMethods() 0 5 3
B checkMethodAllowed() 0 22 7
A setAllowedFunctions() 0 3 1
A setAllowedTags() 0 3 1
B checkSecurity() 0 17 7
A checkPropertyAllowed() 0 17 6
1
<?php
2
3
/*
4
 * This file is part of Twig.
5
 *
6
 * (c) Fabien Potencier
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace App\Twig\Sandbox;
13
14
use Twig\Markup;
15
use Twig\Sandbox\SecurityNotAllowedFilterError;
16
use Twig\Sandbox\SecurityNotAllowedFunctionError;
17
use Twig\Sandbox\SecurityNotAllowedMethodError;
18
use Twig\Sandbox\SecurityNotAllowedPropertyError;
19
use Twig\Sandbox\SecurityNotAllowedTagError;
20
use Twig\Sandbox\SecurityPolicyInterface;
21
use Twig\Template;
22
23
/**
24
 * Represents a security policy which need to be enforced when sandbox mode is enabled.
25
 *
26
 * Modified by Jan Böhmer, to allow inheritance of methods and properties via class hierachy.
27
 *
28
 * @author Fabien Potencier <[email protected]>
29
 */
30
final class InheritanceSecurityPolicy implements SecurityPolicyInterface
31
{
32
    private $allowedTags;
33
    private $allowedFilters;
34
    private $allowedMethods;
35
    private $allowedProperties;
36
    private $allowedFunctions;
37
38
    public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = [])
39
    {
40
        $this->allowedTags = $allowedTags;
41
        $this->allowedFilters = $allowedFilters;
42
        $this->setAllowedMethods($allowedMethods);
43
        $this->allowedProperties = $allowedProperties;
44
        $this->allowedFunctions = $allowedFunctions;
45
    }
46
47
    public function setAllowedTags(array $tags): void
48
    {
49
        $this->allowedTags = $tags;
50
    }
51
52
    public function setAllowedFilters(array $filters): void
53
    {
54
        $this->allowedFilters = $filters;
55
    }
56
57
    public function setAllowedMethods(array $methods): void
58
    {
59
        $this->allowedMethods = [];
60
        foreach ($methods as $class => $m) {
61
            $this->allowedMethods[$class] = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, \is_array($m) ? $m : [$m]);
62
        }
63
    }
64
65
    public function setAllowedProperties(array $properties): void
66
    {
67
        $this->allowedProperties = $properties;
68
    }
69
70
    public function setAllowedFunctions(array $functions): void
71
    {
72
        $this->allowedFunctions = $functions;
73
    }
74
75
    public function checkSecurity($tags, $filters, $functions): void
76
    {
77
        foreach ($tags as $tag) {
78
            if (!\in_array($tag, $this->allowedTags)) {
79
                throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag);
80
            }
81
        }
82
83
        foreach ($filters as $filter) {
84
            if (!\in_array($filter, $this->allowedFilters)) {
85
                throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter);
86
            }
87
        }
88
89
        foreach ($functions as $function) {
90
            if (!\in_array($function, $this->allowedFunctions)) {
91
                throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function);
92
            }
93
        }
94
    }
95
96
    public function checkMethodAllowed($obj, $method): void
97
    {
98
        if ($obj instanceof Template || $obj instanceof Markup) {
99
            return;
100
        }
101
102
        $allowed = false;
103
        $method = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
104
        foreach ($this->allowedMethods as $class => $methods) {
105
            if ($obj instanceof $class) {
106
                $allowed = \in_array($method, $methods);
107
108
                //CHANGED: Only break if we the method is allowed, otherwise try it on the other methods
109
                if ($allowed) {
110
                    break;
111
                }
112
            }
113
        }
114
115
        if (!$allowed) {
0 ignored issues
show
introduced by
The condition $allowed is always false.
Loading history...
116
            $class = \get_class($obj);
117
            throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method);
118
        }
119
    }
120
121
    public function checkPropertyAllowed($obj, $property): void
122
    {
123
        $allowed = false;
124
        foreach ($this->allowedProperties as $class => $properties) {
125
            if ($obj instanceof $class) {
126
                $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]);
127
128
                //CHANGED: Only break if we the method is allowed, otherwise try it on the other methods
129
                if ($allowed) {
130
                    break;
131
                }
132
            }
133
        }
134
135
        if (!$allowed) {
0 ignored issues
show
introduced by
The condition $allowed is always false.
Loading history...
136
            $class = \get_class($obj);
137
            throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property);
138
        }
139
    }
140
}
141