1<?php 2 3use ComboStrap\LogUtility; 4use ComboStrap\Site; 5use ComboStrap\StringUtility; 6 7if (!defined('DOKU_INC')) die(); 8 9/** 10 * 11 * Adding security directive 12 * 13 */ 14class action_plugin_combo_metacsp extends DokuWiki_Action_Plugin 15{ 16 17 18 function __construct() 19 { 20 // enable direct access to language strings 21 // ie $this->lang 22 $this->setupLocale(); 23 } 24 25 public function register(Doku_Event_Handler $controller) 26 { 27 28 $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'httpHeaderCsp', array()); 29 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'htmlMetaCsp', array()); 30 31 } 32 33 /** 34 * Dokuwiki has already a canonical methodology 35 * https://www.dokuwiki.org/canonical 36 * 37 * @param $event 38 */ 39 function htmlMetaCsp($event) 40 { 41 42 43 /** 44 * HTML meta directives 45 */ 46 $directives = [ 47 'block-all-mixed-content', // no http, https 48 ]; 49 50 // Search if the CSP property is already present 51 $cspKey = null; 52 foreach ($event->data['meta'] as $key => $meta) { 53 if (isset($meta["http-equiv"])) { 54 if ($meta["http-equiv"] == "content-security-policy") { 55 $cspKey = $key; 56 } 57 } 58 } 59 if ($cspKey != null) { 60 $actualDirectives = StringUtility::explodeAndTrim($event->data['meta'][$cspKey]["content"], ","); 61 $directives = array_merge($actualDirectives, $directives); 62 $event->data['meta'][$cspKey] = [ 63 "http-equiv" => "content-security-policy", 64 "content" => join(", ", $directives) 65 ]; 66 } else { 67 $event->data['meta'][] = [ 68 "http-equiv" => "content-security-policy", 69 "content" => join(",", $directives) 70 ]; 71 } 72 73 } 74 75 function httpHeaderCsp($event) 76 { 77 /** 78 * Http header CSP directives 79 */ 80 $httpHeaderReferer = $_SERVER['HTTP_REFERER']; 81 $httpDirectives = []; 82 if (strpos($httpHeaderReferer, Site::getUrl()) === false) { 83 // not same origin 84 $httpDirectives = [ 85 "content-security-policy: frame-ancestors 'none'", // the page cannot be used in a iframe (clickjacking), 86 "X-Frame-Options: deny" // the page cannot be used in a iframe (clickjacking) - deprecated for frame ancestores 87 ]; 88 } 89 if (!headers_sent()) { 90 foreach ($httpDirectives as $httpDirective) { 91 header($httpDirective); 92 } 93 } else { 94 LogUtility::msg("HTTP Headers have already ben sent. We couldn't add the CSP security header", LogUtility::LVL_MSG_WARNING,"security"); 95 } 96 } 97 98} 99