xref: /template/strap/action/metacsp.php (revision e8b2ff590c848541e718216df3a67061e98c1761)
121913ab3SNickeau<?php
221913ab3SNickeau
3*e8b2ff59SNickeauuse ComboStrap\LogUtility;
4531e725cSNickeauuse ComboStrap\Site;
521913ab3SNickeauuse ComboStrap\StringUtility;
621913ab3SNickeau
721913ab3SNickeauif (!defined('DOKU_INC')) die();
821913ab3SNickeau
921913ab3SNickeau/**
1021913ab3SNickeau *
1121913ab3SNickeau * Adding security directive
1221913ab3SNickeau *
1321913ab3SNickeau */
1421913ab3SNickeauclass action_plugin_combo_metacsp extends DokuWiki_Action_Plugin
1521913ab3SNickeau{
1621913ab3SNickeau
1721913ab3SNickeau
1821913ab3SNickeau    function __construct()
1921913ab3SNickeau    {
2021913ab3SNickeau        // enable direct access to language strings
2121913ab3SNickeau        // ie $this->lang
2221913ab3SNickeau        $this->setupLocale();
2321913ab3SNickeau    }
2421913ab3SNickeau
2521913ab3SNickeau    public function register(Doku_Event_Handler $controller)
2621913ab3SNickeau    {
27*e8b2ff59SNickeau
28*e8b2ff59SNickeau        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'httpHeaderCsp', array());
29*e8b2ff59SNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'htmlMetaCsp', array());
30*e8b2ff59SNickeau
3121913ab3SNickeau    }
3221913ab3SNickeau
3321913ab3SNickeau    /**
3421913ab3SNickeau     * Dokuwiki has already a canonical methodology
3521913ab3SNickeau     * https://www.dokuwiki.org/canonical
3621913ab3SNickeau     *
3721913ab3SNickeau     * @param $event
3821913ab3SNickeau     */
39*e8b2ff59SNickeau    function htmlMetaCsp($event)
4021913ab3SNickeau    {
4121913ab3SNickeau
42531e725cSNickeau
43531e725cSNickeau        /**
44531e725cSNickeau         * HTML meta directives
45531e725cSNickeau         */
4621913ab3SNickeau        $directives = [
4721913ab3SNickeau            'block-all-mixed-content', // no http, https
4821913ab3SNickeau        ];
4921913ab3SNickeau
5021913ab3SNickeau        // Search if the CSP property is already present
5121913ab3SNickeau        $cspKey = null;
5221913ab3SNickeau        foreach ($event->data['meta'] as $key => $meta) {
5321913ab3SNickeau            if (isset($meta["http-equiv"])) {
5485e82846SNickeau                if ($meta["http-equiv"] == "content-security-policy") {
5521913ab3SNickeau                    $cspKey = $key;
5621913ab3SNickeau                }
5721913ab3SNickeau            }
5821913ab3SNickeau        }
5921913ab3SNickeau        if ($cspKey != null) {
6021913ab3SNickeau            $actualDirectives = StringUtility::explodeAndTrim($event->data['meta'][$cspKey]["content"], ",");
6121913ab3SNickeau            $directives = array_merge($actualDirectives, $directives);
6221913ab3SNickeau            $event->data['meta'][$cspKey] = [
6385e82846SNickeau                "http-equiv" => "content-security-policy",
6421913ab3SNickeau                "content" => join(", ", $directives)
6521913ab3SNickeau            ];
6621913ab3SNickeau        } else {
6721913ab3SNickeau            $event->data['meta'][] = [
6885e82846SNickeau                "http-equiv" => "content-security-policy",
6921913ab3SNickeau                "content" => join(",", $directives)
7021913ab3SNickeau            ];
7121913ab3SNickeau        }
7221913ab3SNickeau
73*e8b2ff59SNickeau    }
74*e8b2ff59SNickeau
75*e8b2ff59SNickeau    function httpHeaderCsp($event)
76*e8b2ff59SNickeau    {
77531e725cSNickeau        /**
78531e725cSNickeau         * Http header CSP directives
79531e725cSNickeau         */
80531e725cSNickeau        $httpHeaderReferer = $_SERVER['HTTP_REFERER'];
81531e725cSNickeau        $httpDirectives = [];
82531e725cSNickeau        if (strpos($httpHeaderReferer, Site::getUrl()) === false) {
83531e725cSNickeau            // not same origin
8421913ab3SNickeau            $httpDirectives = [
8585e82846SNickeau                "content-security-policy: frame-ancestors 'none'", // the page cannot be used in a iframe (clickjacking),
8621913ab3SNickeau                "X-Frame-Options: deny" // the page cannot be used in a iframe (clickjacking) - deprecated for frame ancestores
8721913ab3SNickeau            ];
88531e725cSNickeau        }
89*e8b2ff59SNickeau        if (!headers_sent()) {
9021913ab3SNickeau            foreach ($httpDirectives as $httpDirective) {
9121913ab3SNickeau                header($httpDirective);
9221913ab3SNickeau            }
93*e8b2ff59SNickeau        } else {
94*e8b2ff59SNickeau            LogUtility::msg("HTTP Headers have already ben sent. We couldn't add the CSP security header", LogUtility::LVL_MSG_WARNING,"security");
95*e8b2ff59SNickeau        }
9621913ab3SNickeau    }
9721913ab3SNickeau
9821913ab3SNickeau}
99