From 6b93b973e2725fe2b2aee49171f7bd1c21a7f961 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Wed, 16 Oct 2013 08:54:39 +0200 Subject: [PATCH 1/4] add new directory-validator 'confdir' to check against disallowed paths (like /, /bin, /home, etc.) Signed-off-by: Michael Kaufmann (d00p) --- .../function.validateFormFieldString.php | 20 ++++++ .../settings/function.storeSettingField.php | 64 +++++++++---------- .../function.checkDisallowedPaths.php | 48 ++++++++++++++ lng/english.lng.php | 1 + lng/german.lng.php | 1 + 5 files changed, 100 insertions(+), 34 deletions(-) create mode 100644 lib/functions/validate/function.checkDisallowedPaths.php diff --git a/lib/functions/formfields/string/function.validateFormFieldString.php b/lib/functions/formfields/string/function.validateFormFieldString.php index f60499e9..4993ce61 100644 --- a/lib/functions/formfields/string/function.validateFormFieldString.php +++ b/lib/functions/formfields/string/function.validateFormFieldString.php @@ -68,6 +68,26 @@ function validateFormFieldString($fieldname, $fielddata, $newfieldvalue) $returnvalue = ($newfieldvalue == makeCorrectDir($newfieldvalue)); } } + elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'confdir') { + // check for empty value (it might be allowed) + if (trim($newfieldvalue) == '') { + $newfieldvalue = ''; + $returnvalue = 'stringmustntbeempty'; + } else { + // add trailing slash to validate path if needed + // refs #331 + if (substr($newfieldvalue, -1) != '/') { + $newfieldvalue.= '/'; + } + // if this is a configuration directory, check for stupidity of admins :p + if (checkDisallowedPaths($newfieldvalue) !== true) { + $newfieldvalue = ''; + $returnvalue = 'givendirnotallowed'; + } else { + $returnvalue = ($newfieldvalue == makeCorrectDir($newfieldvalue)); + } + } + } elseif (isset($fielddata['string_type']) && $fielddata['string_type'] == 'file') { // check for empty value (it might be allowed) if (trim($newfieldvalue) == '') { diff --git a/lib/functions/settings/function.storeSettingField.php b/lib/functions/settings/function.storeSettingField.php index 21bc7ccf..e3828043 100644 --- a/lib/functions/settings/function.storeSettingField.php +++ b/lib/functions/settings/function.storeSettingField.php @@ -17,62 +17,58 @@ * */ -function storeSettingField($fieldname, $fielddata, $newfieldvalue) -{ - if(is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') - { +function storeSettingField($fieldname, $fielddata, $newfieldvalue) { - if(saveSetting($fielddata['settinggroup'], $fielddata['varname'], $newfieldvalue) != false) - { + if (is_array($fielddata) + && isset($fielddata['settinggroup']) + && $fielddata['settinggroup'] != '' + && isset($fielddata['varname']) + && $fielddata['varname'] != '' + ) { + if (saveSetting($fielddata['settinggroup'], $fielddata['varname'], $newfieldvalue) != false) { /* * when fielddata[cronmodule] is set, this means enable/disable a cronjob - */ - if(isset($fielddata['cronmodule']) && $fielddata['cronmodule'] != '') - { + */ + if (isset($fielddata['cronmodule']) + && $fielddata['cronmodule'] != '' + ) { toggleCronStatus($fielddata['cronmodule'], $newfieldvalue); } /* * satisfy dependencies - */ - if(isset($fielddata['dependency']) && is_array($fielddata['dependency'])) - { - if((int)$fielddata['dependency']['onlyif'] == (int)$newfieldvalue) - { + */ + if (isset($fielddata['dependency']) + && is_array($fielddata['dependency']) + ) { + if ((int)$fielddata['dependency']['onlyif'] == (int)$newfieldvalue) { storeSettingField($fielddata['dependency']['fieldname'], $fielddata['dependency']['fielddata'], $newfieldvalue); } } return array($fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue); - } - else - { + } else { return false; } - } - else - { + } else { return false; } } -function storeSettingFieldInsertBindTask($fieldname, $fielddata, $newfieldvalue) -{ - if(is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] != '' && isset($fielddata['varname']) && $fielddata['varname'] != '') - { - if(saveSetting($fielddata['settinggroup'], $fielddata['varname'], $newfieldvalue) != false) - { +function storeSettingFieldInsertBindTask($fieldname, $fielddata, $newfieldvalue) { + + if (is_array($fielddata) + && isset($fielddata['settinggroup']) + && $fielddata['settinggroup'] != '' + && isset($fielddata['varname']) + && $fielddata['varname'] != '' + ) { + if (saveSetting($fielddata['settinggroup'], $fielddata['varname'], $newfieldvalue) != false) { return array($fielddata['settinggroup'] . '.' . $fielddata['varname'] => $newfieldvalue); - } - else - { + } else { return false; } - } - else - { + } else { return false; } } - -?> diff --git a/lib/functions/validate/function.checkDisallowedPaths.php b/lib/functions/validate/function.checkDisallowedPaths.php new file mode 100644 index 00000000..80422014 --- /dev/null +++ b/lib/functions/validate/function.checkDisallowedPaths.php @@ -0,0 +1,48 @@ + + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Functions + * + * @since 0.9.30 + * + */ + +/** + * checks a directory against disallowed paths which could + * lead to a damaged system if you use them + * + * @param string $fieldname + * @param array $fielddata + * @param mixed $newfieldvalue + * + * @return boolean|array + */ +function checkDisallowedPaths($path = null) { + + /* + * disallow base-directories and / + */ + $disallowed_values = array( + "/", "/bin/", "/boot/", "/dev/", "/etc/", "/home/", "/lib/", "/lib32/", "/lib64/", + "/opt/", "/proc/", "/root/", "/run/", "/sbin/", "/sys/", "/tmp/", "/usr/", "/var/" + ); + + $path = makeCorrectDir($path); + + // check if it's a disallowed path + if (in_array($path, $disallowed_values)) { + return false; + } + return true; +} diff --git a/lng/english.lng.php b/lng/english.lng.php index 244de80a..cde9455a 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1971,3 +1971,4 @@ $lng['admin']['selectserveralias_desc'] = 'Chose whether froxlor should create a $lng['domains']['serveraliasoption_wildcard'] = 'Wildcard (*.domain.tld)'; $lng['domains']['serveraliasoption_www'] = 'WWW (www.domain.tld)'; $lng['domains']['serveraliasoption_none'] = 'No alias'; +$lng['error']['givendirnotallowed'] = 'The given directory in field %s is not allowed.'; diff --git a/lng/german.lng.php b/lng/german.lng.php index 75b9fa55..bdf9ec4d 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1691,3 +1691,4 @@ $lng['admin']['selectserveralias_desc'] = 'Wählen Sie hier, ob für diese Domai $lng['domains']['serveraliasoption_wildcard'] = 'Wildcard (*.domain.tld)'; $lng['domains']['serveraliasoption_www'] = 'WWW (www.domain.tld)'; $lng['domains']['serveraliasoption_none'] = 'Kein alias'; +$lng['error']['givendirnotallowed'] = 'Das angegebene Verzeichnis im Feld %s ist nicht erlaubt.'; From 03ba127faba918f49792f7aeab1d9d994781dc9d Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Wed, 16 Oct 2013 16:23:10 +0200 Subject: [PATCH 2/4] use new directory-validator 'confdir'; fix if last ssl-ipport got deactivated and a security question is being asked Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/130.webserver.php | 4 ++-- actions/admin/settings/135.fcgid.php | 2 +- actions/admin/settings/136.phpfpm.php | 4 ++-- admin_domains.php | 2 ++ 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php index ece28bf4..a2a49ad3 100644 --- a/actions/admin/settings/130.webserver.php +++ b/actions/admin/settings/130.webserver.php @@ -81,7 +81,7 @@ return array( 'settinggroup' => 'system', 'varname' => 'apacheconf_htpasswddir', 'type' => 'string', - 'string_type' => 'dir', + 'string_type' => 'confdir', 'default' => '/etc/apache2/htpasswd/', 'save_method' => 'storeSettingField', ), @@ -99,7 +99,7 @@ return array( 'settinggroup' => 'system', 'varname' => 'customer_ssl_path', 'type' => 'string', - 'string_type' => 'dir', + 'string_type' => 'confdir', 'default' => '/etc/ssl/froxlor-custom/', 'save_method' => 'storeSettingField', ), diff --git a/actions/admin/settings/135.fcgid.php b/actions/admin/settings/135.fcgid.php index 6f10a217..0659fe08 100644 --- a/actions/admin/settings/135.fcgid.php +++ b/actions/admin/settings/135.fcgid.php @@ -36,7 +36,7 @@ return array( 'settinggroup' => 'system', 'varname' => 'mod_fcgid_configdir', 'type' => 'string', - 'string_type' => 'dir', + 'string_type' => 'confdir', 'default' => '/var/www/php-fcgi-scripts/', 'plausibility_check_method' => 'checkPathConflicts', 'save_method' => 'storeSettingField', diff --git a/actions/admin/settings/136.phpfpm.php b/actions/admin/settings/136.phpfpm.php index eae398b4..f5281268 100644 --- a/actions/admin/settings/136.phpfpm.php +++ b/actions/admin/settings/136.phpfpm.php @@ -79,7 +79,7 @@ return array( 'settinggroup' => 'phpfpm', 'varname' => 'configdir', 'type' => 'string', - 'string_type' => 'dir', + 'string_type' => 'confdir', 'default' => '/etc/php-fpm.d/', 'save_method' => 'storeSettingField', ), @@ -88,7 +88,7 @@ return array( 'settinggroup' => 'phpfpm', 'varname' => 'aliasconfigdir', 'type' => 'string', - 'string_type' => 'dir', + 'string_type' => 'confdir', 'default' => '/var/www/php-fpm/', 'save_method' => 'storeSettingField', ), diff --git a/admin_domains.php b/admin_domains.php index 04f8944b..6ac99a16 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -1065,6 +1065,8 @@ if($page == 'domains' if (isset($_POST['ssl_ipandport']) && is_array($_POST['ssl_ipandport'])) { foreach ($_POST['ssl_ipandport'] as $ssl_ipandport) { if (trim($ssl_ipandport) == "") continue; + // fix if ip/port got de-checked and it was the last one + if (trim($ssl_ipandport) < 1) continue; $ssl_ipandport = intval($ssl_ipandport); $ssl_ipandport_check = $db->query_first("SELECT `id`, `ip`, `port` FROM `" . TABLE_PANEL_IPSANDPORTS . "` WHERE `id` = '" . $db->escape($ssl_ipandport) . "' "); if (!isset($ssl_ipandport_check['id']) From 729b52cf0aff2626be3a51517caf14ad9fda825e Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sat, 19 Oct 2013 18:47:02 +0200 Subject: [PATCH 3/4] outsource check for open support-tickets to init.php so that themes may display the info wherever they want Signed-off-by: Michael Kaufmann (d00p) --- admin_index.php | 12 ------------ customer_index.php | 12 ------------ lib/init.php | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/admin_index.php b/admin_index.php index c2623832..3c52fd7d 100644 --- a/admin_index.php +++ b/admin_index.php @@ -148,18 +148,6 @@ if($page == 'overview') $cron_last_runs = getCronjobsLastRun(); $outstanding_tasks = getOutstandingTasks(); - $opentickets = 0; - $opentickets = $db->query_first('SELECT COUNT(`id`) as `count` FROM `' . TABLE_PANEL_TICKETS . '` - WHERE `answerto` = "0" AND (`status` = "0" OR `status` = "1") - AND `lastreplier`="0" AND `adminid` = "' . $userinfo['adminid'] . '"'); - $awaitingtickets = $opentickets['count']; - $awaitingtickets_text = ''; - - if($opentickets > 0) - { - $awaitingtickets_text = strtr($lng['ticket']['awaitingticketreply'], array('%s' => '' . $opentickets['count'] . '')); - } - if(function_exists('sys_getloadavg')) { $loadArray = sys_getloadavg(); diff --git a/customer_index.php b/customer_index.php index 571c1774..f07fb20d 100644 --- a/customer_index.php +++ b/customer_index.php @@ -60,18 +60,6 @@ if ($page == 'overview') { $userinfo['traffic'] = round($userinfo['traffic'] / (1024 * 1024), $settings['panel']['decimal_places']); $userinfo['traffic_used'] = round($userinfo['traffic_used'] / (1024 * 1024), $settings['panel']['decimal_places']); $userinfo = str_replace_array('-1', $lng['customer']['unlimited'], $userinfo, 'diskspace traffic mysqls emails email_accounts email_forwarders email_quota email_autoresponder ftps tickets subdomains aps_packages'); - $opentickets = 0; - $opentickets = $db->query_first('SELECT COUNT(`id`) as `count` FROM `' . TABLE_PANEL_TICKETS . '` - WHERE `customerid` = "' . $userinfo['customerid'] . '" - AND `answerto` = "0" - AND (`status` = "0" OR `status` = "2") - AND `lastreplier`="1"'); - $awaitingtickets = $opentickets['count']; - $awaitingtickets_text = ''; - - if ($opentickets > 0) { - $awaitingtickets_text = strtr($lng['ticket']['awaitingticketreply'], array('%s' => '' . $opentickets['count'] . '')); - } eval("echo \"" . getTemplate('index/index') . "\";"); } elseif ($page == 'change_password') { diff --git a/lib/init.php b/lib/init.php index 1c6598c3..4474304e 100644 --- a/lib/init.php +++ b/lib/init.php @@ -431,6 +431,40 @@ if (AREA == 'admin' || AREA == 'customer') { unset($navigation_data); } +/** + * header information about open tickets (only if used) + */ +if ($settings['ticket']['enabled'] == '1') { + $awaitingtickets = 0; + $awaitingtickets_text = ''; + $opentickets = 0; + + if (AREA == 'admin' && isset($userinfo['adminid'])) { + $opentickets = $db->query_first(' + SELECT COUNT(`id`) as `count` FROM `' . TABLE_PANEL_TICKETS . '` + WHERE `answerto` = "0" AND (`status` = "0" OR `status` = "1") + AND `lastreplier`="0" AND `adminid` = "' . $userinfo['adminid'] . '" + '); + $awaitingtickets = $opentickets['count']; + + if ($opentickets > 0) { + $awaitingtickets_text = strtr($lng['ticket']['awaitingticketreply'], array('%s' => '' . $opentickets['count'] . '')); + } + } + elseif (AREA == 'customer' && isset($userinfo['customerid'])) { + $opentickets = $db->query_first(' + SELECT COUNT(`id`) as `count` FROM `' . TABLE_PANEL_TICKETS . '` + WHERE `answerto` = "0" AND (`status` = "0" OR `status` = "2") + AND `lastreplier`="1" AND `customerid` = "' . $userinfo['customerid'] . '" + '); + $awaitingtickets = $opentickets['count']; + + if ($opentickets > 0) { + $awaitingtickets_text = strtr($lng['ticket']['awaitingticketreply'], array('%s' => '' . $opentickets['count'] . '')); + } + } +} + $webfont = str_replace('+', ' ', $settings['panel']['webfont']); eval("\$header = \"" . getTemplate('header', '1') . "\";"); From cb556093c12d97afc74e407cc3c7c9366026eb6e Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sat, 19 Oct 2013 18:48:08 +0200 Subject: [PATCH 4/4] fix undefined language indeces (add english as fallback as intented in case a string is not defined in the used language) Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_usage.inc.diskspace.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/jobs/cron_usage.inc.diskspace.php b/scripts/jobs/cron_usage.inc.diskspace.php index e6a48726..2c3db743 100644 --- a/scripts/jobs/cron_usage.inc.diskspace.php +++ b/scripts/jobs/cron_usage.inc.diskspace.php @@ -49,20 +49,24 @@ while($row = $db->fetch_array($result)) 'MAX_PERCENT' => $settings['system']['report_webmax'] ); - $lngfile = $db->query_first("SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "` - WHERE `language` ='" . $row['def_language'] . "'"); + $lngfile = $db->query_first(" + SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "` + WHERE `language` ='" . $row['def_language'] . "' + "); - if($lngfile !== NULL) - { + if ($lngfile !== null) { $langfile = $lngfile['file']; - } - else - { - $lngfile = $db->query_first("SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "` - WHERE `language` ='" . $settings['panel']['standardlanguage'] . "'"); + } else { + $lngfile = $db->query_first(" + SELECT `file` FROM `" . TABLE_PANEL_LANGUAGE . "` + WHERE `language` ='" . $settings['panel']['standardlanguage'] . "' + "); $langfile = $lngfile['file']; } + // include english language file (fallback) + include_once makeCorrectFile($pathtophpfiles . '/lng/english.lng.php'); + // include admin/customer language file include_once makeCorrectFile($pathtophpfiles . '/' . $langfile); // Get mail templates from database; the ones from 'admin' are fetched for fallback