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 12namespace Twig\Sandbox; 13 14use Twig\Markup; 15use Twig\Template; 16 17/** 18 * Represents a security policy which need to be enforced when sandbox mode is enabled. 19 * 20 * @author Fabien Potencier <fabien@symfony.com> 21 */ 22final class SecurityPolicy implements SecurityPolicyInterface 23{ 24 private $allowedTags; 25 private $allowedFilters; 26 private $allowedMethods; 27 private $allowedProperties; 28 private $allowedFunctions; 29 30 public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = []) 31 { 32 $this->allowedTags = $allowedTags; 33 $this->allowedFilters = $allowedFilters; 34 $this->setAllowedMethods($allowedMethods); 35 $this->allowedProperties = $allowedProperties; 36 $this->allowedFunctions = $allowedFunctions; 37 } 38 39 public function setAllowedTags(array $tags) 40 { 41 $this->allowedTags = $tags; 42 } 43 44 public function setAllowedFilters(array $filters) 45 { 46 $this->allowedFilters = $filters; 47 } 48 49 public function setAllowedMethods(array $methods) 50 { 51 $this->allowedMethods = []; 52 foreach ($methods as $class => $m) { 53 $this->allowedMethods[$class] = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, \is_array($m) ? $m : [$m]); 54 } 55 } 56 57 public function setAllowedProperties(array $properties) 58 { 59 $this->allowedProperties = $properties; 60 } 61 62 public function setAllowedFunctions(array $functions) 63 { 64 $this->allowedFunctions = $functions; 65 } 66 67 public function checkSecurity($tags, $filters, $functions) 68 { 69 foreach ($tags as $tag) { 70 if (!\in_array($tag, $this->allowedTags)) { 71 throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); 72 } 73 } 74 75 foreach ($filters as $filter) { 76 if (!\in_array($filter, $this->allowedFilters)) { 77 throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); 78 } 79 } 80 81 foreach ($functions as $function) { 82 if (!\in_array($function, $this->allowedFunctions)) { 83 throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); 84 } 85 } 86 } 87 88 public function checkMethodAllowed($obj, $method) 89 { 90 if ($obj instanceof Template || $obj instanceof Markup) { 91 return; 92 } 93 94 $allowed = false; 95 $method = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); 96 foreach ($this->allowedMethods as $class => $methods) { 97 if ($obj instanceof $class) { 98 $allowed = \in_array($method, $methods); 99 100 break; 101 } 102 } 103 104 if (!$allowed) { 105 $class = \get_class($obj); 106 throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); 107 } 108 } 109 110 public function checkPropertyAllowed($obj, $property) 111 { 112 $allowed = false; 113 foreach ($this->allowedProperties as $class => $properties) { 114 if ($obj instanceof $class) { 115 $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]); 116 117 break; 118 } 119 } 120 121 if (!$allowed) { 122 $class = \get_class($obj); 123 throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); 124 } 125 } 126} 127 128class_alias('Twig\Sandbox\SecurityPolicy', 'Twig_Sandbox_SecurityPolicy'); 129