121913ab3SNickeau<?php 221913ab3SNickeau 3531e725cSNickeauuse ComboStrap\Site; 421913ab3SNickeauuse ComboStrap\StringUtility; 521913ab3SNickeau 621913ab3SNickeauif (!defined('DOKU_INC')) die(); 721913ab3SNickeau 821913ab3SNickeau/** 921913ab3SNickeau * 1021913ab3SNickeau * Adding security directive 1121913ab3SNickeau * 1221913ab3SNickeau */ 1321913ab3SNickeauclass action_plugin_combo_metacsp extends DokuWiki_Action_Plugin 1421913ab3SNickeau{ 1521913ab3SNickeau 1621913ab3SNickeau 1721913ab3SNickeau function __construct() 1821913ab3SNickeau { 1921913ab3SNickeau // enable direct access to language strings 2021913ab3SNickeau // ie $this->lang 2121913ab3SNickeau $this->setupLocale(); 2221913ab3SNickeau } 2321913ab3SNickeau 2421913ab3SNickeau public function register(Doku_Event_Handler $controller) 2521913ab3SNickeau { 2621913ab3SNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaCsp', array()); 2721913ab3SNickeau } 2821913ab3SNickeau 2921913ab3SNickeau /** 3021913ab3SNickeau * Dokuwiki has already a canonical methodology 3121913ab3SNickeau * https://www.dokuwiki.org/canonical 3221913ab3SNickeau * 3321913ab3SNickeau * @param $event 3421913ab3SNickeau */ 3521913ab3SNickeau function metaCsp($event) 3621913ab3SNickeau { 3721913ab3SNickeau 38531e725cSNickeau 39531e725cSNickeau /** 40531e725cSNickeau * HTML meta directives 41531e725cSNickeau */ 4221913ab3SNickeau $directives = [ 4321913ab3SNickeau 'block-all-mixed-content', // no http, https 4421913ab3SNickeau ]; 4521913ab3SNickeau 4621913ab3SNickeau // Search if the CSP property is already present 4721913ab3SNickeau $cspKey = null; 4821913ab3SNickeau foreach ($event->data['meta'] as $key => $meta) { 4921913ab3SNickeau if (isset($meta["http-equiv"])) { 50*85e82846SNickeau if ($meta["http-equiv"] == "content-security-policy") { 5121913ab3SNickeau $cspKey = $key; 5221913ab3SNickeau } 5321913ab3SNickeau } 5421913ab3SNickeau } 5521913ab3SNickeau if ($cspKey != null) { 5621913ab3SNickeau $actualDirectives = StringUtility::explodeAndTrim($event->data['meta'][$cspKey]["content"], ","); 5721913ab3SNickeau $directives = array_merge($actualDirectives, $directives); 5821913ab3SNickeau $event->data['meta'][$cspKey] = [ 59*85e82846SNickeau "http-equiv" => "content-security-policy", 6021913ab3SNickeau "content" => join(", ", $directives) 6121913ab3SNickeau ]; 6221913ab3SNickeau } else { 6321913ab3SNickeau $event->data['meta'][] = [ 64*85e82846SNickeau "http-equiv" => "content-security-policy", 6521913ab3SNickeau "content" => join(",", $directives) 6621913ab3SNickeau ]; 6721913ab3SNickeau } 6821913ab3SNickeau 69531e725cSNickeau /** 70531e725cSNickeau * Http header CSP directives 71531e725cSNickeau */ 72531e725cSNickeau $httpHeaderReferer = $_SERVER['HTTP_REFERER']; 73531e725cSNickeau $httpDirectives = []; 74531e725cSNickeau if (strpos($httpHeaderReferer, Site::getUrl()) === false) { 75531e725cSNickeau // not same origin 7621913ab3SNickeau $httpDirectives = [ 77*85e82846SNickeau "content-security-policy: frame-ancestors 'none'", // the page cannot be used in a iframe (clickjacking), 7821913ab3SNickeau "X-Frame-Options: deny" // the page cannot be used in a iframe (clickjacking) - deprecated for frame ancestores 7921913ab3SNickeau ]; 80531e725cSNickeau } 8121913ab3SNickeau foreach ($httpDirectives as $httpDirective) { 8221913ab3SNickeau header($httpDirective); 8321913ab3SNickeau } 8421913ab3SNickeau 8521913ab3SNickeau } 8621913ab3SNickeau 8721913ab3SNickeau} 88