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