28require
'../main.inc.php';
36require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
37require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
38require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
41$langs->loadLangs(array(
"users",
"admin",
"other",
"website"));
47$action =
GETPOST(
'action',
'aZ09');
48$cancel =
GETPOST(
'cancel',
'alpha');
66if (preg_match(
'/set_([a-z0-9_\-]+)/i', $action, $reg)) {
70 header(
"Location: ".$_SERVER[
"PHP_SELF"]);
75} elseif (preg_match(
'/del_([a-z0-9_\-]+)/i', $action, $reg)) {
78 header(
"Location: ".$_SERVER[
"PHP_SELF"]);
83} elseif ($action ==
'removecspsource') {
86 $sourcecsp = explode(
"_",
GETPOST(
"sourcecsp"));
87 $directive = $sourcecsp[0];
88 $sourcekey = isset($sourcecsp[1]) ? $sourcecsp[1] :
null;
89 $sourcedata = isset($sourcecsp[2]) ? $sourcecsp[2] :
null;
93 if (empty($directive)) {
97 if (!empty($directivesarray[$directive])) {
98 $directivetype = (string) $directivesarray[$directive][
"data-directivetype"];
99 if (isset($sourcekey)) {
100 $sourcetype = $sourcesarray[$directivetype][$sourcekey][
"data-sourcetype"];
104 $securitycspstring =
"";
105 if (!$error && !empty($forceCSPArr)) {
106 if (isset($sourcekey) && !empty($forceCSPArr[$directive][$sourcekey])) {
107 unset($forceCSPArr[$directive][$sourcekey]);
109 if (count($forceCSPArr[$directive]) == 0) {
110 unset($forceCSPArr[$directive]);
112 foreach ($forceCSPArr as $directive => $sourcekeys) {
113 if ($securitycspstring !=
"") {
114 $securitycspstring .=
"; ";
117 foreach ($sourcekeys as $key => $source) {
118 $directivetype = $directivesarray[$directive][
"data-directivetype"];
119 $sourcetype = $sourcesarray[$directivetype][$source][
"data-sourcetype"];
120 if ($sourcetype ==
"quoted") {
121 $sourcestring .=
" '".$source.
"'";
123 $sourcestring .=
" ".$source;
126 $securitycspstring .= $directive . $sourcestring;
132 $res =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCECSP', $securitycspstring,
'chaine', 0,
'', $conf->entity);
140 setEventMessages($langs->trans(
"MainSecurityPolicySucesfullyRemoved"),
null,
'mesgs');
143 setEventMessages($langs->trans(
"MainErrorRemovingSecurityPolicy"),
null,
'errors');
146 header(
"Location: ".$_SERVER[
"PHP_SELF"]);
148} elseif ($action ==
"updateform" &&
GETPOST(
"btn_MAIN_SECURITY_FORCECSP")) {
149 $directivecsp =
GETPOST(
"select_identifier_MAIN_SECURITY_FORCECSP");
150 $sourcecsp =
GETPOST(
"select_source_MAIN_SECURITY_FORCECSP");
151 $sourcedatacsp =
GETPOST(
"input_data_MAIN_SECURITY_FORCECSP");
157 if (empty($directivecsp)) {
160 if ($error || (!isset($sourcecsp) && $directivesarray[$directivecsp][
"data-directivetype"] !=
"none")) {
164 $directivetype = $directivesarray[$directivecsp][
"data-directivetype"];
165 if (isset($sourcecsp)) {
166 $sourcetype = $sourcesarray[$directivetype][$sourcecsp][
"data-sourcetype"];
168 $securitycspstring =
"";
169 if (isset($sourcetype) && $sourcetype ==
"data") {
170 $forceCSPArr[$directivecsp][] =
"data:".$sourcedatacsp;
171 } elseif (isset($sourcetype) && $sourcetype ==
"blob") {
172 $forceCSPArr[$directivecsp][] =
"blob:".$sourcedatacsp;
173 } elseif (isset($sourcetype) && $sourcetype ==
"input") {
174 if (empty($forceCSPArr[$directivecsp])) {
175 $forceCSPArr[$directivecsp] = array();
177 $forceCSPArr[$directivecsp] = array_merge(explode(
" ", $sourcedatacsp), $forceCSPArr[$directivecsp]);
179 if (empty($forceCSPArr[$directivecsp])) {
180 $forceCSPArr[$directivecsp] = array();
182 if (!isset($sourcecsp)) {
185 array_unshift($forceCSPArr[$directivecsp], $sourcecsp);
187 foreach ($forceCSPArr as $directive => $sourcekeys) {
188 if ($securitycspstring !=
"") {
189 $securitycspstring .=
"; ";
192 foreach ($sourcekeys as $key => $source) {
193 $directivetype = $directivesarray[$directive][
"data-directivetype"];
194 $sourcetype = $sourcesarray[$directivetype][$source][
"data-sourcetype"];
195 if (isset($sourcetype) && $sourcetype ==
"quoted") {
196 $sourcestring .=
" '".$source.
"'";
197 } elseif ($directivetype !=
"none") {
198 $sourcestring .=
" ".$source;
201 $securitycspstring .= $directive . $sourcestring;
207 $res =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCECSP', $securitycspstring,
'chaine', 0,
'', $conf->entity);
215 setEventMessages($langs->trans(
"MainSecurityPolicySucesfullyAdded"),
null,
'mesgs');
218 setEventMessages($langs->trans(
"MainErrorAddingSecurityPolicy"),
null,
'errors');
220 header(
"Location: ".$_SERVER[
"PHP_SELF"]);
222} elseif ($action ==
"updateform") {
224 $res1 = $res2 = $res3 = $res4 = 0;
225 $securityrp =
GETPOST(
'MAIN_SECURITY_FORCERP',
'alpha');
226 $securitysts =
GETPOST(
'MAIN_SECURITY_FORCESTS',
'alpha');
227 $securitypp =
GETPOST(
'MAIN_SECURITY_FORCEPP',
'alpha');
228 $securitycsp =
GETPOST(
'MAIN_SECURITY_FORCECSP',
'alpha');
229 $securitycspro =
GETPOST(
'MAIN_SECURITY_FORCECSPRO',
'alpha');
235 $res1 =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCERP', $securityrp,
'chaine', 0,
'', $conf->entity);
236 $res2 =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCESTS', $securitysts,
'chaine', 0,
'', $conf->entity);
237 $res3 =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCEPP', $securitypp,
'chaine', 0,
'', $conf->entity);
238 $res4 =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCECSP', $securitycsp,
'chaine', 0,
'', $conf->entity);
239 $res5 =
dolibarr_set_const($db,
'MAIN_SECURITY_FORCECSPRO', $securitycspro,
'chaine', 0,
'', $conf->entity);
241 if ($res1 >= 0 && $res2 >= 0 && $res3 >= 0 && $res4 >= 0 && $res5 >= 0) {
245 header(
"Location: ".$_SERVER[
"PHP_SELF"]);
263 if (!empty($securitycsp)) {
264 if (!preg_match(
'/script-src.*self/', $securitycsp) || !preg_match(
'/script-src.*unsafe-inline/', $securitycsp)) {
265 if (!preg_match(
'/script-src/', $securitycsp)) {
266 $securitycsp .= (preg_match(
'/;\s*$/', $securitycsp) ?
'' :
'; ').
' script-src \'self\' \'unsafe-inline\';';
268 $securitycsp = preg_replace(
'/script-src\s+/',
'script-src \'self\' \'unsafe-inline\' ', $securitycsp);
271 if (!preg_match(
'/style-src.*self/', $securitycsp) || !preg_match(
'/style-src.*unsafe-inline/', $securitycsp)) {
272 if (!preg_match(
'/style-src/', $securitycsp)) {
273 $securitycsp .= (preg_match(
'/;\s*$/', $securitycsp) ?
'' :
'; ').
' style-src \'self\' \'unsafe-inline\';';
275 $securitycsp = preg_replace(
'/style-src\s+/',
'style-src \'self\' \'unsafe-inline\' ', $securitycsp);
278 if (!preg_match(
'/dolibarr\.org/', $securitycsp)) {
279 if (!preg_match(
'/default-src/', $securitycsp)) {
280 $securitycsp .= (preg_match(
'/;\s*$/', $securitycsp) ?
'' :
'; ').
' default-src *.dolibarr.org;';
282 $securitycsp = preg_replace(
'/default-src\s+/',
'default-src *.dolibarr.org ', $securitycsp);
286 $securitycsp = preg_replace(
'/\s+/',
' ', $securitycsp);
295$form =
new Form($db);
297$wikihelp =
'EN:Setup_Security|FR:Paramétrage_Sécurité|ES:Configuración_Seguridad';
298llxHeader(
'', $langs->trans(
"MainHttpSecurityHeaders"), $wikihelp,
'', 0, 0,
'',
'',
'',
'mod-admin page-security_other');
307print
'<span class="opacitymedium">'.$langs->trans(
"HTTPHeaderEditor").
'. '.$langs->trans(
"ReservedToAdvancedUsers").
'.</span><br><br>';
309print
'<form action="'.$_SERVER[
"PHP_SELF"].
'" method="POST">';
310print
'<input type="hidden" name="token" value="'.newToken().
'">';
311print
'<input type="hidden" name="action" value="updateform">';
313print
'<div class="div-table-responsive-no-min">';
314print
'<table class="noborder centpercent">';
315print
'<tr class="liste_titre">';
316print
'<td>'.$langs->trans(
"HTTPHeader").
'</td>';
317print
'<td></td>'.
"\n";
321print
'<tr class="oddeven">';
322print
'<td>'.$form->textwithpicto($langs->trans(
'MainSecurityForceRP'),
'HTTP Header Referer-Policy<br><br>'.$langs->trans(
"Recommended").
':<br>strict-origin-when-cross-origin <span class="opacitymedium"> '.$langs->trans(
"or").
' </span> same-origin <span class="opacitymedium">(more secured)</span>', 1,
'help',
'valignmiddle', 0, 3,
'MAIN_SECURITY_FORCERP').
'</td>';
323print
'<td><input class="minwidth500" name="MAIN_SECURITY_FORCERP" id="MAIN_SECURITY_FORCERP" value="'.getDolGlobalString(
"MAIN_SECURITY_FORCERP").
'" spellcheck="false"></td>';
326print
'<tr class="oddeven">';
327print
'<td>'.$form->textwithpicto($langs->trans(
'MainSecurityForceSTS'),
'HTTP Header Strict-Transport-Security<br><br>'.$langs->trans(
"Example").
':<br>max-age=31536000; includeSubDomains', 1,
'help',
'valignmiddle', 0, 3,
'MAIN_SECURITY_FORCESTS').
'</td>';
328print
'<td><input class="minwidth500" name="MAIN_SECURITY_FORCESTS" id="MAIN_SECURITY_FORCESTS" value="'.getDolGlobalString(
"MAIN_SECURITY_FORCESTS").
'" spellcheck="false"></td>';
331print
'<tr class="oddeven">';
332print
'<td>'.$form->textwithpicto($langs->trans(
'MainSecurityForcePP'),
'HTTP Header Permissions-Policy<br><br>'.$langs->trans(
"Example").
':<br>camera=*, microphone=(), geolocation=*', 1,
'help',
'valignmiddle', 0, 3,
'MAIN_SECURITY_FORCEPP').
'</td>';
333print
'<td><input class="minwidth500" name="MAIN_SECURITY_FORCEPP" id="MAIN_SECURITY_FORCEPP" value="'.getDolGlobalString(
"MAIN_SECURITY_FORCEPP").
'" spellcheck="false"></td>';
336$examplecsprule =
"frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com;";
339print
'<tr class="oddeven nohover">';
340print
'<td class="tdtop">'.$form->textwithpicto($langs->trans(
'MainContentSecurityPolicy'),
'HTTP Header Content-Security-Policy<br><br>'.$langs->trans(
"Example").
":<br>".$examplecsprule, 1,
'help',
'valignmiddle', 0, 3,
'MAIN_SECURITY_FORCECSP').
'</td>';
343print
'<div class="div-table-responsive-no-min">';
345print
'<input class="minwidth500 quatrevingtpercent" name="MAIN_SECURITY_FORCECSP" id="MAIN_SECURITY_FORCECSP" value="'.$forceCSP.
'" spellcheck="false"> <a href="#" id="btnaddcontentsecuritypolicy">'.
img_picto(
'',
'add').
'</a><br>';
347print
'<br class="selectaddcontentsecuritypolicy hidden">';
349print
'<div id="selectaddcontentsecuritypolicy" class="hidden selectaddcontentsecuritypolicy">';
350print $form->selectarray(
"select_identifier_MAIN_SECURITY_FORCECSP", $selectarrayCSPDirectives,
"select_identifier_MAIN_SECURITY_FORCECSP", $langs->trans(
"FillCSPDirective"), 0, 0,
'', 0, 0, 0,
'',
'minwidth200 maxwidth350 inline-block');
352print
'<input type="hidden" id="select_source_MAIN_SECURITY_FORCECSP" name="select_source_MAIN_SECURITY_FORCECSP">';
353foreach ($selectarrayCSPSources as $key => $values) {
354 print
'<div class="div_MAIN_SECURITY_FORCECSP hidden inline-block maxwidth350" id="div_'.$key.
'_MAIN_SECURITY_FORCECSP">';
355 print $form->selectarray(
"select_".$key.
"_MAIN_SECURITY_FORCECSP", $values,
"select_".$key.
"_MAIN_SECURITY_FORCECSP", $langs->trans(
"FillCSPSource"), 0, 0,
'', 0, 0, 0,
'',
'minwidth200 maxwidth300 inline-block select_MAIN_SECURITY_FORCECSP');
359print
'<div class="div_input_data_MAIN_SECURITY_FORCECSP hidden inline-block maxwidth200"><input id="input_data_MAIN_SECURITY_FORCECSP" name="input_data_MAIN_SECURITY_FORCECSP"></div>';
361print
'<div class="div_btn_class_MAIN_SECURITY_FORCECSP inline-block maxwidth200"><input type="submit" id="btn_MAIN_SECURITY_FORCECSP" name="btn_MAIN_SECURITY_FORCECSP" class="butAction small smallpaddingimp" value="'.$langs->trans(
"Add").
'" disabled></div>';
365if (!empty($forceCSP)) {
368 print
'<div class="div-table-responsive-no-min">';
369 print
img_picto(
'',
'graph',
'class="pictofixedwidth"').$langs->trans(
"HierarchicView").
'<br>';
371 foreach ($forceCSPArr as $directive => $sources) {
373 if (in_array($directive, array_keys($selectarrayCSPDirectives))) {
374 print
'<span>'.$directive.
'</span>';
376 print $form->textwithpicto($directive, $langs->trans(
"UnknowContentSecurityPolicyDirective"), 1,
'warning');
378 if (!empty($sources)) {
380 foreach ($sources as $key => $source) {
381 print
'<li><span>'.$source.
'</span> <a href="'.$_SERVER[
"PHP_SELF"].
'?action=removecspsource&sourcecsp='.$directive.
'_'.$key.
'&token='.
newToken().
'">'.
img_delete().
'</a></li>';
385 print
' <a href="'.$_SERVER[
"PHP_SELF"].
'?action=removecspsource&sourcecsp='.$directive.
'&token='.
newToken().
'">'.
img_delete().
'</a>';
399 print
'<tr class="oddeven">';
400 print
'<td>'.$form->textwithpicto($langs->trans(
'MainSecurityForceCSPRO'),
'HTTP Header Content-Security-Policy-Report-Only<br><br>'.$langs->trans(
"Example").
":<br>".$examplecsprule, 1,
'help',
'valignmiddle', 0, 3,
'MAIN_SECURITY_FORCECSPRO').
'</td>';
401 print
'<td><input class="minwidth500" name="MAIN_SECURITY_FORCECSPRO" id="MAIN_SECURITY_FORCECSPRO" value="'.getDolGlobalString(
"MAIN_SECURITY_FORCECSPRO").
'"></td>';
409print
'<div class="center">';
411print
'<input type="submit" class="button small" name="updateandstay" value="'.$langs->trans(
"Save").
'">';
412print
'<input class="button button-cancel small" type="submit" name="cancel" value="'.$langs->trans(
"Cancel").
'">';
418 $(document).ready(function() {
419 $("#btnaddcontentsecuritypolicy").on("click", function(){
420 if($("#selectaddcontentsecuritypolicy").is(":visible")){
421 console.log("We hide select to add Content Security Policy");
422 $(".selectaddcontentsecuritypolicy").hide();
424 console.log("We show select to add Content Security Policy");
425 $(".selectaddcontentsecuritypolicy").show();
429 $("#select_identifier_MAIN_SECURITY_FORCECSP").on("change", function() {
430 key = $(this).find(":selected").data("directivetype");
431 console.log("We hide all select div");
432 $(".div_MAIN_SECURITY_FORCECSP").hide();
433 $(".select_MAIN_SECURITY_FORCECSP").val(null).trigger("change");
434 $(".div_input_data_MAIN_SECURITY_FORCECSP").hide();
435 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",true);
437 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",false);
439 console.log("We show div select with key "+key);
440 $("#div_"+key+"_MAIN_SECURITY_FORCECSP").css("display", "inline-block");
444 $(".select_MAIN_SECURITY_FORCECSP").on("change", function() {
445 keysource = $(this).find(":selected").data("sourcetype");
446 $("#select_source_MAIN_SECURITY_FORCECSP").val($(this).val());
447 console.log("We hide and show fields");
448 if (keysource == "data" || keysource == "input") {
449 $(".div_input_data_MAIN_SECURITY_FORCECSP").css("display", "inline-block");
450 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",true);
452 $("#input_data_MAIN_SECURITY_FORCECSP").val("");
453 $(".div_input_data_MAIN_SECURITY_FORCECSP").hide();
454 if (keysource != undefined) {
455 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",false);
457 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",true);
462 $("#input_data_MAIN_SECURITY_FORCECSP").on("change keyup", function(){
463 if ($(this).val() != "") {
464 console.log("We show add button");
465 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",false);
467 console.log("We hide add button");
468 $("#btn_MAIN_SECURITY_FORCECSP").prop("disabled",true);
security_prepare_head()
Prepare array with list of tabs.
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
GetContentPolicySources()
Prepare array of sources for HTTP headers.
GetContentPolicyToArray($forceCSP)
Transform a Content Security Policy to an array.
GetContentPolicyDirectives()
Prepare array of directives for HTTP headers.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.