diff --git a/htdocs/admin/security_file.php b/htdocs/admin/security_file.php
index 53c2761b4b0..42ade68a31f 100644
--- a/htdocs/admin/security_file.php
+++ b/htdocs/admin/security_file.php
@@ -166,7 +166,7 @@ if (isset($max)) {
}
print '';
print '
';
-print ' '.$langs->trans("Kb");
+print ' '.$langs->trans("Kb");
print ' | ';
print '';
@@ -176,7 +176,7 @@ print '';
print $form->textwithpicto($langs->trans("UMask"), $langs->trans("UMaskExplanation"));
print ' | ';
print '';
-print '';
+print '';
print ' | ';
print '';
@@ -197,7 +197,7 @@ if (ini_get('safe_mode') && getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) {
dol_syslog("safe_mode is on, basedir is ".$basedir.", safe_mode_exec_dir is ".ini_get('safe_mode_exec_dir'), LOG_WARNING);
}
}
-print '';
+print '';
if (defined('MAIN_ANTIVIRUS_COMMAND') && !defined('MAIN_ANTIVIRUS_BYPASS_COMMAND_AND_PARAM')) {
print '
'.$langs->trans("ValueIsForcedBySystem").'';
}
@@ -211,7 +211,7 @@ print ''.$langs->trans("AntiVirusParam").' ';
print ''.$langs->trans("AntiVirusParamExample").'';
print ' | ';
print '';
-print '';
+print '';
if (defined('MAIN_ANTIVIRUS_PARAM')) {
print ' '.$langs->trans("ValueIsForcedBySystem").'';
}
@@ -223,7 +223,7 @@ print ' | '.$langs->trans("UploadExtensionRestriction").' ';
print ''.$langs->trans("UploadExtensionRestrictionExemple").'';
print ' | ';
print '';
-print '';
+print '';
print " | ";
print '';
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index 3e374c9d9aa..5e203d08aff 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -461,6 +461,9 @@ 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 '
';
+
+// Clear password ?
+
print ''.$langs->trans("DoNotStoreClearPassword").': ';
print !getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? '' : img_picto('', 'tick').' ';
print yn(!getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 0 : 1);
@@ -470,6 +473,22 @@ if (!getDolGlobalString('DATABASE_PWD_ENCRYPTED')) {
print '
';
print '
';
+
+// Mask by default in upload
+$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 '
';
+
+
/* Already into section conf file */
/*
$usepassinconfencrypted = 0;
@@ -516,20 +535,16 @@ if (!getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) {
print '
';
print '
';
-$umask = getDolGlobalString('MAIN_UMASK');
+// File extension locked in upload by default
-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 ''.$langs->trans("UploadExtensionRestriction").': ';
+print implode(', ', explode(',', getDolGlobalString('MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION')));
+print ' ('.$langs->trans("Recommended").': '.implode(', ', getExecutableContent()).')';
print '
';
print '
';
+
$securityevent = new Events($db);
$eventstolog = $securityevent->eventstolog;
@@ -602,7 +617,6 @@ if (!$test) {
}
print '
';
-
// Modules for Payments
$test = isModEnabled('stripe');
if ($test) {
@@ -664,6 +678,8 @@ print '
';
print '
';
+// Other setup
+
print load_fiche_titre($langs->trans("OtherSetup"), '', 'folder');
print '';
@@ -681,11 +697,9 @@ print 'MAIN_SECURITY_CSRF_WITH_TOKEN = '.getDolGlobalString('MA
print '
';
-
print '
';
print '
';
-
print load_fiche_titre($langs->trans("DatabaseEncryption"), '', 'folder');
print '';
@@ -734,51 +748,59 @@ print '
';
print '
';
print '
';
+
// Websites
-print load_fiche_titre($langs->trans("Website"), '', 'website');
-print '';
+if (isModEnabled('website')) {
+ print load_fiche_titre($langs->trans("Website"), '', 'website');
+ print '
';
-$sql = "SELECT w.rowid as id, w.ref";
-$sql .= " FROM ".MAIN_DB_PREFIX."website as w";
-$sql .= " WHERE w.entity = ".((int) $conf->entity);
-$sql .= " AND w.status = 1";
+ $sql = "SELECT w.rowid as id, w.ref";
+ $sql .= " FROM ".MAIN_DB_PREFIX."website as w";
+ $sql .= " WHERE w.entity = ".((int) $conf->entity);
+ $sql .= " AND w.status = 1";
-$resql = $db->query($sql);
-if ($resql) {
- $num_rows = $db->num_rows($resql);
- if ($num_rows > 0) {
- $i = 0;
- while ($obj = $db->fetch_object($resql)) {
- print "".$langs->trans("RefWebsite").": ".$obj->ref."";
- print'
';
- print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$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 '")
';
+ $resql = $db->query($sql);
+ if ($resql) {
+ $num_rows = $db->num_rows($resql);
+ if ($num_rows > 0) {
+ $i = 0;
+ while ($obj = $db->fetch_object($resql)) {
+ print "".$langs->trans("RefWebsite").": ".$obj->ref."";
+ print'
';
+ print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$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 'WEBSITE_'.$obj->id.'_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_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 'WEBSITE_'.$obj->id.'_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_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 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)
';
+ print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)
';
- print 'WEBSITE_'.$obj->id.'_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
+ print 'WEBSITE_'.$obj->id.'_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
- print 'WEBSITE_'.$obj->id.'_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
";
- $i++;
- if ($i != $num_rows) {
- print '
';
+ print 'WEBSITE_'.$obj->id.'_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
";
+ $i++;
+ if ($i != $num_rows) {
+ print '
';
+ }
}
+ } else {
+ print ''.$langs->trans("NoWebsite").'';
}
+ } else {
+ dol_print_error($db);
}
-} else {
- dol_print_error($db);
+ print '
';
+
+
+ print '
';
}
-print '
';
// Other - experimental
@@ -790,7 +812,7 @@ print 'MAIN_EXEC_USE_POPEN = ';
if (!getDolGlobalString('MAIN_EXEC_USE_POPEN')) {
print ''.$langs->trans("Undefined").'';
} else {
- print $conf->global->MAIN_EXEC_USE_POPEN;
+ print getDolGlobalString('MAIN_EXEC_USE_POPEN');
}
if ($execmethod == 1) {
print ' "exec" PHP method will be used for shell commands';
@@ -869,6 +891,11 @@ 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 '
';
+print 'MAIN_DISALLOW_STRING_OBFUSCATION_IN_DOL_EVAL = '.(getDolGlobalString('MAIN_DISALLOW_STRING_OBFUSCATION_IN_DOL_EVAL') ? '1' : ''.$langs->trans("Undefined").'');
+print ' ('.$langs->trans("Recommended").": 1 - may break use of concatenation function like . or dol_concatdesc into extra fields conditions or formula)
";
+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)')."
";
@@ -889,9 +916,11 @@ print 'MAIN_SECURITY_FORCERP = '.getDolGlobalString('MAIN_SECUR
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 '
';
+/* Removed, already in the dedicated section Websites.
+print '
';
+
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:;";
@@ -913,10 +942,12 @@ print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('W
print '
';
print 'WEBSITE_MAIN_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
";
+*/
print '';
+print '
';
print '
';
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index 1a71d9d6c55..bf0652760f4 100644
--- a/htdocs/core/lib/files.lib.php
+++ b/htdocs/core/lib/files.lib.php
@@ -1972,11 +1972,13 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $updatesessionor
$info = pathinfo($destfile);
$destfile = dol_sanitizeFileName($info['filename'].($info['extension'] != '' ? ('.'.strtolower($info['extension'])) : ''));
- $fileextensionrestriction = getDolGlobalString("MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION", 'htm,html,shtml,js,php');
- if (!empty($info['extension']) && !empty($fileextensionrestriction)) {
- $fileextensionrestrictionarr = explode(",", $fileextensionrestriction);
- foreach ($fileextensionrestrictionarr as $key => $fileextension) {
- if (preg_match('/'.preg_quote($fileextension, '/').'/i', $info['extension'])) {
+ // Check extension is allowed for upload
+ $fileextensionrestriction = getDolGlobalString("MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION", implode(',', getExecutableContent()));
+ if (!empty($fileextensionrestriction)) {
+ $arrayofregexextension = explode(",", $fileextensionrestriction);
+
+ foreach ($arrayofregexextension as $fileextension) {
+ if (preg_match('/\.'.preg_quote(trim($fileextension), '/').'$/i', $destfull)) {
$langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now.
setEventMessages($langs->trans("ErrorFilenameExtensionNotAllowed", $filenameto), null, 'errors');
return -1;
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index d966af8305c..ae2f9eb3a4f 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -14118,16 +14118,35 @@ function fetchObjectByElement($element_id, $element_type, $element_ref = '', $us
return $ret;
}
+/**
+ * Return array of extension for executable files of text files that can contains executable code.
+ *
+ * @return array Array of extensions
+ */
+function getExecutableContent()
+{
+ $arrayofregexextension = array(
+ 'htm', 'html', 'shtml', 'js', 'phar', 'php', 'php3', 'php4', 'php5', 'phtml', 'pht', 'pl', 'py', 'cgi', 'ksh', 'sh', 'shtml',
+ 'bash', 'bat', 'cmd', 'wpk', 'exe', 'dmg', 'appimage'
+ );
+
+ return $arrayofregexextension;
+}
+
/**
* Return if a file can contains executable content
*
- * @param string $filename File name to test
- * @return boolean True if yes, False if no
+ * @param string $filename File name to test
+ * @return boolean True if yes, False if no
*/
function isAFileWithExecutableContent($filename)
{
- if (preg_match('/\.(htm|html|js|phar|php|php\d+|phtml|pht|pl|py|cgi|ksh|sh|shtml|bash|bat|cmd|wpk|exe|dmg)$/i', $filename)) {
- return true;
+ $arrayofregexextension = getExecutableContent();
+
+ foreach ($arrayofregexextension as $fileextension) {
+ if (preg_match('/\.'.preg_quote($fileextension, '/').'$/i', $filename)) {
+ return true;
+ }
}
return false;