* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/admin/system/security.php * \brief Page to show Security information */ // Load Dolibarr environment require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/events.class.php'; // Load translation files required by the page $langs->loadLangs(array("install", "other", "admin", "errors")); if (!$user->admin) { accessforbidden(); } if (GETPOST('action', 'aZ09') == 'donothing') { exit; } $execmethod = getDolGlobalInt('MAIN_EXEC_USE_POPEN', 1); /* * View */ $form = new Form($db); llxHeader('', '', '', '', 0, 0, '', '', '', 'mod-admin page-system_security'); print load_fiche_titre($langs->trans("Security"), '', 'title_setup'); print ''.$langs->trans("YouMayFindSecurityAdviceHere", 'hhttps://wiki.dolibarr.org/index.php/Security_information').''; print '     '; print ''; print img_picto($langs->trans("Reload"), 'refresh').' '; print $langs->trans("Reload"); print ''; print '
'; print '
'; print '
'; print load_fiche_titre($langs->trans("PHPSetup"), '', 'folder'); print '
'; // Get version of PHP $phpversion = version_php(); print "PHP: ".$langs->trans("Version").": ".$phpversion; if (function_exists('php_ini_loaded_file')) { $inipath = php_ini_loaded_file(); print " - INI: ".$inipath; } print "
\n"; // Get version of web server print "
Web server - ".$langs->trans("Version").": ".$_SERVER["SERVER_SOFTWARE"]."
\n"; print ''.$langs->trans("DataRootServer").": ".DOL_DATA_ROOT."
\n"; // Web user group by default $labeluser = dol_getwebuser('user'); $labelgroup = dol_getwebuser('group'); if ($labeluser && $labelgroup) { print ''.$langs->trans("WebUserGroup")." (env vars) : ".$labeluser.':'.$labelgroup; if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) { $arrayofinfoofuser = posix_getpwuid(posix_geteuid()); print ' (POSIX '.$arrayofinfoofuser['name'].':'.$arrayofinfoofuser['gecos'].':'.$arrayofinfoofuser['dir'].':'.$arrayofinfoofuser['shell'].')
'."\n"; } } // Web user group real (detected by 'id' external command) if (function_exists('exec')) { $arrayout = array(); $varout = 0; exec('id', $arrayout, $varout); if (empty($varout)) { // Test command is ok. Work only on Linux OS. print ''.$langs->trans("WebUserGroup")." (real, 'id' command) : ".implode(',', $arrayout)."
\n"; } } print '
'; print "PHP session.use_strict_mode = ".(ini_get('session.use_strict_mode') ? img_picto('', 'tick').' ' : img_warning().' ').(ini_get('session.use_strict_mode') ? ini_get('session.use_strict_mode') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", '1').")
\n"; print "PHP session.use_only_cookies = ".(ini_get('session.use_only_cookies') ? img_picto('', 'tick').' ' : img_warning().' ').(ini_get('session.use_only_cookies') ? ini_get('session.use_only_cookies') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", '1').")
\n"; print "PHP session.cookie_httponly = ".(ini_get('session.cookie_httponly') ? img_picto('', 'tick').' ' : img_warning().' ').(ini_get('session.cookie_httponly') ? ini_get('session.cookie_httponly') : '').'   ('.$langs->trans("RecommendedValueIs", '1').")
\n"; print "PHP session.cookie_samesite = ".(ini_get('session.cookie_samesite') ? img_picto('', 'tick').' ' .ini_get('session.cookie_samesite') : 'None'); if (!ini_get('session.cookie_samesite') || ini_get('session.cookie_samesite') == 'Lax') { print '   ('.$langs->trans("RecommendedValueIs", 'Lax').")"; } elseif (ini_get('session.cookie_samesite') == 'Strict') { print '   '.img_warning().' '.$langs->trans("WarningPaypalPaymentNotCompatibleWithStrict").""; } print "
\n"; print "PHP open_basedir = ".(ini_get('open_basedir') ? img_picto('', 'tick').' '.ini_get('open_basedir') : img_warning().' '.yn(0).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("ARestrictedPath").', '.$langs->transnoentitiesnoconv("Example").': '.$_SERVER["DOCUMENT_ROOT"].','.DOL_DATA_ROOT).')')."
\n"; print "PHP short_open_tag = ".((empty(ini_get('short_open_tag')) || ini_get('short_open_tag') == 'Off') ? img_picto('', 'tick').' '.yn(0) : img_warning().' '.yn(1)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).')'."
\n"; print "PHP allow_url_fopen = ".(ini_get('allow_url_fopen') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_fopen') : yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No"))." but may be required by some external modules)
\n"; print "PHP allow_url_include = ".(ini_get('allow_url_include') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning').' '.ini_get('allow_url_include') : img_picto('', 'tick').' '.yn(0)).'   ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")
\n"; //print "PHP safe_mode = ".(ini_get('safe_mode') ? ini_get('safe_mode') : yn(0)).'   '.$langs->trans("Deprecated")." (removed in PHP 5.4)
\n"; if (getDolGlobalString('MAIN_SECURITY_SHOW_MORE_INFO')) { print "PHP auto_prepend_file = ".(ini_get('auto_prepend_file') ? ini_get('auto_prepend_file') : '')."
\n"; print "PHP sendmail_path = ".(ini_get('sendmail_path') ? ini_get('sendmail_path') : '')."
\n"; } print "PHP disable_functions = "; $arrayoffunctionsdisabled = explode(',', ini_get('disable_functions')); $arrayoffunctionstodisable = explode(',', 'dl,apache_note,apache_setenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,show_source,virtual'); //$arrayoffunctionstodisable[] = 'stream_wrapper_restore'; //$arrayoffunctionstodisable[] = 'stream_wrapper_register'; if ($execmethod == 1) { $arrayoffunctionstodisable2 = explode(',', 'passthru,shell_exec,system,proc_open,popen'); $functiontokeep = 'exec'; } else { $arrayoffunctionstodisable2 = explode(',', 'exec,passthru,shell_exec,system,proc_open'); $functiontokeep = 'popen'; } $i = 0; foreach ($arrayoffunctionsdisabled as $functionkey) { if ($i > 0) { print ', '; } print ''.$functionkey.''; $i++; } print "
\n"; $todisabletext = ''; $i = 0; foreach ($arrayoffunctionstodisable as $functiontodisable) { if (\function_exists($functiontodisable)) { if ($i > 0) { $todisabletext .= ', '; } $todisabletext .= ' '.$functiontodisable.''; $i++; } } if ($todisabletext) { print img_picto('', 'warning', 'class="pictofixedwidth"').$langs->trans("YouShouldDisablePHPFunctions").': '.$todisabletext; print '
'; } $todisabletext = ''; $i = 0; foreach ($arrayoffunctionstodisable2 as $functiontodisable) { if (\function_exists($functiontodisable)) { if ($i > 0) { $todisabletext .= ', '; } $todisabletext .= ' '.$functiontodisable.''; $i++; } } if ($todisabletext) { print img_picto('', 'warning', 'class="pictofixedwidth"').$langs->trans("IfCLINotRequiredYouShouldDisablePHPFunctions").': '.$todisabletext; print '
'; } if (!\function_exists($functiontokeep)) { print img_picto($langs->trans("PHPFunctionsRequiredForCLI"), 'warning', 'class="pictofixedwidth"'); } else { print img_picto('', 'tick', 'class="pictofixedwidth"'); } print $langs->trans("PHPFunctionsRequiredForCLI").': '; print ''.$functiontokeep.''; print '
'; print '
'; // JSON print 'JSON: '; $loadedExtensions = array_map('strtolower', get_loaded_extensions(false)); $test = !in_array('json', $loadedExtensions); if ($test || function_exists('dol_json_decode')) { print img_picto('', 'error').' '.$langs->trans("NotInstalled").' - '.$langs->trans("VulnerableToRCEAttack"); } else { print img_picto('', 'tick').' '.$langs->trans("Available").' (PHP native so not emulated, safe)'; } print '
'; // XDebug print 'XDebug: '; $test = !function_exists('xdebug_is_enabled') && !extension_loaded('xdebug'); if ($test) { print img_picto('', 'tick').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); } else { print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedMayExposeInformation", $langs->transnoentities("XDebug")); print ' - '.$langs->trans("MoreInformation").' XDebug admin page'; } print '
'; print '
'; // OS Permissions print '
'; print load_fiche_titre($langs->trans("OSSetup").' - '.$langs->trans("PermissionsOnFiles"), '', 'folder'); print '
'; print ''.$langs->trans("PermissionsOnFilesInWebRoot").': '; $arrayoffilesinroot = dol_dir_list(DOL_DOCUMENT_ROOT, 'all', 1, '', array('\/custom'), 'name', SORT_ASC, 4, 1, '', 1); $fileswithwritepermission = array(); foreach ($arrayoffilesinroot as $fileinroot) { // Test if there is at least one write permission file. If yes, add the entry into array $fileswithwritepermission if (isset($fileinroot['perm']) && ($fileinroot['perm'] & 0222)) { $fileswithwritepermission[] = $fileinroot['relativename']; } } if (empty($fileswithwritepermission)) { print img_picto('', 'tick').' '.$langs->trans("NoWritableFilesFoundIntoRootDir"); } else { print img_warning().' '.$langs->trans("SomeFilesOrDirInRootAreWritable"); print '
'.$langs->trans("Example").': '; $i = 0; foreach ($fileswithwritepermission as $filewithwritepermission) { if ($i > 0) { print ', '; } print ''.$filewithwritepermission.''; if ($i > 20) { print ' ...'; break; } $i++; } } print '
'; print '
'; print ''.$langs->trans("PermissionsOnFile", $conffile).': '; // $conffile is defined into filefunc.inc.php $perms = fileperms($dolibarr_main_document_root.'/'.$conffile); if ($perms) { if (($perms & 0x0004) || ($perms & 0x0002)) { print img_warning().' '.$langs->trans("ConfFileIsReadableOrWritableByAnyUsers"); // Web user group by default $labeluser = dol_getwebuser('user'); $labelgroup = dol_getwebuser('group'); print ' '.$langs->trans("User").': '.$labeluser.':'.$labelgroup; if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) { $arrayofinfoofuser = posix_getpwuid(posix_geteuid()); print ' (POSIX '.$arrayofinfoofuser['name'].':'.$arrayofinfoofuser['gecos'].':'.$arrayofinfoofuser['dir'].':'.$arrayofinfoofuser['shell'].')'; } } else { print img_picto('', 'tick'); } } else { print img_warning().' '.$langs->trans("FailedToReadFile", $conffile); } print '
'; print '
'; $installlock = DOL_DATA_ROOT.'/install.lock'; $upgradeunlock = DOL_DATA_ROOT.'/upgrade.unlock'; $installmoduleslock = DOL_DATA_ROOT.'/installmodules.lock'; // Is install (upgrade) locked print ''.$langs->trans("DolibarrSetup").': '; if (file_exists($installlock)) { if (file_exists($upgradeunlock)) { print img_picto('', 'tick').' '.$langs->trans("InstallLockedBy", $installlock); } else { print img_picto('', 'tick').' '.$langs->trans("InstallAndUpgradeLockedBy", $installlock); } } else { print img_warning().' '.$langs->trans("WarningLockFileDoesNotExists", DOL_DATA_ROOT); } print '
'; print '
'; // Is upgrade unlocked if (file_exists($installlock)) { // If install not locked, no need to show this. if (file_exists($upgradeunlock)) { print ''.$langs->trans("DolibarrUpgrade").': '; print img_warning().' '.$langs->trans("WarningUpgradeHasBeenUnlocked", $upgradeunlock); print '
'; print '
'; } } // Is addon install locked ? print ''.$langs->trans("DolibarrAddonInstall").': '; if (file_exists($installmoduleslock)) { print img_picto('', 'tick').' '.$langs->trans("InstallAndUpgradeLockedBy", $installmoduleslock); } else { print $langs->trans("InstallOfAddonIsNotBlocked", DOL_DATA_ROOT); } print '
'; // File conf.php print '
'; print '
'; print load_fiche_titre($langs->trans("ConfigurationFile").' ('.$conffile.')', '', 'folder'); print '
'; print '$dolibarr_main_prod: '.($dolibarr_main_prod ? $dolibarr_main_prod : '0'); if (empty($dolibarr_main_prod)) { print '     '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 1); } print '
'; print '$dolibarr_nocsrfcheck: '.(empty($dolibarr_nocsrfcheck) ? '0' : $dolibarr_nocsrfcheck); if (!empty($dolibarr_nocsrfcheck)) { print '    '.img_picto('', 'error').' '.$langs->trans("IfYouAreOnAProductionSetThis", 0); } else { print '     ('.$langs->trans("Recommended").': 0)'; } print '
'; print '$dolibarr_main_restrict_ip: '; if (empty($dolibarr_main_restrict_ip)) { print $langs->trans("None"); print '     ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("StaticIPsOfUsers")).')'; } else { print $dolibarr_main_restrict_ip; } print '
'; print '$dolibarr_main_restrict_os_commands: '; if (empty($dolibarr_main_restrict_os_commands)) { print $langs->trans("None"); } else { print $dolibarr_main_restrict_os_commands; } print '     ('.$langs->trans("RecommendedValueIs", 'mysqldump, mysql, pg_dump, pg_restore, mariadb, mariadb-dump, clamdscan').')'; print '
'; if (!getDolGlobalString('SECURITY_DISABLE_TEST_ON_OBFUSCATED_CONF')) { print '$dolibarr_main_db_pass: '; if (!empty($dolibarr_main_db_pass) && empty($dolibarr_main_db_encrypted_pass)) { print img_picto('', 'warning').' '.$langs->trans("DatabasePasswordNotObfuscated").'     ('.$langs->trans("Recommended").': '.$langs->trans("SetOptionTo", $langs->transnoentitiesnoconv("MainDbPasswordFileConfEncrypted"), yn(1)).')'; //print ' ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')'; } else { print img_picto('', 'tick').' '.$langs->trans("DatabasePasswordObfuscated"); } print '
'; } print '$dolibarr_main_stream_to_disable: '; // $arrayofstreamtodisable is defined into filefunc.inc.php if (empty($dolibarr_main_stream_to_disable)) { print ''.$langs->trans("Undefined").' = '.implode(', ', $arrayofstreamtodisable).''; } else { print implode(', ', $dolibarr_main_stream_to_disable); } print ' -> Current PHP streams allowed = '; $arrayofstreams = stream_get_wrappers(); if (!empty($arrayofstreams)) { sort($arrayofstreams); print(implode(', ', $arrayofstreams)).'     ('.$langs->trans("Recommended").': '.$langs->trans("TryToKeepOnly", 'file,http,https,php,zip').')'."\n"; } print '
'; /* if (!empty($dolibarr_main_stream_do_not_disable)) { print '$dolibarr_main_stream_do_not_disable: '; if (empty($dolibarr_main_stream_do_not_disable)) { print ''.$langs->trans("Undefined").''; } else { print join(', ', $dolibarr_main_stream_do_not_disable); } print ' -> PHP stream allowed = '; $arrayofstreams = stream_get_wrappers(); if (!empty($arrayofstreams)) { sort($arrayofstreams); print (join(',', $arrayofstreams)).'     ('.$langs->trans("RecommendedValueIs", 'Undefined').')'."\n"; } print '
'; } */ // Menu Home - Setup - Security print '
'; print '
'; print load_fiche_titre($langs->trans("Menu").' '.$langs->trans("SecuritySetup"), '', 'folder'); print '
'; print ''.$langs->trans("UseCaptchaCode").': '; print !getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA') ? '' : img_picto('', 'tick').' '; print yn(!getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA') ? 0 : 1); print '
'; print '
'; $sessiontimeout = ini_get("session.gc_maxlifetime"); if (!getDolGlobalString('MAIN_SESSION_TIMEOUT')) { $conf->global->MAIN_SESSION_TIMEOUT = $sessiontimeout; } print ''.$langs->trans("SessionTimeOut").''; if (!ini_get("session.gc_probability")) { print $form->textwithpicto('', $langs->trans("SessionsPurgedByExternalSystem", ini_get("session.gc_maxlifetime"))); } else { print $form->textwithpicto('', $langs->trans("SessionExplanation", ini_get("session.gc_probability"), ini_get("session.gc_divisor"), ini_get("session.gc_maxlifetime"))); } print ': '.getDolGlobalInt('MAIN_SESSION_TIMEOUT').' '.strtolower($langs->trans("Seconds")); print '

'; print ''.$langs->trans("MaxNumberOfImagesInGetPost").': '; print(getDolGlobalInt('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT') ? img_picto('', 'tick').' ' : '').getDolGlobalInt('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT').' '.strtolower($langs->trans("Images")); print '

'; print ''.$langs->trans("MaxNumberOfPostOnPublicPagesByIP").': '; print(getDolGlobalInt('MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS', 200) ? img_picto('', 'tick').' ' : '').getDolGlobalInt('MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS', 200).' '.strtolower($langs->trans("Posts")); print '

'; print ''.$langs->trans("MaxNumberOfAttachementOnForms").': '; print(getDolGlobalInt('MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS', 10) ? img_picto('', 'tick').' ' : '').getDolGlobalInt("MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", 10).' '.strtolower($langs->trans("Files")); print '

'; print ''.$langs->trans("DoNotStoreClearPassword").': '; print !getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? '' : img_picto('', 'tick').' '; print yn(!getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 0 : 1); if (!getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { print ' ('.$langs->trans("Recommended").' '.yn(1).')'; } print '
'; print '
'; /* Already into section conf file */ /* $usepassinconfencrypted = 0; global $dolibarr_main_db_pass, $dolibarr_main_db_encrypted_pass; if (preg_match('/crypted:/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) { $usepassinconfencrypted = 1; } print ''.$langs->trans("MainDbPasswordFileConfEncrypted").': '; print $usepassinconfencrypted ? img_picto('', 'tick').' ' : img_warning().' '; print yn($usepassinconfencrypted); if (empty($usepassinconfencrypted)) { print ' ('.$langs->trans("Recommended").' '.yn(1).')'; } print '
'; print '
'; */ /* Password length // Stored into $tabconf[0] if module generator is "Perso" or specific to the module generator. $tabConf = explode(";", getDolGlobalString('USER_PASSWORD_PATTERN')); print ''.$langs->trans("PasswordLength").': '; print empty($conf->global->DATABASE_PWD_ENCRYPTED) ? '' : img_picto('', 'tick').' '; print yn(empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1); if (empty($conf->global->DATABASE_PWD_ENCRYPTED)) { print ' ('.$langs->trans("Recommended").' '.yn(1).')'; } print '
'; print '
'; */ print ''.$langs->trans("AntivirusEnabledOnUpload").': '; print !getDolGlobalString('MAIN_ANTIVIRUS_COMMAND') ? img_warning().' ' : img_picto('', 'tick').' '; print yn(!getDolGlobalString('MAIN_ANTIVIRUS_COMMAND') ? 0 : 1); if (!getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) { print ' - '.$langs->trans("Recommended").': '.$langs->trans("DefinedAPathForAntivirusCommandIntoSetup", $langs->transnoentitiesnoconv("Home")." - ".$langs->transnoentitiesnoconv("Setup")." - ".$langs->transnoentitiesnoconv("Security")).''; } else { print '   - ' . getDolGlobalString('MAIN_ANTIVIRUS_COMMAND'); if (defined('MAIN_ANTIVIRUS_COMMAND') && !defined('MAIN_ANTIVIRUS_BYPASS_COMMAND_AND_PARAM')) { print ' - '.$langs->trans("ValueIsForcedBySystem").''; } } print '
'; print '
'; $umask = getDolGlobalString('MAIN_UMASK'); print ''.$langs->trans("UMask").': '; if (! in_array($umask, array('600', '660', '0600', '0660'))) { print img_warning().' '; } print $umask; if (! in_array($umask, array('600', '660', '0600', '0660'))) { print '   ('.$langs->trans("Recommended").': 0600 | 0660)'; } print '
'; print '
'; $securityevent = new Events($db); $eventstolog = $securityevent->eventstolog; print ''.$langs->trans("AuditedSecurityEvents").': '; $out = ''; if (!empty($eventstolog) && is_array($eventstolog)) { // Loop on each event type $i = 0; foreach ($eventstolog as $key => $arr) { if ($arr['id']) { $key = 'MAIN_LOGEVENTS_'.$arr['id']; $value = getDolGlobalString($key); if ($value) { if ($i > 0) { $out .= ', '; } $out .= ''.$key.''; $i++; } } } print $out; } if (empty($out)) { print img_warning().' '.$langs->trans("NoSecurityEventsAreAduited", $langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Security").' - '.$langs->transnoentities("Audit")).'
'; } else { $s = $langs->trans("SeeSetupPage", '{s1}'.$langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Security").' - '.$langs->transnoentities("Audit").'{s2}'); print ' - '.str_replace('{s2}', '', str_replace('{s1}', '', $s)); } print '
'; print '
'; // Modules/Applications print '
'; print '
'; print load_fiche_titre($langs->trans("Modules"), '', 'folder'); print '
'; // Module log print ''.$langs->trans("Syslog").': '; $test = isModEnabled('syslog'); if (!$test) { print img_picto('', 'tick').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); } else { if (getDolGlobalInt('SYSLOG_LEVEL') > LOG_NOTICE) { print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedWithTooHighLogLevel", $langs->transnoentities("Syslog")); } else { print img_picto('', 'tick').' '.$langs->trans("ModuleSyslogActivatedButLevelNotTooVerbose", $langs->transnoentities("Syslog"), getDolGlobalInt('SYSLOG_LEVEL')); } //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; } print '
'; print '
'; // Module debugbar print ''.$langs->trans("DebugBar").': '; $test = isModEnabled('debugbar'); if (!$test) { print img_picto('', 'tick').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis"); } else { print img_picto('', 'error').' '.$langs->trans("ModuleActivatedDoNotUseInProduction", $langs->transnoentities("DebugBar")); //print ' '.$langs->trans("MoreInformation").' XDebug admin page'; } print '
'; // Modules for Payments $test = isModEnabled('stripe'); if ($test) { print '
'; print ''.$langs->trans("Stripe").': '; if (!getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) { print img_picto('', 'error').' '.$langs->trans("OptionXShouldBeEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Stripe")); } else { print img_picto('', 'tick').' '.$langs->trans("OptionXIsCorrectlyEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Stripe")); } print '
'; } else { $test = isModEnabled('paypal'); if ($test) { print '
'; print ''.$langs->trans("Paypal").': '; if (!getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) { print img_picto('', 'error').' '.$langs->trans("OptionXShouldBeEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Paypal")); } else { print img_picto('', 'tick').' '.$langs->trans("OptionXIsCorrectlyEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Paypal")); } print '
'; } } print '
'; // APIs print '
'; print '
'; print load_fiche_titre($langs->trans("API"), '', 'folder'); print '
'; if (!isModEnabled('api') && !isModEnabled('webservices')) { print $langs->trans("APIsAreNotEnabled"); } else { if (isModEnabled('webservices')) { print img_picto('', 'warning').' '.$langs->trans('YouEnableDeprecatedWSAPIsUseRESTAPIsInstead')."
\n"; print '
'; } if (isModEnabled('api')) { print 'API_ENDPOINT_RULES = '.getDolGlobalString('API_ENDPOINT_RULES', ''.$langs->trans("Undefined").'   ('.$langs->trans("Example").': login:0,users:0,setup:1,status:1,tickets:1,...)')."
\n"; } } print '
'; print 'API_DISABLE_LOGIN_API = '.getDolGlobalString('API_DISABLE_LOGIN_API', '0').'   ('.$langs->trans("Recommended").': 1)
'; print '
'; print '
'; print '
'; print load_fiche_titre($langs->trans("OtherSetup"), '', 'folder'); print '
'; print 'MAIN_ALLOW_SVG_FILES_AS_IMAGES = '.getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_IMAGES', '0').'   ('.$langs->trans("Recommended").': 0)
'; print '
'; print 'MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE = '.getDolGlobalString('MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': 1)
'; print '
'; //print ''.$langs->trans("PasswordEncryption").': '; print 'MAIN_SECURITY_HASH_ALGO = '.getDolGlobalString('MAIN_SECURITY_HASH_ALGO', ''.$langs->trans("Undefined").'')."   "; if (!getDolGlobalString('MAIN_SECURITY_HASH_ALGO')) { print '     (If unset: \'md5\')'; } if (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') != 'password_hash') { print '
MAIN_SECURITY_SALT = '.getDolGlobalString('MAIN_SECURITY_SALT', ''.$langs->trans("Undefined").'').'
'; } else { print '('.$langs->trans("Recommended").': password_hash)'; print '
'; } if (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') != 'password_hash') { print '
The recommended value for MAIN_SECURITY_HASH_ALGO is now \'password_hash\' but setting it now will make ALL existing passwords of all users not valid, so update is not possible.
'; print 'If you really want to switch, you must:
'; print '- Go on home - setup - other and add constant MAIN_SECURITY_HASH_ALGO to value \'password_hash\'
'; print '- In same session, WITHOUT LOGGING OUT, go into your admin user record and set a new password
'; print '- You can now logout and login with this new password. You must now reset password of all other users.
'; print '
'; } print '
'; print 'MAIN_SECURITY_ANTI_SSRF_SERVER_IP = '.getDolGlobalString('MAIN_SECURITY_ANTI_SSRF_SERVER_IP', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': List of static IPs of server separated with coma - '.$langs->trans("Note").': common loopback ip like 127.*.*.*, [::1] are already added)')."
"; print '
'; print 'MAIN_SECURITY_CSRF_WITH_TOKEN = '.getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 2)'."
"; print '
'; print '
'; print '
'; // Other - experimental print load_fiche_titre($langs->trans("OtherSetup").' ('.$langs->trans("Experimental").')', '', 'folder'); print '
'; print 'MAIN_EXEC_USE_POPEN = '; if (!getDolGlobalString('MAIN_EXEC_USE_POPEN')) { print ''.$langs->trans("Undefined").''; } else { print $conf->global->MAIN_EXEC_USE_POPEN; } if ($execmethod == 1) { print '     "exec" PHP method will be used for shell commands'; print '   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 1)'; print ''; } if ($execmethod == 2) { print '     "popen" PHP method will be used for shell commands'; print '   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 1)'; print ''; } print '
'; print '
'; print 'MAIN_SECURITY_MAXFILESIZE_DOWNLOADED = '.getDolGlobalString('MAIN_SECURITY_MAXFILESIZE_DOWNLOADED', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': 100000000)')."
"; print '
'; print 'MAIN_RESTRICTHTML_ONLY_VALID_HTML = '.(getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML') ? '1' : ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Recommended").": 1 - does not work on HTML5 with some old libxml libs)"; // Test compatibility of MAIN_RESTRICTHTML_ONLY_VALID_HTML $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES'); $savMAIN_RESTRICTHTML_ONLY_VALID_HTML = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML'); $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY'); $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 0; $result=dol_htmlwithnojs(' src=>0xbeefed'); $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY; if ($result == 'InvalidHTMLStringCantBeCleaned') { print '   -   '.img_warning().' Your libxml seems to old to work correctly with this option. Disable it !'; } else { print '   -   Test of compatibility with this option seems ok'; } print '
'; print '
'; print 'MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = '.(getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY') ? '1' : ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Recommended").': 1)   -   Module "php-tidy" must be enabled (currently: '.((extension_loaded('tidy') && class_exists("tidy")) ? 'Enabled' : img_picto('', 'warning').' Not available').")"; if (extension_loaded('tidy') && class_exists("tidy")) { // Test compatibility of MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES'); $savMAIN_RESTRICTHTML_ONLY_VALID_HTML = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML'); $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY'); $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 0; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 1; $result=dol_htmlwithnojs(' src=>0xbeefed'); $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY; if ($result == 'InvalidHTMLStringCantBeCleaned') { print '   -   '.img_warning().' Your libxml seems to old to work correctly with this option. Disable it !'; } else { print '   -   Test of compatibility with this option seems ok'; } } print '
'; print '
'; print 'MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = '.(getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES') ? '1' : ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Recommended").": 1 - does not work on HTML5 with some old libxml libs)
"; print '
'; // MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 1, disallow url links except if on /medias // MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 2, disallow all external urls link print 'MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = '.getDolGlobalString('MAIN_DISALLOW_URL_INTO_DESCRIPTIONS', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': 1=only local links allowed or 2=no links at all)')."
"; print '
'; print 'MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS = '.getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; print '
'; // MAIN_ALLOW_LOCAL_LINKS_AS_EXTERNAL_LINKS print 'MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL = '.getDolGlobalString('MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; print '
'; print 'MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED = '.getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; print '
'; $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;"; print 'MAIN_SECURITY_FORCECSPRO = '.getDolGlobalString('MAIN_SECURITY_FORCECSPRO', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").': "'.$examplecsprule.'")
'; print '
'; $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;"; print 'MAIN_SECURITY_FORCECSP = '.getDolGlobalString('MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").': "'.$examplecsprule.'")
'; print '
'; print 'MAIN_SECURITY_FORCERP = '.getDolGlobalString('MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\" so browser doesn't send any referrer when going into another web site domain)
"; print '
'; print 'MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN = '.getDolGlobalString('MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").": 1)
"; print '
'; // For websites print 'WEBSITE_MAIN_SECURITY_FORCECSPRO = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSPRO', ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Example").': "'; $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; print $examplecsprule; print '")
'; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Example").': "'; $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; print $examplecsprule; print '")
'; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)
'; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
"; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
"; print '
'; print '
'; print load_fiche_titre($langs->trans("LimitsAndMitigation"), '', 'folder'); print '
'; print ''; print $langs->trans("RecommendMitigationOnURL").'
'; print '
'; print '
'; $urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/fail2ban/filter.d/'; print ' Login or API authentication (see fail2ban example on GitHub)
'; print ' '.DOL_URL_ROOT.'/passwordforgotten.php (see fail2ban example on GitHub)
'; print ' '.DOL_URL_ROOT.'/public/* (see fail2ban example on GitHub)
'; print '
'; $urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/apache/'; print ' You can also protect the application using a HTTP Basic authentication layer (see apache2 virtualhost example on GitHub)
'; print '
'; // End of page llxFooter(); $db->close();