From 32ace6a8cfdfe0771ab5682dd654a803c7675c4d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 30 Apr 2018 14:39:12 +0200 Subject: [PATCH] NEW Add hook setContentSecurityPolicy --- htdocs/comm/action/list.php | 3 ++ htdocs/core/class/hookmanager.class.php | 5 ++- htdocs/main.inc.php | 42 +++++++++++++++---- .../modulebuilder/template/myobject_card.php | 3 +- .../modulebuilder/template/myobject_list.php | 2 +- htdocs/theme/eldy/style.css.php | 2 +- htdocs/theme/md/style.css.php | 2 +- 7 files changed, 46 insertions(+), 13 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 36630b93092..cca1f59bf8e 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -25,12 +25,15 @@ * \brief Page to list actions */ +if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); + require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $langs->loadLangs(array("users","companies","agenda","commercial")); diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index f3ca56c2e8f..5c1f1358784 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -120,7 +120,7 @@ class HookManager * @param array $parameters Array of parameters * @param Object $object Object to use hooks on * @param string $action Action code on calling page ('create', 'edit', 'view', 'add', 'update', 'delete'...) - * @return mixed For 'addreplace' hooks (doActions,formObjectOptions,pdf_xxx,...): Return 0 if we want to keep standard actions, >0 if we want to stop standard actions, <0 if KO. Things to print are returned into ->resprints and set into ->resPrint. Things to return are returned into ->results by hook and set into ->resArray for caller. + * @return mixed For 'addreplace' hooks (doActions,formObjectOptions,pdf_xxx,...): Return 0 if we want to keep standard actions, >0 if we want to stop/replace standard actions, <0 if KO. Things to print are returned into ->resprints and set into ->resPrint. Things to return are returned into ->results by hook and set into ->resArray for caller. * For 'output' hooks (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...): Return 0, <0 if KO. Things to print are returned into ->resprints and set into ->resPrint. Things to return are returned into ->results by hook and set into ->resArray for caller. * All types can also return some values into an array ->results that will be finaly merged into this->resArray for caller. * $this->error or this->errors are also defined by class called by this function if error. @@ -184,7 +184,8 @@ class HookManager 'printObjectSubLine', 'sendMail', 'sendMailAfter', - 'showLinkToObjectBlock' + 'showLinkToObjectBlock', + 'setContentSecurityPolicy' ) )) $hooktype='addreplace'; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 862b0701e33..f76bb90ef8f 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1077,20 +1077,48 @@ if (! function_exists("llxHeader")) */ function top_httphead($contenttype='text/html', $forcenocache=0) { - global $conf; + global $db, $conf, $hookmanager; if ($contenttype == 'text/html' ) header("Content-Type: text/html; charset=".$conf->file->character_set_client); else header("Content-Type: ".$contenttype); // Security options header("X-Content-Type-Options: nosniff"); // With the nosniff option, if the server says the content is text/html, the browser will render it as text/html (note that most browsers now force this option to on) header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) - if (! empty($conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY)) + header("X-XSS-Protection: 1"); // Enable XSS protection of some browsers (note: use of Content-Security-Policy is more efficient) + if (! defined('FORCECSP')) { - // For example, to restrict script, object, frames or img to some domains - // script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; child-src https://youtube.com; img-src: https://static.example.com - // For example, to restrict everything to one domain, except object, ... - // default-src https://cdn.example.net; object-src 'none' - header("Content-Security-Policy: ".$conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY); + //if (! isset($conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY)) + //{ + // // A default security policy that keep usage of js external component like ckeditor, stripe, google, working + // $contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';"; + //} + //else $contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY; + $contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY; + + if (! is_object($hookmanager)) $hookmanager = new HookManager($db); + $hookmanager->initHooks("main"); + + $parameters=array('contentsecuritypolicy'=>$contentsecuritypolicy); + $result=$hookmanager->executeHooks('setContentSecurityPolicy',$parameters); // Note that $action and $object may have been modified by some hooks + if ($result > 0) $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP + else $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP + + if (! empty($contentsecuritypolicy)) + { + // For example, to restrict 'script', 'object', 'frames' or 'img' to some domains: + // script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: https://static.example.com + // For example, to restrict everything to one domain, except 'object', ...: + // default-src https://cdn.example.net; object-src 'none' + // For example, to restrict everything to itself except img that can be on other servers: + // default-src 'self'; img-src *; + // Pre-existing site that uses too much inline code to fix but wants to ensure resources are loaded only over https and disable plugins: + // default-src http: https: 'unsafe-eval' 'unsafe-inline'; object-src 'none' + header("Content-Security-Policy: ".$contentsecuritypolicy); + } + } + elseif (constant('FORCECSP')) + { + header("Content-Security-Policy: ".constant('FORCECSP')); } if ($forcenocache) { diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 9a7fda388d2..5b2a1213c0f 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -38,7 +38,8 @@ //if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) //if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT','auto'); // Force lang to a particular value //if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE','aloginmodule'); // Force authentication handler -//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP','none'); // Disable all Content Security Policies // Load Dolibarr environment diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index cbac5339384..8d4cf6439a4 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -38,7 +38,7 @@ //if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) //if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT','auto'); // Force lang to a particular value //if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE','aloginmodule'); // Force authentication handler -//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN',1); // The main.inc.php does not make a redirect if not logged, instead show simple error message // Load Dolibarr environment $res=0; diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 6683e966a97..8eb6f0b98c8 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -3509,7 +3509,7 @@ div.titre { padding-bottom: 5px; } -#dolpaymenttable { min-width: 300px; font-size: 16px; } /* Width must have min to make stripe input area visible */ +#dolpaymenttable { min-width: 320px; font-size: 16px; } /* Width must have min to make stripe input area visible. Lower than 320 makes input area crazy for credit card that need zip code */ #tablepublicpayment { border: 1px solid #CCCCCC !important; width: 100%; padding: 20px; } #tablepublicpayment .CTableRow1 { background-color: #F0F0F0 !important; } #tablepublicpayment tr.liste_total { border-bottom: 1px solid #CCCCCC !important; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 0cafac9a6c2..2188a5bff9c 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -3462,7 +3462,7 @@ div.titre { dol_optimize_smallscreen)?'':'margin-top: 4px;'); ?> } -#dolpaymenttable { min-width: 300px; font-size: 16px; } /* Width must have min to make stripe input area visible */ +#dolpaymenttable { min-width: 320px; font-size: 16px; } /* Width must have min to make stripe input area visible. Lower than 320 makes input area crazy for credit card that need zip code */ #tablepublicpayment { border: 1px solid #CCCCCC !important; width: 100%; padding: 20px; } #tablepublicpayment .CTableRow1 { background-color: #F0F0F0 !important; } #tablepublicpayment tr.liste_total { border-bottom: 1px solid #CCCCCC !important; }