From 6854cb3f4d8219cf1829e32122eb2502a916eae9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 1 Feb 2020 09:05:48 +0100 Subject: initial checkin --- includes/class.csp.php | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 includes/class.csp.php (limited to 'includes/class.csp.php') diff --git a/includes/class.csp.php b/includes/class.csp.php new file mode 100644 index 0000000..ecf4541 --- /dev/null +++ b/includes/class.csp.php @@ -0,0 +1,106 @@ +add('default-src', "'none'"); $csp->add('style-src', "'self'"); $csp->emit(); + */ +class ContentSecurityPolicy { + + #private $csp=array(); + public $csp=array(); + + # for debugging just to track which extension/plugins wants to add csp-entries + #public $history=array(); + + function __construct(){ + $this->csp=array(); + } + + /** + * get the constructed concatenated value string part for the http Content-Security-Header + * + * TODO: maybe some syntax checks and logical verification when building the string. + * + * MAYBE: add optional parameter to get only a part like $csp->get('img-src') + * Alternatively the user can just access the currently public $csp->csp['img-src'] to get that values as array. + * + */ + public function get(){ + $out = ''; + foreach ( $this->csp as $key => $values ) { + $out .= $key.' '.implode(' ', $values).'; '; + } + $out = trim($out, '; '); + return $out; + } + + /** + * adds a value to a csp type + * + * @param type + * @param value single values for a type + * + * examples: + * $csp->add('default-src', "'self'"); # surrounding double quotes "" used to pass the single quotes + * $csp->add('img-src', 'mycdn.example.com'); # single quoted string ok + */ + public function add($type, $value){ + if( isset($this->csp[$type]) ) { + if( !in_array( $value, $this->csp[$type] ) ) { + $this->csp[$type][] = $value; + } + } else { + $this->csp[$type] = array($value); + } + #$this->history[]=debug_backtrace()[1]; + } + + /** + * sends the Content-Security-Policy http headers + */ + public function emit() { + $string=$this->get(); + header('Content-Security-Policy: '.$string ); + # some older web browsers used vendor prefixes before csp got w3c recommendation. + # maybe use useragent string to detect who should receive this outdated vendor csp strings. + # for IE 10-11 + header('X-Content-Security-Policy: '.$string ); + # for Chrome 15-24, Safari 5.1-6, .. + header('X-WebKit-CSP: '.$string ); + } + + /** + * Put the csp as meta-tags in the HTML-head section. + * + * Q: What is the benefit of adding csp as meta tags too? + * + * I don't know, maybe this way the csp persist if someone saves a page to his harddrive for instance or if bad web proxies rip off csp http headers? + * Do webbrowsers store the CSP-HTTP header to the HTML-head as metatags automatically if there is no related metatag in the original page? Mhh.. + */ + public function getMeta() { + $string=$this->get(); + $out= ''; + # enable if you think it is necessary for your customers. + # older web browsers used vendor prefixes before csp2 got a w3c recommendation standard.. + # maybe use useragent string to detect who should receive this outdated vendor csp strings. + # for IE 10-11 + $out.= ''; + # for Chrome 15-24, Safari 5.1-6, .. + $out.= ''; + return $out; + } + +} -- cgit v1.2.3-70-g09d2