From 97d035eee9d8f24572fb32e9e800f097a9ba76f8 Mon Sep 17 00:00:00 2001 From: FliegenKLATSCH Date: Sat, 30 Apr 2016 17:24:11 +0200 Subject: [PATCH 01/62] fix group by clause to be be compliant with mysql 5.7 --- customer_domains.php | 2 +- customer_traffic.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/customer_domains.php b/customer_domains.php index 6849c0e8..7cb60472 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -730,7 +730,7 @@ if ($page == 'overview') { AND `dip`.`id_ipandports` IN (SELECT `id_ipandports` FROM `".TABLE_DOMAINTOIP."` WHERE `id_domain` = :id) - GROUP BY `d`.`domain` + GROUP BY `d`.`id`, `d`.`domain` ORDER BY `d`.`domain` ASC" ); Database::pexecute($domains_stmt, array("id" => $result['id'], "customerid" => $userinfo['customerid'])); diff --git a/customer_traffic.php b/customer_traffic.php index 8b3aaf17..abca00b0 100644 --- a/customer_traffic.php +++ b/customer_traffic.php @@ -115,8 +115,7 @@ if (!is_null($month) && !is_null($year)) { $result_stmt = Database::prepare("SELECT `month`, `year`, SUM(`http`) AS http, SUM(`ftp_up`) AS ftp_up, SUM(`ftp_down`) AS ftp_down, SUM(`mail`) AS mail FROM `" . TABLE_PANEL_TRAFFIC . "` WHERE `customerid` = :customerid - GROUP BY CONCAT(`year`,`month`) - ORDER BY CONCAT(`year`,`month`) DESC + GROUP BY `year` DESC, `month` DESC LIMIT 12" ); Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'])); From 2e198dbe5cda1ad74ad7904e0c4d63551241c11d Mon Sep 17 00:00:00 2001 From: FliegenKLATSCH Date: Sun, 1 May 2016 18:01:05 +0200 Subject: [PATCH 02/62] fix default value for domain reg./term. date --- admin_domains.php | 12 ++++++++++++ install/froxlor.sql | 8 ++++---- install/updates/froxlor/0.9/update_0.9.inc.php | 11 +++++++++++ lib/version.inc.php | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index 0e7d4fbd..5bddacd1 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -393,6 +393,9 @@ if ($page == 'domains' || $page == 'overview') { '0', '' )); + if ($registration_date == '0000-00-00') { + $registration_date = null; + } $termination_date = trim($_POST['termination_date']); $termination_date = validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( @@ -400,6 +403,9 @@ if ($page == 'domains' || $page == 'overview') { '0', '' )); + if ($termination_date == '0000-00-00') { + $termination_date = null; + } if ($userinfo['change_serversettings'] == '1') { @@ -1206,12 +1212,18 @@ if ($page == 'domains' || $page == 'overview') { '0', '' )); + if ($registration_date == '0000-00-00') { + $registration_date = null; + } $termination_date = trim($_POST['termination_date']); $termination_date = validate($termination_date, 'termination_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array( '0000-00-00', '0', '' )); + if ($termination_date == '0000-00-00') { + $termination_date = null; + } $isemaildomain = 0; if (isset($_POST['isemaildomain'])) { diff --git a/install/froxlor.sql b/install/froxlor.sql index f30c943a..cd6daeb7 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -66,7 +66,7 @@ CREATE TABLE `mail_virtual` ( `id` int(11) NOT NULL auto_increment, `email` varchar(255) NOT NULL default '', `email_full` varchar(255) NOT NULL default '', - `destination` text NOT NULL, + `destination` text NOT NULL default '', `domainid` int(11) NOT NULL default '0', `customerid` int(11) NOT NULL default '0', `popaccountid` int(11) NOT NULL default '0', @@ -245,8 +245,8 @@ CREATE TABLE `panel_domains` ( `deactivated` tinyint(1) NOT NULL default '0', `bindserial` varchar(10) NOT NULL default '2000010100', `add_date` int( 11 ) NOT NULL default '0', - `registration_date` date NOT NULL, - `termination_date` date NOT NULL, + `registration_date` date DEFAULT NULL, + `termination_date` date DEFAULT NULL, `phpsettingid` INT( 11 ) UNSIGNED NOT NULL DEFAULT '1', `mod_fcgid_starter` int(4) default '-1', `mod_fcgid_maxrequests` int(4) default '-1', @@ -573,7 +573,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'version', '0.9.37'), - ('panel', 'db_version', '201609200'); + ('panel', 'db_version', '201609240'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 7da2b984..de3c2de8 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3475,3 +3475,14 @@ if (isDatabaseVersion('201609120')) { updateToDbVersion('201609200'); } + +if (isDatabaseVersion('201609200')) { + + showUpdateStep("Changing tables to be more mysql strict-mode compatible"); + Database::query("ALTER TABLE `".TABLE_MAIL_VIRTUAL."` CHANGE `destination` `destination` TEXT NOT NULL DEFAULT '';"); + Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `registration_date` `registration_date` DATE NULL DEFAULT NULL;"); + Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `termination_date` `termination_date` DATE NULL DEFAULT NULL;"); + lastStepStatus(0); + + updateToDbVersion('201609240'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index 8a1d56d3..6f16ab32 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.9.37'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201609200'; +$dbversion = '201609240'; // Distribution branding-tag (used for Debian etc.) $branding = ''; From 4a3e02c1f0f92c3fbb32ef0bef46b030e744ae71 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 7 Oct 2016 11:01:45 +0200 Subject: [PATCH 03/62] add HSTS for domains (admin-side) and froxlor-vhost; fixes #1660 Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/131.ssl.php | 28 +- install/froxlor.sql | 2 +- .../updates/froxlor/0.9/update_0.9.inc.php | 27 +- lib/classes/output/class.htmlform.php | 27 + .../admin/domains/formfield.domains_add.php | 104 +++- .../admin/domains/formfield.domains_edit.php | 104 +++- lib/init.php | 23 +- lib/version.inc.php | 2 +- lng/english.lng.php | 9 +- lng/german.lng.php | 9 +- .../jobs/cron_tasks.inc.http.10.apache.php | 2 +- .../jobs/cron_tasks.inc.http.20.lighttpd.php | 2 +- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 589 +++++++++--------- 13 files changed, 534 insertions(+), 394 deletions(-) diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index 56c27cd5..dc03f926 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -153,7 +153,33 @@ return array( 'type' => 'bool', 'default' => false, 'save_method' => 'storeSettingField' - ) + ), + 'system_hsts_maxage' => array( + 'label' => $lng['admin']['domain_hsts_maxage'], + 'settinggroup' => 'system', + 'varname' => 'hsts_maxage', + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'default' => 0, + 'save_method' => 'storeSettingField' + ), + 'system_hsts_incsub' => array( + 'label' => $lng['admin']['domain_hsts_incsub'], + 'settinggroup' => 'system', + 'varname' => 'hsts_incsub', + 'type' => 'bool', + 'default' => false, + 'save_method' => 'storeSettingField' + ), + 'system_hsts_preload' => array( + 'label' => $lng['admin']['domain_hsts_preload'], + 'settinggroup' => 'system', + 'varname' => 'hsts_preload', + 'type' => 'bool', + 'default' => false, + 'save_method' => 'storeSettingField' + ), ) ) ) diff --git a/install/froxlor.sql b/install/froxlor.sql index cd6daeb7..63ce8661 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -573,7 +573,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'version', '0.9.37'), - ('panel', 'db_version', '201609240'); + ('panel', 'db_version', '201610070'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index de3c2de8..66fea160 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3478,11 +3478,26 @@ if (isDatabaseVersion('201609120')) { if (isDatabaseVersion('201609200')) { - showUpdateStep("Changing tables to be more mysql strict-mode compatible"); - Database::query("ALTER TABLE `".TABLE_MAIL_VIRTUAL."` CHANGE `destination` `destination` TEXT NOT NULL DEFAULT '';"); - Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `registration_date` `registration_date` DATE NULL DEFAULT NULL;"); - Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `termination_date` `termination_date` DATE NULL DEFAULT NULL;"); - lastStepStatus(0); + showUpdateStep("Changing tables to be more mysql strict-mode compatible"); + Database::query("ALTER TABLE `".TABLE_MAIL_VIRTUAL."` CHANGE `destination` `destination` TEXT NOT NULL DEFAULT '';"); + Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `registration_date` `registration_date` DATE NULL DEFAULT NULL;"); + Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` CHANGE `termination_date` `termination_date` DATE NULL DEFAULT NULL;"); + lastStepStatus(0); - updateToDbVersion('201609240'); + updateToDbVersion('201609240'); +} + +if (isDatabaseVersion('201609240')) { + + showUpdateStep("Add HSTS settings for froxlor-vhost"); + Settings::AddNew("system.hsts_maxage", 0); + Settings::AddNew("system.hsts_incsub", 0); + Settings::AddNew("system.hsts_preload", 0); + lastStepStatus(0); + + showUpdateStep("Settings HSTS default values for all domains (deactivated)"); + Database::query("UPDATE `".TABLE_PANEL_DOMAINS."` SET `hsts_sub` = '0', `hsts_preload` = '0';"); + lastStepStatus(0); + + updateToDbVersion('201610070'); } diff --git a/lib/classes/output/class.htmlform.php b/lib/classes/output/class.htmlform.php index 2bc6edca..6f1c4a3b 100644 --- a/lib/classes/output/class.htmlform.php +++ b/lib/classes/output/class.htmlform.php @@ -122,6 +122,8 @@ class htmlform return self::_checkbox($fieldname, $data); break; case 'file': return self::_file($fieldname, $data); break; + case 'int': + return self::_int($fieldname, $data); break; } } @@ -313,4 +315,29 @@ class htmlform return $return; } + private static function _int($fieldname = '', $data = array()) + { + $return = ''; + $extras = ''; + if(isset($data['int_min'])) { + $extras .= ' min="'.$data['int_min'].'"'; + } + if(isset($data['int_max'])) { + $extras .= ' max="'.$data['int_max'].'"'; + } + + // add support to save reloaded forms + if (isset($data['value'])) { + $value = $data['value']; + } elseif (isset($_SESSION['requestData'][$fieldname])) { + $value = $_SESSION['requestData'][$fieldname]; + } else { + $value = ''; + } + + $type = 'number'; + $ulfield = ''; + eval("\$return = \"" . getTemplate("misc/form/input_text", "1") . "\";"); + return $return; + } } diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index c85d6500..15ca70e4 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -101,40 +101,6 @@ return array( 'is_array' => 1, 'mandatory' => true ), - 'ssl_ipandport' => array( - 'label' => $lng['domains']['ipandport_ssl_multi']['title'], - 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], - 'type' => 'checkbox', - 'values' => $ssl_ipsandports, - 'value' => '', - 'is_array' => 1 - ), - 'ssl_redirect' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), - 'label' => $lng['domains']['ssl_redirect']['title'], - 'desc' => $lng['domains']['ssl_redirect']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array() - ), - 'letsencrypt' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false) : false), - 'label' => $lng['admin']['letsencrypt']['title'], - 'desc' => $lng['admin']['letsencrypt']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array() - ), - 'no_ssl_available_info' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports == '' ? true : false) : false), - 'label' => 'SSL', - 'type' => 'label', - 'value' => $lng['panel']['nosslipsavailable'] - ), 'selectserveralias' => array( 'label' => $lng['admin']['selectserveralias'], 'desc' => $lng['admin']['selectserveralias_desc'], @@ -161,6 +127,76 @@ return array( ) ) ), + 'section_bssl' => array( + 'title' => $lng['admin']['webserversettings_ssl'], + 'image' => 'icons/domain_add.png', + 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'fields' => array( + 'ssl_ipandport' => array( + 'label' => $lng['domains']['ipandport_ssl_multi']['title'], + 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], + 'type' => 'checkbox', + 'values' => $ssl_ipsandports, + 'value' => '', + 'is_array' => 1 + ), + 'ssl_redirect' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['domains']['ssl_redirect']['title'], + 'desc' => $lng['domains']['ssl_redirect']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'letsencrypt' => array( + 'visible' => (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), + 'label' => $lng['admin']['letsencrypt']['title'], + 'desc' => $lng['admin']['letsencrypt']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'no_ssl_available_info' => array( + 'visible' => ($ssl_ipsandports == '' ? true : false), + 'label' => 'SSL', + 'type' => 'label', + 'value' => $lng['panel']['nosslipsavailable'] + ), + 'hsts_maxage' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_maxage']['title'], + 'desc' => $lng['admin']['domain_hsts_maxage']['description'], + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'value' => 0 + ), + 'hsts_incsub' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_incsub']['title'], + 'desc' => $lng['admin']['domain_hsts_incsub']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'hsts_preload' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_preload']['title'], + 'desc' => $lng['admin']['domain_hsts_preload']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + ), + ), 'section_c' => array( 'title' => $lng['admin']['phpserversettings'], 'image' => 'icons/domain_add.png', diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 6837da0a..11b6c6bc 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -113,40 +113,6 @@ return array( 'is_array' => 1, 'mandatory' => true ), - 'ssl_ipandport' => array( - 'label' => $lng['domains']['ipandport_ssl_multi']['title'], - 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], - 'type' => 'checkbox', - 'values' => $ssl_ipsandports, - 'value' => $usedips, - 'is_array' => 1 - ), - 'ssl_redirect' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), - 'label' => $lng['domains']['ssl_redirect']['title'], - 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''), - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array($result['ssl_redirect']) - ), - 'letsencrypt' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false) : false), - 'label' => $lng['admin']['letsencrypt']['title'], - 'desc' => $lng['admin']['letsencrypt']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array($result['letsencrypt']) - ), - 'no_ssl_available_info' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports == '' ? true : false) : false), - 'label' => 'SSL', - 'type' => 'label', - 'value' => $lng['panel']['nosslipsavailable'] - ), 'selectserveralias' => array( 'label' => $lng['admin']['selectserveralias'], 'desc' => $lng['admin']['selectserveralias_desc'], @@ -184,6 +150,76 @@ return array( ) ) ), + 'section_bssl' => array( + 'title' => $lng['admin']['webserversettings_ssl'], + 'image' => 'icons/domain_edit.png', + 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'fields' => array( + 'ssl_ipandport' => array( + 'label' => $lng['domains']['ipandport_ssl_multi']['title'], + 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], + 'type' => 'checkbox', + 'values' => $ssl_ipsandports, + 'value' => $usedips, + 'is_array' => 1 + ), + 'ssl_redirect' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['domains']['ssl_redirect']['title'], + 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''), + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['ssl_redirect']) + ), + 'letsencrypt' => array( + 'visible' => (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), + 'label' => $lng['admin']['letsencrypt']['title'], + 'desc' => $lng['admin']['letsencrypt']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['letsencrypt']) + ), + 'no_ssl_available_info' => array( + 'visible' => ($ssl_ipsandports == '' ? true : false), + 'label' => 'SSL', + 'type' => 'label', + 'value' => $lng['panel']['nosslipsavailable'] + ), + 'hsts_maxage' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_maxage']['title'], + 'desc' => $lng['admin']['domain_hsts_maxage']['description'], + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'value' => $result['hsts'] + ), + 'hsts_incsub' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_incsub']['title'], + 'desc' => $lng['admin']['domain_hsts_incsub']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['hsts_sub']) + ), + 'hsts_preload' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_preload']['title'], + 'desc' => $lng['admin']['domain_hsts_preload']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['hsts_preload']) + ), + ) + ), 'section_c' => array( 'title' => $lng['admin']['phpserversettings'], 'image' => 'icons/domain_edit.png', diff --git a/lib/init.php b/lib/init.php index 1c116a2c..b4e4c018 100644 --- a/lib/init.php +++ b/lib/init.php @@ -39,11 +39,6 @@ header("X-XSS-Protection: 1; mode=block"); // Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking header("X-Frame-Options: DENY"); -// If Froxlor was called via HTTPS -> enforce it for the next time -if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { - header("Strict-Transport-Security: max-age=15768000"); -} - // Internet Explorer shall not guess the Content-Type, see: // http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx header("X-Content-Type-Options: nosniff"); @@ -127,6 +122,24 @@ require FROXLOR_INSTALL_DIR.'/lib/tables.inc.php'; */ $idna_convert = new idna_convert_wrapper(); +/** + * If Froxlor was called via HTTPS -> enforce it for the next time by settings HSTS header according to settings + */ +if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { + $maxage = Settings::Get('system.hsts_maxage'); + if (empty($maxage)) { + $maxage = 0; + } + $hsts_header = "Strict-Transport-Security: max-age=".$maxage; + if (Settings::Get('system.hsts_incsub') == '1') { + $hsts_header .= "; includeSubDomains"; + } + if (Settings::Get('system.hsts_preload') == '1') { + $hsts_header .= "; preload"; + } + header($hsts_header); +} + /** * disable magic_quotes_runtime if enabled */ diff --git a/lib/version.inc.php b/lib/version.inc.php index 6f16ab32..52a85722 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.9.37'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201609240'; +$dbversion = '201610070'; // Distribution branding-tag (used for Debian etc.) $branding = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 6859fd06..036cf118 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2027,7 +2027,7 @@ $lng['error']['dns_record_toolong'] = 'Records/labels can only be up to 63 chara $lng['serversettings']['panel_customer_hide_options']['title'] = 'Hide menu items and traffic charts in customer panel'; $lng['serversettings']['panel_customer_hide_options']['description'] = 'Select items to hide in customer panel. To select multiple options, hold down CTRL while selecting.'; -// Added in froxlor 0.9.37.1 +// Added in froxlor 0.9.38-rc1 $lng['serversettings']['allow_allow_customer_shell']['title'] = 'Allow customers to enable shell access for ftp-users'; $lng['serversettings']['allow_allow_customer_shell']['description'] = 'Please note: Shell access allows the user to execute various binaries on your system. Use with extrem caution. Please only activate this if you REALLY know what you are doing!!!'; $lng['serversettings']['available_shells']['title'] = 'List of available shells'; @@ -2055,3 +2055,10 @@ $lng['domains']['ssl_certificates'] = 'SSL certificates'; $lng['domains']['ssl_certificate_removed'] = 'The certificate with the id #%s has been removed successfully'; $lng['domains']['ssl_certificate_error'] = "Error reading certificate for domain: %s"; $lng['domains']['no_ssl_certificates'] = "There are no domains with SSL certificate"; +$lng['admin']['webserversettings_ssl'] = 'Webserver SSL settings'; +$lng['admin']['domain_hsts_maxage']['title'] = 'HTTP Strict Transport Security (HSTS)'; +$lng['admin']['domain_hsts_maxage']['description'] = 'Specify the max-age value for the Strict-Transport-Security header
The value 0 will disable HSTS for the domain. Most user set a value of 31536000 (one year).'; +$lng['admin']['domain_hsts_incsub']['title'] = 'Include HSTS for any subdomain'; +$lng['admin']['domain_hsts_incsub']['description'] = 'The optional "includeSubDomains" directive, if present, signals the UA that the HSTS Policy applies to this HSTS Host as well as any subdomains of the host\'s domain name.'; +$lng['admin']['domain_hsts_preload']['title'] = 'Include domain in HSTS preload list'; +$lng['admin']['domain_hsts_preload']['description'] = 'If you would like this domain to be included in the HSTS preload list maintained by Chrome (and used by Firefox and Safari), then use activate this.
Sending the preload directive from your site can have PERMANENT CONSEQUENCES and prevent users from accessing your site and any of its subdomains.
Please read the details at hstspreload.appspot.com/#removal before sending the header with "preload".'; diff --git a/lng/german.lng.php b/lng/german.lng.php index fc6d9489..0af16748 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1679,7 +1679,7 @@ $lng['error']['dns_record_toolong'] = 'Records/Labels können maximal 63 Zeichen $lng['serversettings']['panel_customer_hide_options']['title'] = 'Menüpunkte und Traffic-Charts im Kundenbereich ausblenden'; $lng['serversettings']['panel_customer_hide_options']['description'] = 'Wählen Sie hier die gewünschten Menüpunkte und Traffic-Charts aus, welche im Kundenbereich ausgeblendet werden sollen. Für Mehrfachauswahl, halten Sie während der Auswahl STRG gedrückt.'; -// Added in froxlor 0.9.37.1 +// Added in froxlor 0.9.38-rc1 $lng['serversettings']['allow_allow_customer_shell']['title'] = 'Erlaube Kunden für FTP Benutzer eine Shell auszuwählen'; $lng['serversettings']['allow_allow_customer_shell']['description'] = 'Bitte beachten: Shell Zugriff gestattet dem Benutzer verschiedene Programme auf Ihrem System auszuführen. Mit großer Vorsicht verwenden. Bitte aktiviere dies nur wenn WIRKLICH bekannt ist, was das bedeutet!!!'; $lng['serversettings']['available_shells']['title'] = 'Liste der verfügbaren Shells'; @@ -1706,3 +1706,10 @@ $lng['domains']['ssl_certificates'] = 'SSL Zertifikate'; $lng['domains']['ssl_certificate_removed'] = 'Das Zertifikat mit der ID #%s wurde erfolgreich gelöscht.'; $lng['domains']['ssl_certificate_error'] = "Fehler beim Lesen des Zertifikats für die Domain: %s"; $lng['domains']['no_ssl_certificates'] = "Es wurden keine SSL-Zertifikate gefunden"; +$lng['admin']['webserversettings_ssl'] = 'Webserver SSL-Einstellungen'; +$lng['admin']['domain_hsts_maxage']['title'] = 'HTTP Strict Transport Security (HSTS)'; +$lng['admin']['domain_hsts_maxage']['description'] = '"max-age" Wert für den Strict-Transport-Security Header
Der Wert 0 deaktiviert HSTS für diese Domain. Meist wird der Wert 31536000 gerne genutzt (ein Jahr).'; +$lng['admin']['domain_hsts_incsub']['title'] = 'Inkludiere HSTS für jede Subdomain'; +$lng['admin']['domain_hsts_incsub']['description'] = 'Die optionale "includeSubDomains" Direktive, wenn vorhanden, signalisiert dem UA, dass die HSTS that the HSTS Regel für diese Domain und auch jede Subdomain dieser gilt.'; +$lng['admin']['domain_hsts_preload']['title'] = 'Füge Domain in die HSTS preload Liste hinzu'; +$lng['admin']['domain_hsts_preload']['description'] = 'Wenn die Domain in die HSTS preload Liste, verwaltet von Chrome (und genutzt von Firefox und Safari), hinzugefügt werden soll, dann aktiviere diese Einstellung.
Die preload-Direktive zu senden kann PERMANTENTE KONSEQUENZEN haben und dazu führen, dass Benutzer auf diese Domain und auch Subdomains nicht zugreifen können.
Beachte Details unter hstspreload.appspot.com/#removal bevor ein Header mit "preload" gesendet wird.'; diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 4d6acb46..07ec5752 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -836,7 +836,7 @@ class apache extends HttpConfigBase $vhost_content .= ' SSLCertificateChainFile ' . makeCorrectFile($domain['ssl_cert_chainfile']) . "\n"; } - if ($domain['hsts'] > 0) { + if ($domain['hsts'] >= 0) { $vhost_content .= ' ' . "\n"; $vhost_content .= ' Header always set Strict-Transport-Security "max-age=' . $domain['hsts']; if ($domain['hsts_sub'] == 1) { diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 90b70cc0..651f80db 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -519,7 +519,7 @@ class lighttpd extends HttpConfigBase $ssl_settings .= 'ssl.ca-file = "' . makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n"; } - if ($domain['hsts'] > 0) { + if ($domain['hsts'] >= 0) { $vhost_content .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts']; if ($domain['hsts_sub'] == 1) { diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index 81263633..3a79d610 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -1,4 +1,7 @@ - (2010-) - * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt - * @package Cron + * @copyright (c) the authors + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron * */ -require_once(dirname(__FILE__).'/../classes/class.HttpConfigBase.php'); +require_once (dirname(__FILE__) . '/../classes/class.HttpConfigBase.php'); + +class nginx extends HttpConfigBase +{ -class nginx extends HttpConfigBase { private $logger = false; + private $idnaConvert = false; + private $nginx_server = array(); // protected protected $nginx_data = array(); + protected $needed_htpasswds = array(); + protected $auth_backend_loaded = false; + protected $htpasswds_data = array(); + protected $known_htpasswdsfilenames = array(); + protected $mod_accesslog_loaded = '0'; + protected $vhost_root_autoindex = false; + protected $known_vhostfilenames = array(); + /** * indicator whether a customer is deactivated or not * if yes, only the webroot will be generated @@ -39,42 +54,36 @@ class nginx extends HttpConfigBase { */ private $_deactivated = false; - public function __construct($logger, $idnaConvert, $nginx_server=array()) { + public function __construct($logger, $idnaConvert, $nginx_server = array()) + { $this->logger = $logger; $this->idnaConvert = $idnaConvert; $this->nginx_server = $nginx_server; } - - public function reload() { + public function reload() + { $this->logger->logAction(CRON_ACTION, LOG_INFO, 'nginx::reload: reloading nginx'); safe_exec(Settings::Get('system.apachereload_command')); /** * nginx does not auto-spawn fcgi-processes */ - if (Settings::Get('system.phpreload_command') != '' - && (int)Settings::Get('phpfpm.enabled') == 0 - ) { + if (Settings::Get('system.phpreload_command') != '' && (int) Settings::Get('phpfpm.enabled') == 0) { $this->logger->logAction(CRON_ACTION, LOG_INFO, 'nginx::reload: restarting php processes'); safe_exec(Settings::Get('system.phpreload_command')); - } elseif ((int)Settings::Get('phpfpm.enabled') == 1) { + } elseif ((int) Settings::Get('phpfpm.enabled') == 1) { $this->logger->logAction(CRON_ACTION, LOG_INFO, 'nginx::reload: reloading php-fpm'); safe_exec(escapeshellcmd(Settings::Get('phpfpm.reload'))); } } - /** * define a default ErrorDocument-statement, bug #unknown-yet */ - private function _createStandardErrorHandler() { - if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' - && (Settings::Get('defaultwebsrverrhandler.err401') != '' - || Settings::Get('defaultwebsrverrhandler.err403') != '' - || Settings::Get('defaultwebsrverrhandler.err404') != '' - || Settings::Get('defaultwebsrverrhandler.err500') != '') - ) { + private function _createStandardErrorHandler() + { + if (Settings::Get('defaultwebsrverrhandler.enabled') == '1' && (Settings::Get('defaultwebsrverrhandler.err401') != '' || Settings::Get('defaultwebsrverrhandler.err403') != '' || Settings::Get('defaultwebsrverrhandler.err404') != '' || Settings::Get('defaultwebsrverrhandler.err500') != '')) { $vhosts_folder = ''; if (is_dir(Settings::Get('system.apacheconf_vhost'))) { $vhosts_folder = makeCorrectDir(Settings::Get('system.apacheconf_vhost')); @@ -84,33 +93,36 @@ class nginx extends HttpConfigBase { $vhosts_filename = makeCorrectFile($vhosts_folder . '/05_froxlor_default_errorhandler.conf'); - if (!isset($this->nginx_data[$vhosts_filename])) { + if (! isset($this->nginx_data[$vhosts_filename])) { $this->nginx_data[$vhosts_filename] = ''; } - $statusCodes = array('401', '403', '404', '500'); + $statusCodes = array( + '401', + '403', + '404', + '500' + ); foreach ($statusCodes as $statusCode) { if (Settings::Get('defaultwebsrverrhandler.err' . $statusCode) != '') { $defhandler = Settings::Get('defaultwebsrverrhandler.err' . $statusCode); - if (!validateUrl($defhandler)) { + if (! validateUrl($defhandler)) { $defhandler = makeCorrectFile($defhandler); } - $this->nginx_data[$vhosts_filename].= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n"; + $this->nginx_data[$vhosts_filename] .= 'error_page ' . $statusCode . ' ' . $defhandler . ';' . "\n"; } } } } + public function createVirtualHosts() + {} - public function createVirtualHosts() { - } + public function createFileDirOptions() + {} - - public function createFileDirOptions() { - } - - - public function createIpPort() { + public function createIpPort() + { $result_ipsandports_stmt = Database::query(" SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `ip` ASC, `port` ASC "); @@ -126,7 +138,7 @@ class nginx extends HttpConfigBase { $this->logger->logAction(CRON_ACTION, LOG_INFO, 'nginx::createIpPort: creating ip/port settings for ' . $ip . ":" . $port); $vhost_filename = makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf'); - if (!isset($this->nginx_data[$vhost_filename])) { + if (! isset($this->nginx_data[$vhost_filename])) { $this->nginx_data[$vhost_filename] = ''; } @@ -159,7 +171,7 @@ class nginx extends HttpConfigBase { 'adminid' => 1, /* first admin-user (superadmin) */ 'loginname' => 'froxlor.panel', 'documentroot' => $mypath, - 'parentdomainid' => 0, + 'parentdomainid' => 0 ); // override corresponding array values @@ -187,11 +199,11 @@ class nginx extends HttpConfigBase { /** * this HAS to be set for the default host in nginx or else no vhost will work */ - $this->nginx_data[$vhost_filename] .= "\t". 'listen ' . $ip . ':' . $port . ' default_server'. ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; - $this->nginx_data[$vhost_filename] .= "\t".'# Froxlor default vhost' . "\n"; - $this->nginx_data[$vhost_filename] .= "\t".'server_name ' . Settings::Get('system.hostname') . ';' . "\n"; - $this->nginx_data[$vhost_filename] .= "\t".'access_log /var/log/nginx/access.log;' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'server_name ' . Settings::Get('system.hostname') . ';' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'access_log /var/log/nginx/access.log;' . "\n"; $is_redirect = false; // check for SSL redirect @@ -205,26 +217,23 @@ class nginx extends HttpConfigBase { } else { $_sslport = $this->checkAlternativeSslPort(); $mypath = 'https://' . Settings::Get('system.hostname') . $_sslport . '/'; - $this->nginx_data[$vhost_filename] .= "\t".'return 301 '.$mypath.'$request_uri;'."\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n"; } } - if (!$is_redirect) { - $this->nginx_data[$vhost_filename] .= "\t".'root '.$mypath.';'."\n"; - $this->nginx_data[$vhost_filename] .= "\t".'index index.php index.html index.htm;'."\n\n"; - $this->nginx_data[$vhost_filename] .= "\t".'location / {'."\n"; - $this->nginx_data[$vhost_filename] .= "\t".'}'."\n"; + if (! $is_redirect) { + $this->nginx_data[$vhost_filename] .= "\t" . 'root ' . $mypath . ';' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; } if ($row_ipsandports['specialsettings'] != '') { - $this->nginx_data[$vhost_filename].= $this->processSpecialConfigTemplate( - $row_ipsandports['specialsettings'], - array('domain'=> Settings::Get('system.hostname'), - 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), - 'documentroot'=> $mypath), - $row_ipsandports['ip'], - $row_ipsandports['port'], - $row_ipsandports['ssl'] == '1'). "\n"; + $this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], array( + 'domain' => Settings::Get('system.hostname'), + 'loginname' => Settings::Get('phpfpm.vhost_httpuser'), + 'documentroot' => $mypath + ), $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n"; } /** @@ -232,13 +241,13 @@ class nginx extends HttpConfigBase { */ if ($row_ipsandports['ssl'] == '1') { $row_ipsandports['domain'] = Settings::Get('system.hostname'); - $this->nginx_data[$vhost_filename].=$this->composeSslSettings($row_ipsandports); + $this->nginx_data[$vhost_filename] .= $this->composeSslSettings($row_ipsandports); } - if (!$is_redirect) { + if (! $is_redirect) { $this->nginx_data[$vhost_filename] .= "\tlocation ~ \.php {\n"; $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n"; - $this->nginx_data[$vhost_filename] .= "\t\tinclude ".Settings::Get('nginx.fastcgiparams').";\n"; + $this->nginx_data[$vhost_filename] .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n"; $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n"; $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n"; $this->nginx_data[$vhost_filename] .= "\t\ttry_files \$fastcgi_script_name =404;\n"; @@ -247,24 +256,24 @@ class nginx extends HttpConfigBase { $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_param HTTPS on;\n"; } - if ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1) { + if ((int) Settings::Get('phpfpm.enabled') == 1 && (int) Settings::Get('phpfpm.enabled_ownvhost') == 1) { $domain = array( 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => -1, - 'mod_fcgid_maxrequests' => -1, + 'mod_fcgid_starter' => - 1, + 'mod_fcgid_maxrequests' => - 1, 'guid' => Settings::Get('phpfpm.vhost_httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), 'loginname' => 'froxlor.panel', - 'documentroot' => $mypath, + 'documentroot' => $mypath ); $php = new phpinterface($domain); - $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_pass unix:".$php->getInterface()->getSocketFile().";\n"; + $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_pass unix:" . $php->getInterface()->getSocketFile() . ";\n"; } else { - $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_pass ".Settings::Get('system.nginx_php_backend').";\n"; + $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n"; } $this->nginx_data[$vhost_filename] .= "\t\tfastcgi_index index.php;\n"; @@ -284,36 +293,32 @@ class nginx extends HttpConfigBase { $this->_createStandardErrorHandler(); } - /** * create vhosts */ - protected function createNginxHosts() { - + protected function createNginxHosts() + { $domains = WebserverBase::getVhostsToCreate(); foreach ($domains as $domain) { if (is_dir(Settings::Get('system.apacheconf_vhost'))) { - safe_exec('mkdir -p '.escapeshellarg(makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); + safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } $vhost_filename = $this->getVhostFilename($domain); - if (!isset($this->nginx_data[$vhost_filename])) { + if (! isset($this->nginx_data[$vhost_filename])) { $this->nginx_data[$vhost_filename] = ''; } - if ((empty($this->nginx_data[$vhost_filename]) - && !is_dir(Settings::Get('system.apacheconf_vhost'))) - || is_dir(Settings::Get('system.apacheconf_vhost')) - ) { + if ((empty($this->nginx_data[$vhost_filename]) && ! is_dir(Settings::Get('system.apacheconf_vhost'))) || is_dir(Settings::Get('system.apacheconf_vhost'))) { $domain['nonexistinguri'] = '/' . md5(uniqid(microtime(), 1)) . '.htm'; // Create non-ssl host - $this->nginx_data[$vhost_filename].= $this->getVhostContent($domain, false); + $this->nginx_data[$vhost_filename] .= $this->getVhostContent($domain, false); if ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1') { $vhost_filename_ssl = $this->getVhostFilename($domain, true); - if (!isset($this->nginx_data[$vhost_filename_ssl])) { + if (! isset($this->nginx_data[$vhost_filename_ssl])) { $this->nginx_data[$vhost_filename_ssl] = ''; } // Now enable ssl stuff @@ -323,57 +328,45 @@ class nginx extends HttpConfigBase { } } - - protected function getVhostFilename($domain, $ssl_vhost = false) { - if ((int)$domain['parentdomainid'] == 0 - && isCustomerStdSubdomain((int)$domain['id']) == false - && ((int)$domain['ismainbutsubto'] == 0 - || domainMainToSubExists($domain['ismainbutsubto']) == false) - ) { + protected function getVhostFilename($domain, $ssl_vhost = false) + { + if ((int) $domain['parentdomainid'] == 0 && isCustomerStdSubdomain((int) $domain['id']) == false && ((int) $domain['ismainbutsubto'] == 0 || domainMainToSubExists($domain['ismainbutsubto']) == false)) { $vhost_no = '35'; - } elseif ((int)$domain['parentdomainid'] == 0 - && isCustomerStdSubdomain((int)$domain['id']) == false - && (int)$domain['ismainbutsubto'] > 0 - ) { + } elseif ((int) $domain['parentdomainid'] == 0 && isCustomerStdSubdomain((int) $domain['id']) == false && (int) $domain['ismainbutsubto'] > 0) { $vhost_no = '30'; } else { // number of dots in a domain specifies it's position (and depth of subdomain) starting at 29 going downwards on higher depth - $vhost_no = (string)(30 - substr_count($domain['domain'], ".") + 1); + $vhost_no = (string) (30 - substr_count($domain['domain'], ".") + 1); } if ($ssl_vhost === true) { - $vhost_filename = makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/'.$vhost_no.'_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_ssl_vhost_' . $domain['domain'] . '.conf'); } else { - $vhost_filename = makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/'.$vhost_no.'_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); + $vhost_filename = makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/' . $vhost_no . '_froxlor_normal_vhost_' . $domain['domain'] . '.conf'); } return $vhost_filename; } - - protected function getVhostContent($domain, $ssl_vhost = false) { - if ($ssl_vhost === true - && $domain['ssl'] != '1' - && $domain['ssl_redirect'] != '1' - ) { + protected function getVhostContent($domain, $ssl_vhost = false) + { + if ($ssl_vhost === true && $domain['ssl'] != '1' && $domain['ssl_redirect'] != '1') { return ''; } // check whether the customer is deactivated and NO docroot for deactivated users has been set# $ddr = Settings::Get('system.deactivateddocroot'); if ($domain['deactivated'] == '1' && empty($ddr)) { - return '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n"; + return '# Customer deactivated and a docroot for deactivated users hasn\'t been set.' . "\n"; } $vhost_content = ''; $_vhost_content = ''; - $query = "SELECT * FROM `".TABLE_PANEL_IPSANDPORTS."` `i`, `".TABLE_DOMAINTOIP."` `dip` + $query = "SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` `i`, `" . TABLE_DOMAINTOIP . "` `dip` WHERE dip.id_domain = :domainid AND i.id = dip.id_ipandports "; - if ($ssl_vhost === true - && ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1') - ) { + if ($ssl_vhost === true && ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1')) { // by ordering by cert-file the row with filled out SSL-Fields will be shown last, // thus it is enough to fill out 1 set of SSL-Fields $query .= "AND i.ssl = 1 ORDER BY i.ssl_cert_file ASC;"; @@ -382,10 +375,12 @@ class nginx extends HttpConfigBase { } // start vhost - $vhost_content.= 'server { ' . "\n"; + $vhost_content .= 'server { ' . "\n"; $result_stmt = Database::prepare($query); - Database::pexecute($result_stmt, array('domainid' => $domain['id'])); + Database::pexecute($result_stmt, array( + 'domainid' => $domain['id'] + )); while ($ipandport = $result_stmt->fetch(PDO::FETCH_ASSOC)) { @@ -411,41 +406,34 @@ class nginx extends HttpConfigBase { } if ($ipandport['default_vhostconf_domain'] != '') { - $_vhost_content .= $this->processSpecialConfigTemplate( - $ipandport['default_vhostconf_domain'], - $domain, - $domain['ip'], - $domain['port'], - $ssl_vhost). "\n"; + $_vhost_content .= $this->processSpecialConfigTemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } - $vhost_content.= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; + $vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; } // get all server-names $vhost_content .= $this->getServerNames($domain); // respect ssl_redirect settings, #542 - if ($ssl_vhost == false - && $domain['ssl'] == '1' - && $domain['ssl_redirect'] == '1') { + if ($ssl_vhost == false && $domain['ssl'] == '1' && $domain['ssl_redirect'] == '1') { // We must not check if our port differs from port 443, // but if there is a destination-port != 443 $_sslport = ''; // This returns the first port that is != 443 with ssl enabled, if any // ordered by ssl-certificate (if any) so that the ip/port combo // with certificate is used - $ssldestport_stmt = Database::prepare( - "SELECT `ip`.`port` FROM ".TABLE_PANEL_IPSANDPORTS." `ip` - LEFT JOIN `".TABLE_DOMAINTOIP."` `dip` ON (`ip`.`id` = `dip`.`id_ipandports`) + $ssldestport_stmt = Database::prepare("SELECT `ip`.`port` FROM " . TABLE_PANEL_IPSANDPORTS . " `ip` + LEFT JOIN `" . TABLE_DOMAINTOIP . "` `dip` ON (`ip`.`id` = `dip`.`id_ipandports`) WHERE `dip`.`id_domain` = :domainid AND `ip`.`ssl` = '1' AND `ip`.`port` != 443 - ORDER BY `ip`.`ssl_cert_file` DESC, `ip`.`port` LIMIT 1;" - ); - $ssldestport = Database::pexecute_first($ssldestport_stmt, array('domainid' => $domain['id'])); + ORDER BY `ip`.`ssl_cert_file` DESC, `ip`.`port` LIMIT 1;"); + $ssldestport = Database::pexecute_first($ssldestport_stmt, array( + 'domainid' => $domain['id'] + )); if ($ssldestport['port'] != '') { - $_sslport = ":".$ssldestport['port']; + $_sslport = ":" . $ssldestport['port']; } $domain['documentroot'] = 'https://' . $domain['domain'] . $_sslport . '/'; @@ -455,26 +443,22 @@ class nginx extends HttpConfigBase { $domain['documentroot'] = trim($domain['documentroot']); // create ssl settings first since they are required for normal and redirect vhosts - if ($ssl_vhost === true - && $domain['ssl'] == '1' - && Settings::Get('system.use_ssl') == '1' - ) { - $vhost_content.= "\n" . $this->composeSslSettings($domain) . "\n"; + if ($ssl_vhost === true && $domain['ssl'] == '1' && Settings::Get('system.use_ssl') == '1') { + $vhost_content .= "\n" . $this->composeSslSettings($domain) . "\n"; } - if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.leenabled') == '1') - { + if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.leenabled') == '1') { $acmeConfFilename = Settings::Get('system.letsencryptacmeconf'); - $vhost_content.= "\t".'include '.$acmeConfFilename.';'."\n"; + $vhost_content .= "\t" . 'include ' . $acmeConfFilename . ';' . "\n"; } // if the documentroot is an URL we just redirect if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $uri = $this->idnaConvert->encode_uri($domain['documentroot']); - if (substr($uri, -1) == '/') { - $uri = substr($uri, 0, -1); + if (substr($uri, - 1) == '/') { + $uri = substr($uri, 0, - 1); } - $vhost_content .= "\t".'return 301 '.$uri.'$request_uri;'."\n"; + $vhost_content .= "\t" . 'return 301 ' . $uri . '$request_uri;' . "\n"; } else { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); @@ -484,18 +468,12 @@ class nginx extends HttpConfigBase { if ($this->_deactivated == false) { $vhost_content = $this->mergeVhostCustom($vhost_content, $this->create_pathOptions($domain)) . "\n"; - $vhost_content.= $this->composePhpOptions($domain, $ssl_vhost); + $vhost_content .= $this->composePhpOptions($domain, $ssl_vhost); - $vhost_content.= isset($this->needed_htpasswds[$domain['id']]) ? $this->needed_htpasswds[$domain['id']] . "\n" : ''; + $vhost_content .= isset($this->needed_htpasswds[$domain['id']]) ? $this->needed_htpasswds[$domain['id']] . "\n" : ''; if ($domain['specialsettings'] != "") { - $vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate( - $domain['specialsettings'], - $domain, - $domain['ip'], - $domain['port'], - $ssl_vhost - )); + $vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost)); } if ($_vhost_content != '') { @@ -503,13 +481,7 @@ class nginx extends HttpConfigBase { } if (Settings::Get('system.default_vhostconf') != '') { - $vhost_content = $this->mergeVhostCustom($vhost_content, - $this->processSpecialConfigTemplate( - Settings::Get('system.default_vhostconf'), - $domain, - $domain['ip'], - $domain['port'], - $ssl_vhost)."\n"); + $vhost_content = $this->mergeVhostCustom($vhost_content, $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"); } } } @@ -518,16 +490,23 @@ class nginx extends HttpConfigBase { return $vhost_content; } - protected function mergeVhostCustom($vhost_frx, $vhost_usr) { + protected function mergeVhostCustom($vhost_frx, $vhost_usr) + { // Clean froxlor defined settings $vhost_frx = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_frx)))); // Break into array items $vhost_frx = array_map("trim", $vhost_frx); // remove unnecessary whitespaces // Clean user defined settings $vhost_usr = str_replace("\r", "\n", $vhost_usr); // Remove windows linebreaks - $vhost_usr = str_replace(array("{ ", " }"), array("{\n", "\n}"), $vhost_usr); // Break blocks into lines + $vhost_usr = str_replace(array( + "{ ", + " }" + ), array( + "{\n", + "\n}" + ), $vhost_usr); // Break blocks into lines $vhost_usr = explode("\n", preg_replace('/[ \t]+/', ' ', trim(preg_replace('/\t+/', '', $vhost_usr)))); // Break into array items - $vhost_usr = array_filter($vhost_usr, create_function('$a','return preg_match("#\S#", $a);')); // Remove empty lines + $vhost_usr = array_filter($vhost_usr, create_function('$a', 'return preg_match("#\S#", $a);')); // Remove empty lines // Cycle through the user defined settings $currentBlock = array(); @@ -537,10 +516,10 @@ class nginx extends HttpConfigBase { $currentBlock[] = $line; if (strpos($line, "{") !== false) { - $blockLevel++; + $blockLevel ++; } if (strpos($line, "}") !== false && $blockLevel > 0) { - $blockLevel--; + $blockLevel --; } if ($line == "}" && $blockLevel == 0) { @@ -548,10 +527,10 @@ class nginx extends HttpConfigBase { // Add to existing block $pos = array_search($currentBlock[0], $vhost_frx); do { - $pos++; + $pos ++; } while ($vhost_frx[$pos] != "}"); - for ($i = 1; $i < count($currentBlock) - 1; $i++) { + for ($i = 1; $i < count($currentBlock) - 1; $i ++) { array_splice($vhost_frx, $pos + $i - 1, 0, $currentBlock[$i]); } } else { @@ -566,13 +545,13 @@ class nginx extends HttpConfigBase { } $nextLevel = 0; - for ($i = 0; $i < count($vhost_frx); $i++) { + for ($i = 0; $i < count($vhost_frx); $i ++) { if (substr_count($vhost_frx[$i], "}") != 0 && substr_count($vhost_frx[$i], "{") == 0) { $nextLevel -= 1; $vhost_frx[$i] .= "\n"; } if ($nextLevel > 0) { - for ($j = 0; $j < $nextLevel; $j++) { + for ($j = 0; $j < $nextLevel; $j ++) { $vhost_frx[$i] = " " . $vhost_frx[$i]; } } @@ -584,8 +563,8 @@ class nginx extends HttpConfigBase { return implode("\n", $vhost_frx); } - protected function composeSslSettings($domain_or_ip) { - + protected function composeSslSettings($domain_or_ip) + { $sslsettings = ''; if ($domain_or_ip['ssl_cert_file'] == '') { @@ -607,93 +586,95 @@ class nginx extends HttpConfigBase { if ($domain_or_ip['ssl_cert_file'] != '') { - // check for existence, #1485 - if (!file_exists($domain_or_ip['ssl_cert_file'])) { - $this->logger->logAction(CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "'.$domain_or_ip['ssl_cert_file'].'" does not exist! Cannot create ssl-directives'); - } else { - // obsolete: ssl on now belongs to the listen block as 'ssl' at the end - //$sslsettings .= "\t" . 'ssl on;' . "\n"; - $sslsettings .= "\t" . 'ssl_protocols TLSv1 TLSv1.1 TLSv1.2;' . "\n"; - $sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n"; - $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; - $sslsettings .= "\t" . 'ssl_prefer_server_ciphers on;' . "\n"; - $sslsettings .= "\t" . 'ssl_certificate ' . makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; + // check for existence, #1485 + if (! file_exists($domain_or_ip['ssl_cert_file'])) { + $this->logger->logAction(CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); + } else { + // obsolete: ssl on now belongs to the listen block as 'ssl' at the end + // $sslsettings .= "\t" . 'ssl on;' . "\n"; + $sslsettings .= "\t" . 'ssl_protocols TLSv1 TLSv1.1 TLSv1.2;' . "\n"; + $sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n"; + $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; + $sslsettings .= "\t" . 'ssl_prefer_server_ciphers on;' . "\n"; + $sslsettings .= "\t" . 'ssl_certificate ' . makeCorrectFile($domain_or_ip['ssl_cert_file']) . ';' . "\n"; - if ($domain_or_ip['ssl_key_file'] != '') { - // check for existence, #1485 - if (!file_exists($domain_or_ip['ssl_key_file'])) { - $this->logger->logAction(CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate key file "'.$domain_or_ip['ssl_key_file'].'" does not exist! Cannot create ssl-directives'); - } else { - $sslsettings .= "\t" . 'ssl_certificate_key ' .makeCorrectFile($domain_or_ip['ssl_key_file']) . ';' . "\n"; - } - } + if ($domain_or_ip['ssl_key_file'] != '') { + // check for existence, #1485 + if (! file_exists($domain_or_ip['ssl_key_file'])) { + $this->logger->logAction(CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate key file "' . $domain_or_ip['ssl_key_file'] . '" does not exist! Cannot create ssl-directives'); + } else { + $sslsettings .= "\t" . 'ssl_certificate_key ' . makeCorrectFile($domain_or_ip['ssl_key_file']) . ';' . "\n"; + } + } - if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] > 0) { - $vhost_content .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; - if ($domain_or_ip['hsts_sub'] == 1) { - $vhost_content .= '; includeSubDomains'; - } - if ($domain_or_ip['hsts_preload'] == 1) { - $vhost_content .= '; preload'; - } - $vhost_content .= '";' . "\n"; + if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] >= 0) { + $vhost_content .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; + if ($domain_or_ip['hsts_sub'] == 1) { + $vhost_content .= '; includeSubDomains'; + } + if ($domain_or_ip['hsts_preload'] == 1) { + $vhost_content .= '; preload'; + } + $vhost_content .= '";' . "\n"; + } } - } } return $sslsettings; } - - protected function create_pathOptions($domain) { + protected function create_pathOptions($domain) + { $has_location = false; $result_stmt = Database::prepare(" SELECT * FROM " . TABLE_PANEL_HTACCESS . " WHERE `path` LIKE :docroot "); - Database::pexecute($result_stmt, array('docroot' => $domain['documentroot'] . '%')); + Database::pexecute($result_stmt, array( + 'docroot' => $domain['documentroot'] . '%' + )); $path_options = ''; $htpasswds = $this->getHtpasswds($domain); // for each entry in the htaccess table while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { - if (!empty($row['error404path'])) { + if (! empty($row['error404path'])) { $defhandler = $row['error404path']; - if (!validateUrl($defhandler)) { + if (! validateUrl($defhandler)) { $defhandler = makeCorrectFile($defhandler); } - $path_options .= "\t".'error_page 404 ' . $defhandler . ';' . "\n"; + $path_options .= "\t" . 'error_page 404 ' . $defhandler . ';' . "\n"; } - if (!empty($row['error403path'])) { + if (! empty($row['error403path'])) { $defhandler = $row['error403path']; - if (!validateUrl($defhandler)) { + if (! validateUrl($defhandler)) { $defhandler = makeCorrectFile($defhandler); } - $path_options .= "\t".'error_page 403 ' . $defhandler . ';' . "\n"; + $path_options .= "\t" . 'error_page 403 ' . $defhandler . ';' . "\n"; } - if (!empty($row['error500path'])) { + if (! empty($row['error500path'])) { $defhandler = $row['error500path']; - if (!validateUrl($defhandler)) { + if (! validateUrl($defhandler)) { $defhandler = makeCorrectFile($defhandler); } - $path_options .= "\t".'error_page 500 502 503 504 ' . $defhandler . ';' . "\n"; + $path_options .= "\t" . 'error_page 500 502 503 504 ' . $defhandler . ';' . "\n"; } - // if ($row['options_indexes'] != '0') { + // if ($row['options_indexes'] != '0') { $path = makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); - $path_options .= "\t".'# '.$path."\n"; + $path_options .= "\t" . '# ' . $path . "\n"; if ($path == '/') { if ($row['options_indexes'] != '0') { $this->vhost_root_autoindex = true; } - $path_options .= "\t".'location ' . $path . ' {' . "\n"; + $path_options .= "\t" . 'location ' . $path . ' {' . "\n"; if ($this->vhost_root_autoindex) { $path_options .= "\t\t" . 'autoindex on;' . "\n"; $this->vhost_root_autoindex = false; @@ -705,80 +686,77 @@ class nginx extends HttpConfigBase { if (count($htpasswds) > 0) { foreach ($htpasswds as $idx => $single) { switch ($single['path']) { - case '/awstats/': - case '/webalizer/': - // no stats-alias in "location /"-context - break; - default: - if ($single['path'] == '/') { - $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';'."\n"; - $path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; - $path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; - $path_options .= "\t\t" . '}' . "\n"; - // remove already used entries so we do not have doubles - unset($htpasswds[$idx]); - } + case '/awstats/': + case '/webalizer/': + // no stats-alias in "location /"-context + break; + default: + if ($single['path'] == '/') { + $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; + $path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';' . "\n"; + $path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; + $path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; + $path_options .= "\t\t" . '}' . "\n"; + // remove already used entries so we do not have doubles + unset($htpasswds[$idx]); + } } } } - $path_options .= "\t".'}' . "\n"; + $path_options .= "\t" . '}' . "\n"; $this->vhost_root_autoindex = false; } else { - $path_options .= "\t".'location ' . $path . ' {' . "\n"; + $path_options .= "\t" . 'location ' . $path . ' {' . "\n"; if ($this->vhost_root_autoindex || $row['options_indexes'] != '0') { $path_options .= "\t\t" . 'autoindex on;' . "\n"; $this->vhost_root_autoindex = false; } - $path_options .= "\t".'} ' . "\n"; + $path_options .= "\t" . '} ' . "\n"; } - // } + // } /** * Perl support * required the fastCGI wrapper to be running to receive the CGI requests. */ - if (customerHasPerlEnabled($domain['customerid']) - && $row['options_cgi'] != '0' - ) { + if (customerHasPerlEnabled($domain['customerid']) && $row['options_cgi'] != '0') { $path = makeCorrectDir(substr($row['path'], strlen($domain['documentroot']) - 1)); mkDirWithCorrectOwnership($domain['documentroot'], $row['path'], $domain['guid'], $domain['guid']); // We need to remove the last slash, otherwise the regex wouldn't work if ($row['path'] != $domain['documentroot']) { - $path = substr($path, 0, -1); + $path = substr($path, 0, - 1); } $path_options .= "\t" . 'location ~ \(.pl|.cgi)$ {' . "\n"; $path_options .= "\t\t" . 'gzip off; #gzip makes scripts feel slower since they have to complete before getting gzipped' . "\n"; - $path_options .= "\t\t" . 'fastcgi_pass '. Settings::Get('system.perl_server') . ';' . "\n"; + $path_options .= "\t\t" . 'fastcgi_pass ' . Settings::Get('system.perl_server') . ';' . "\n"; $path_options .= "\t\t" . 'fastcgi_index index.cgi;' . "\n"; - $path_options .= "\t\t" . 'include '.Settings::Get('nginx.fastcgiparams').';'."\n"; + $path_options .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ';' . "\n"; $path_options .= "\t" . '}' . "\n"; } - } // now the rest of the htpasswds if (count($htpasswds) > 0) { foreach ($htpasswds as $idx => $single) { - //if ($single['path'] != '/') { + // if ($single['path'] != '/') { switch ($single['path']) { - case '/awstats/': - case '/webalizer/': - $path_options .= $this->getStats($domain,$single); - unset($htpasswds[$idx]); - break; - default: - $path_options .= "\t" . 'location ' . makeCorrectDir($single['path']) . ' {' . "\n"; - $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';'."\n"; - $path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; - $path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; - $path_options .= "\t\t" . '}' . "\n"; - $path_options .= "\t".'}' . "\n"; + case '/awstats/': + case '/webalizer/': + $path_options .= $this->getStats($domain, $single); + unset($htpasswds[$idx]); + break; + default: + $path_options .= "\t" . 'location ' . makeCorrectDir($single['path']) . ' {' . "\n"; + $path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; + $path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';' . "\n"; + $path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n"; + $path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; + $path_options .= "\t\t" . '}' . "\n"; + $path_options .= "\t" . '}' . "\n"; } - //} + // } unset($htpasswds[$idx]); } } @@ -786,16 +764,18 @@ class nginx extends HttpConfigBase { return $path_options; } - - protected function getHtpasswds($domain) { - + protected function getHtpasswds($domain) + { $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` AS a JOIN `" . TABLE_PANEL_DOMAINS . "` AS b USING (`customerid`) WHERE b.customerid = :customerid AND b.domain = :domain "); - Database::pexecute($result_stmt, array('customerid' => $domain['customerid'], 'domain' => $domain['domain'])); + Database::pexecute($result_stmt, array( + 'customerid' => $domain['customerid'], + 'domain' => $domain['domain'] + )); $returnval = array(); $x = 0; @@ -804,15 +784,15 @@ class nginx extends HttpConfigBase { $htpasswd_filename = makeCorrectFile(Settings::Get('system.apacheconf_htpasswddir') . '/' . $row_htpasswds['customerid'] . '-' . md5($row_htpasswds['path']) . '.htpasswd'); // ensure we can write to the array with index $htpasswd_filename - if (!isset($this->htpasswds_data[$htpasswd_filename])) { + if (! isset($this->htpasswds_data[$htpasswd_filename])) { $this->htpasswds_data[$htpasswd_filename] = ''; } - $this->htpasswds_data[$htpasswd_filename].= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; + $this->htpasswds_data[$htpasswd_filename] .= $row_htpasswds['username'] . ':' . $row_htpasswds['password'] . "\n"; // if the domains and their web contents are located in a subdirectory of // the nginx user, we have to evaluate the right path which is to protect - if (stripos($row_htpasswds['path'], $domain['documentroot']) !== false ) { + if (stripos($row_htpasswds['path'], $domain['documentroot']) !== false) { // if the website contents is located in the user directory $path = makeCorrectDir(substr($row_htpasswds['path'], strlen($domain['documentroot']) - 1)); } else { @@ -827,7 +807,7 @@ class nginx extends HttpConfigBase { // Ensure there is only one auth name per password block, otherwise // the directives are inserted multiple times -> invalid config $authname = $row_htpasswds['authname']; - for ($i = 0; $i < $x; $i++) { + for ($i = 0; $i < $x; $i ++) { if ($returnval[$i]['usrf'] == $htpasswd_filename) { $authname = $returnval[$i]['authname']; break; @@ -836,7 +816,7 @@ class nginx extends HttpConfigBase { $returnval[$x]['authname'] = $authname; $returnval[$x]['usrf'] = $htpasswd_filename; - $x++; + $x ++; } } @@ -846,66 +826,59 @@ class nginx extends HttpConfigBase { return $returnval; } - - protected function composePhpOptions($domain, $ssl_vhost = false) { + protected function composePhpOptions($domain, $ssl_vhost = false) + { $phpopts = ''; if ($domain['phpenabled'] == '1') { - $phpopts = "\tlocation ~ \.php {\n"; + $phpopts = "\tlocation ~ \.php {\n"; $phpopts .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; $phpopts .= "\t" . '}' . "\n\n"; $phpopts .= "\tlocation @php {\n"; $phpopts .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n"; - $phpopts .= "\t\tinclude ".Settings::Get('nginx.fastcgiparams').";\n"; + $phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n"; $phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n"; $phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n"; $phpopts .= "\t\ttry_files \$fastcgi_script_name =404;\n"; - $phpopts .= "\t\tfastcgi_pass ".Settings::Get('system.nginx_php_backend').";\n"; + $phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n"; $phpopts .= "\t\tfastcgi_index index.php;\n"; if ($domain['ssl'] == '1' && $ssl_vhost) { $phpopts .= "\t\tfastcgi_param HTTPS on;\n"; } $phpopts .= "\t}\n\n"; - } return $phpopts; } - - protected function getWebroot($domain, $ssl) { + protected function getWebroot($domain, $ssl) + { $webroot_text = ''; - if ($domain['deactivated'] == '1' - && Settings::Get('system.deactivateddocroot') != '' - ) { - $webroot_text .= "\t".'# Using docroot for deactivated users...' . "\n"; - $webroot_text .= "\t".'root '.makeCorrectDir(Settings::Get('system.deactivateddocroot')).';'."\n"; + if ($domain['deactivated'] == '1' && Settings::Get('system.deactivateddocroot') != '') { + $webroot_text .= "\t" . '# Using docroot for deactivated users...' . "\n"; + $webroot_text .= "\t" . 'root ' . makeCorrectDir(Settings::Get('system.deactivateddocroot')) . ';' . "\n"; $this->_deactivated = true; } else { - $webroot_text .= "\t".'root '.makeCorrectDir($domain['documentroot']).';'."\n"; + $webroot_text .= "\t" . 'root ' . makeCorrectDir($domain['documentroot']) . ';' . "\n"; $this->_deactivated = false; } - $webroot_text .= "\n\t".'location / {'."\n"; + $webroot_text .= "\n\t" . 'location / {' . "\n"; - if ($domain['phpenabled'] == '1') - { - $webroot_text .= "\t" . 'index index.php index.html index.htm;'."\n"; - $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;'."\n"; - } - else - { - $webroot_text .= "\t" . 'index index.html index.htm;'."\n"; + if ($domain['phpenabled'] == '1') { + $webroot_text .= "\t" . 'index index.php index.html index.htm;' . "\n"; + $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;' . "\n"; + } else { + $webroot_text .= "\t" . 'index index.html index.htm;' . "\n"; } if ($this->vhost_root_autoindex) { - $webroot_text .= "\t\t".'autoindex on;'."\n"; + $webroot_text .= "\t\t" . 'autoindex on;' . "\n"; $this->vhost_root_autoindex = false; } - $webroot_text .= "\t".'}'."\n\n"; - if ($domain['phpenabled'] == '1') - { + $webroot_text .= "\t" . '}' . "\n\n"; + if ($domain['phpenabled'] == '1') { $webroot_text .= "\tlocation @rewrites {\n"; $webroot_text .= "\t\trewrite ^ /index.php last;\n"; $webroot_text .= "\t}\n\n"; @@ -914,8 +887,8 @@ class nginx extends HttpConfigBase { return $webroot_text; } - - protected function getStats($domain, $single) { + protected function getStats($domain, $single) + { $stats_text = ''; // define basic path to the stats @@ -927,9 +900,9 @@ class nginx extends HttpConfigBase { // if this is a parentdomain, we use this domain-name if ($domain['parentdomainid'] == '0') { - $alias_dir = makeCorrectDir($alias_dir.'/'.$domain['domain']); + $alias_dir = makeCorrectDir($alias_dir . '/' . $domain['domain']); } else { - $alias_dir = makeCorrectDir($alias_dir.'/'.$domain['parentdomain']); + $alias_dir = makeCorrectDir($alias_dir . '/' . $domain['parentdomain']); } if (Settings::Get('system.awstats_enabled') == '1') { @@ -941,8 +914,8 @@ class nginx extends HttpConfigBase { } $stats_text .= "\t\t" . 'alias ' . $alias_dir . ';' . "\n"; - $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; - $stats_text .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';'."\n"; + $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; + $stats_text .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';' . "\n"; $stats_text .= "\t" . '}' . "\n\n"; // awstats icons @@ -955,8 +928,8 @@ class nginx extends HttpConfigBase { return $stats_text; } - - protected function getLogFiles($domain) { + protected function getLogFiles($domain) + { $logfiles_text = ''; $speciallogfile = ''; @@ -981,11 +954,11 @@ class nginx extends HttpConfigBase { chown($access_log, Settings::Get('system.httpuser')); chgrp($access_log, Settings::Get('system.httpgroup')); - $logfiles_text .= "\t".'access_log ' . $access_log . ' combined;' . "\n"; - $logfiles_text .= "\t".'error_log ' . $error_log . ' error;' . "\n"; + $logfiles_text .= "\t" . 'access_log ' . $access_log . ' combined;' . "\n"; + $logfiles_text .= "\t" . 'error_log ' . $error_log . ' error;' . "\n"; if (Settings::Get('system.awstats_enabled') == '1') { - if ((int)$domain['parentdomainid'] == 0) { + if ((int) $domain['parentdomainid'] == 0) { // prepare the aliases and subdomains for stats config files $server_alias = ''; $alias_domains_stmt = Database::prepare(" @@ -993,7 +966,9 @@ class nginx extends HttpConfigBase { FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :domainid OR `parentdomainid` = :domainid "); - Database::pexecute($alias_domains_stmt, array('domainid' => $domain['id'])); + Database::pexecute($alias_domains_stmt, array( + 'domainid' => $domain['id'] + )); while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { $server_alias .= ' ' . $alias_domain['domain'] . ' '; @@ -1027,12 +1002,11 @@ class nginx extends HttpConfigBase { return $logfiles_text; } + public function createOwnVhostStarter() + {} - public function createOwnVhostStarter() { - } - - - protected function getServerNames($domain) { + protected function getServerNames($domain) + { $server_alias = ''; if ($domain['iswildcarddomain'] == '1') { @@ -1046,7 +1020,9 @@ class nginx extends HttpConfigBase { FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `aliasdomain` = :domainid "); - Database::pexecute($alias_domains_stmt, array('domainid' => $domain['id'])); + Database::pexecute($alias_domains_stmt, array( + 'domainid' => $domain['id'] + )); while (($alias_domain = $alias_domains_stmt->fetch(PDO::FETCH_ASSOC)) !== false) { $server_alias .= ' ' . $alias_domain['domain']; @@ -1054,25 +1030,25 @@ class nginx extends HttpConfigBase { if ($alias_domain['iswildcarddomain'] == '1') { $server_alias .= ' *.' . $alias_domain['domain']; } elseif ($alias_domain['wwwserveralias'] == '1') { - $server_alias.= ' www.' . $alias_domain['domain']; + $server_alias .= ' www.' . $alias_domain['domain']; } } - $servernames_text = "\t".'server_name '.$domain['domain']; + $servernames_text = "\t" . 'server_name ' . $domain['domain']; if (trim($server_alias) != '') { - $servernames_text .= ' '.$server_alias; + $servernames_text .= ' ' . $server_alias; } $servernames_text .= ';' . "\n"; return $servernames_text; } - - public function writeConfigs() { + public function writeConfigs() + { $this->logger->logAction(CRON_ACTION, LOG_INFO, "nginx::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost')); $vhostDir = new frxDirectory(Settings::Get('system.apacheconf_vhost')); - if (!$vhostDir->isConfigDir()) { + if (! $vhostDir->isConfigDir()) { // Save one big file $vhosts_file = ''; @@ -1083,7 +1059,7 @@ class nginx extends HttpConfigBase { ksort($this->nginx_data); foreach ($this->nginx_data as $vhosts_filename => $vhost_content) { - $vhosts_file.= $vhost_content . "\n\n"; + $vhosts_file .= $vhost_content . "\n\n"; } $vhosts_filename = Settings::Get('system.apacheconf_vhost'); @@ -1094,7 +1070,7 @@ class nginx extends HttpConfigBase { fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } else { - if (!file_exists(Settings::Get('system.apacheconf_vhost'))) { + if (! file_exists(Settings::Get('system.apacheconf_vhost'))) { $this->logger->logAction(CRON_ACTION, LOG_NOTICE, 'nginx::writeConfigs: mkdir ' . escapeshellarg(makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir(Settings::Get('system.apacheconf_vhost')))); } @@ -1106,23 +1082,22 @@ class nginx extends HttpConfigBase { // Apply header $vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file; - if (!empty($vhosts_filename)) { + if (! empty($vhosts_filename)) { $vhosts_file_handler = fopen($vhosts_filename, 'w'); fwrite($vhosts_file_handler, $vhosts_file); fclose($vhosts_file_handler); } - } } // htaccess stuff if (count($this->htpasswds_data) > 0) { - if (!file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { + if (! file_exists(Settings::Get('system.apacheconf_htpasswddir'))) { $umask = umask(); umask(0000); mkdir(Settings::Get('system.apacheconf_htpasswddir'), 0751); umask($umask); - } elseif (!is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { + } elseif (! is_dir(Settings::Get('system.apacheconf_htpasswddir'))) { $this->logger->logAction(CRON_ACTION, LOG_WARNING, 'WARNING!!! ' . Settings::Get('system.apacheconf_htpasswddir') . ' is not a directory. htpasswd directory protection is disabled!!!'); } @@ -1138,6 +1113,4 @@ class nginx extends HttpConfigBase { } } } - - } From d198729222b36bf0d82efed605376675f4e1c769 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 7 Oct 2016 11:48:13 +0200 Subject: [PATCH 04/62] make the hsts domain settings actually saveable; add hsts domain settings for customer-panel; refs #1660 Signed-off-by: Michael Kaufmann (d00p) --- admin_domains.php | 62 +++++++++++++-- customer_domains.php | 33 ++++++-- .../domains/formfield.domains_add.php | 78 ++++++++++++++----- .../domains/formfield.domains_edit.php | 58 +++++++++++--- 4 files changed, 187 insertions(+), 44 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index abb66e6b..99dc415d 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -584,12 +584,23 @@ if ($page == 'domains' || $page == 'overview') { $ssl_ipandports[] = $ssl_ipandport; } } + + // HSTS + $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; + $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; + $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; + } else { $ssl_redirect = 0; $letsencrypt = 0; // we need this for the serialize // if ssl is disabled or no ssl-ip/port exists $ssl_ipandports[] = - 1; + + // HSTS + $hsts_maxage = 0; + $hsts_sub = 0; + $hsts_preload = 0; } } else { $ssl_redirect = 0; @@ -597,6 +608,11 @@ if ($page == 'domains' || $page == 'overview') { // we need this for the serialize // if ssl is disabled or no ssl-ip/port exists $ssl_ipandports[] = - 1; + + // HSTS + $hsts_maxage = 0; + $hsts_sub = 0; + $hsts_preload = 0; } // We can't enable let's encrypt for wildcard - domains @@ -760,7 +776,10 @@ if ($page == 'domains' || $page == 'overview') { 'registration_date' => $registration_date, 'termination_date' => $termination_date, 'issubof' => $issubof, - 'letsencrypt' => $letsencrypt + 'letsencrypt' => $letsencrypt, + 'hsts' => $hsts_maxage, + 'hsts_sub' => $hsts_sub, + 'hsts_preload' => $hsts_preload ); $security_questions = array( @@ -808,7 +827,10 @@ if ($page == 'domains' || $page == 'overview') { 'mod_fcgid_starter' => $mod_fcgid_starter, 'mod_fcgid_maxrequests' => $mod_fcgid_maxrequests, 'ismainbutsubto' => $issubof, - 'letsencrypt' => $letsencrypt + 'letsencrypt' => $letsencrypt, + 'hsts' => $hsts_maxage, + 'hsts_sub' => $hsts_sub, + 'hsts_preload' => $hsts_preload ); $ins_stmt = Database::prepare(" @@ -836,12 +858,15 @@ if ($page == 'domains' || $page == 'overview') { `ssl_redirect` = :ssl_redirect, `add_date` = :add_date, `registration_date` = :registration_date, - `termination_date` = :termination_date, + `termination_date` = :termination_date, `phpsettingid` = :phpsettingid, `mod_fcgid_starter` = :mod_fcgid_starter, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `ismainbutsubto` = :ismainbutsubto, - `letsencrypt` = :letsencrypt + `letsencrypt` = :letsencrypt, + `hsts` = :hsts, + `hsts_sub` = :hsts_sub, + `hsts_preload` = :hsts_preload "); Database::pexecute($ins_stmt, $ins_data); $domainid = Database::lastInsertId(); @@ -1398,12 +1423,23 @@ if ($page == 'domains' || $page == 'overview') { $ssl_ipandports[] = $ssl_ipandport; } } + + // HSTS + $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; + $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; + $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; + } else { $ssl_redirect = 0; $letsencrypt = 0; // we need this for the serialize // if ssl is disabled or no ssl-ip/port exists $ssl_ipandports[] = - 1; + + // HSTS + $hsts_maxage = 0; + $hsts_sub = 0; + $hsts_preload = 0; } } else { $ssl_redirect = 0; @@ -1411,6 +1447,11 @@ if ($page == 'domains' || $page == 'overview') { // we need this for the serialize // if ssl is disabled or no ssl-ip/port exists $ssl_ipandports[] = - 1; + + // HSTS + $hsts_maxage = 0; + $hsts_sub = 0; + $hsts_preload = 0; } // We can't enable let's encrypt for wildcard domains @@ -1548,7 +1589,10 @@ if ($page == 'domains' || $page == 'overview') { 'speciallogverified' => $speciallogverified, 'ipandport' => serialize($ipandports), 'ssl_ipandport' => serialize($ssl_ipandports), - 'letsencrypt' => $letsencrypt + 'letsencrypt' => $letsencrypt, + 'hsts' => $hsts_maxage, + 'hsts_sub' => $hsts_sub, + 'hsts_preload' => $hsts_preload ); $security_questions = array( @@ -1708,6 +1752,9 @@ if ($page == 'domains' || $page == 'overview') { $update_data['termination_date'] = $termination_date; $update_data['ismainbutsubto'] = $issubof; $update_data['letsencrypt'] = $letsencrypt; + $update_data['hsts'] = $hsts_maxage; + $update_data['hsts_sub'] = $hsts_sub; + $update_data['hsts_preload'] = $hsts_preload; $update_data['id'] = $id; $update_stmt = Database::prepare(" @@ -1735,7 +1782,10 @@ if ($page == 'domains' || $page == 'overview') { `registration_date` = :registration_date, `termination_date` = :termination_date, `ismainbutsubto` = :ismainbutsubto, - `letsencrypt` = :letsencrypt + `letsencrypt` = :letsencrypt, + `hsts` = :hsts, + `hsts_sub` = :hsts_sub, + `hsts_preload` = :hsts_preload WHERE `id` = :id "); Database::pexecute($update_stmt, $update_data); diff --git a/customer_domains.php b/customer_domains.php index 2aa9bbab..e79af357 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -374,6 +374,11 @@ if ($page == 'overview') { $ssl_redirect = 2; } + // HSTS + $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; + $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; + $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; + if ($path == '') { standard_error('patherror'); } elseif ($subdomain == '') { @@ -416,7 +421,10 @@ if ($page == 'overview') { `specialsettings` = :specialsettings, `ssl_redirect` = :ssl_redirect, `phpsettingid` = :phpsettingid, - `letsencrypt` = :letsencrypt" + `letsencrypt` = :letsencrypt, + `hsts` = :hsts, + `hsts_sub` = :hsts_sub, + `hsts_preload` = :hsts_preload" ); $params = array( "customerid" => $userinfo['customerid'], @@ -433,7 +441,10 @@ if ($page == 'overview') { "specialsettings" => $domain_check['specialsettings'], "ssl_redirect" => $ssl_redirect, "phpsettingid" => $phpsid_result['phpsettingid'], - "letsencrypt" => $letsencrypt + "letsencrypt" => $letsencrypt, + "hsts" => $hsts_maxage, + "hsts_sub" => $hsts_sub, + "hsts_preload" => $hsts_preload ); Database::pexecute($stmt, $params); @@ -527,8 +538,7 @@ if ($page == 'overview') { } } elseif ($action == 'edit' && $id != 0) { - $stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`isbinddomain`, `d`.`wwwserveralias`, `d`.`iswildcarddomain`, - `d`.`parentdomainid`, `d`.`ssl_redirect`, `d`.`aliasdomain`, `d`.`openbasedir`, `d`.`openbasedir_path`, `d`.`letsencrypt`, `pd`.`subcanemaildomain` + $stmt = Database::prepare("SELECT `d`.*, `pd`.`subcanemaildomain` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_DOMAINS . "` `pd` WHERE `d`.`customerid` = :customerid AND `d`.`id` = :id @@ -634,7 +644,7 @@ if ($page == 'overview') { // We can't enable let's encrypt for wildcard - domains if ($iswildcarddomain == '1' && $letsencrypt == '1') { - standard_error('nowildcardwithletsencrypt'); + standard_error('nowildcardwithletsencrypt'); } // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated @@ -642,6 +652,11 @@ if ($page == 'overview') { $ssl_redirect = 2; } + // HSTS + $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; + $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; + $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; + if ($path == '') { standard_error('patherror'); } else { @@ -677,7 +692,10 @@ if ($page == 'overview') { `aliasdomain`= :aliasdomain, `openbasedir_path`= :openbasedir_path, `ssl_redirect`= :ssl_redirect, - `letsencrypt`= :letsencrypt + `letsencrypt`= :letsencrypt, + `hsts` = :hsts, + `hsts_sub` = :hsts_sub, + `hsts_preload` = :hsts_preload, WHERE `customerid`= :customerid AND `id`= :id" ); @@ -690,6 +708,9 @@ if ($page == 'overview') { "openbasedir_path" => $openbasedir_path, "ssl_redirect" => $ssl_redirect, "letsencrypt" => $letsencrypt, + "hsts" => $hsts_maxage, + "hsts_sub" => $hsts_sub, + "hsts_preload" => $hsts_preload, "customerid" => $userinfo['customerid'], "id" => $id ); diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index 2f24fcae..e25302b0 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -66,33 +66,69 @@ return array( 'type' => 'label', 'value' => $lng['customer']['selectserveralias_addinfo'] ), - 'ssl_redirect' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), - 'label' => $lng['domains']['ssl_redirect']['title'], - 'desc' => $lng['domains']['ssl_redirect']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array() - ), - 'letsencrypt' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false) : false), - 'label' => $lng['customer']['letsencrypt']['title'], - 'desc' => $lng['customer']['letsencrypt']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array() - ), 'openbasedir_path' => array( 'label' => $lng['domain']['openbasedirpath'], 'type' => 'select', 'select_var' => $openbasedir ) ) - ) + ), + 'section_bssl' => array( + 'title' => $lng['admin']['webserversettings_ssl'], + 'image' => 'icons/domain_add.png', + 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'fields' => array( + 'ssl_redirect' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['domains']['ssl_redirect']['title'], + 'desc' => $lng['domains']['ssl_redirect']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'letsencrypt' => array( + 'visible' => (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), + 'label' => $lng['customer']['letsencrypt']['title'], + 'desc' => $lng['customer']['letsencrypt']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'hsts_maxage' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_maxage']['title'], + 'desc' => $lng['admin']['domain_hsts_maxage']['description'], + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'value' => 0 + ), + 'hsts_incsub' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_incsub']['title'], + 'desc' => $lng['admin']['domain_hsts_incsub']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + 'hsts_preload' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_preload']['title'], + 'desc' => $lng['admin']['domain_hsts_preload']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), + ), + ), ) ) ); diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index 0b319248..2e753e21 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -76,14 +76,27 @@ return array( ), 'value' => array($result['isemaildomain']) ), + 'openbasedir_path' => array( + 'visible' => ($result['openbasedir'] == '1') ? true : false, + 'label' => $lng['domain']['openbasedirpath'], + 'type' => 'select', + 'select_var' => $openbasedir + ) + ) + ), + 'section_bssl' => array( + 'title' => $lng['admin']['webserversettings_ssl'], + 'image' => 'icons/domain_edit.png', + 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'fields' => array( 'ssl_redirect' => array( 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false), 'label' => $lng['domains']['ssl_redirect']['title'], 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''), 'type' => 'checkbox', 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), 'value' => array($result['ssl_redirect']) ), 'letsencrypt' => array( @@ -92,18 +105,41 @@ return array( 'desc' => $lng['customer']['letsencrypt']['description'], 'type' => 'checkbox', 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), 'value' => array($result['letsencrypt']) ), - 'openbasedir_path' => array( - 'visible' => ($result['openbasedir'] == '1') ? true : false, - 'label' => $lng['domain']['openbasedirpath'], - 'type' => 'select', - 'select_var' => $openbasedir - ) + 'hsts_maxage' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_maxage']['title'], + 'desc' => $lng['admin']['domain_hsts_maxage']['description'], + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'value' => $result['hsts'] + ), + 'hsts_incsub' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_incsub']['title'], + 'desc' => $lng['admin']['domain_hsts_incsub']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['hsts_sub']) + ), + 'hsts_preload' => array( + 'visible' => ($ssl_ipsandports != '' ? true : false), + 'label' => $lng['admin']['domain_hsts_preload']['title'], + 'desc' => $lng['admin']['domain_hsts_preload']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['hsts_preload']) + ), ) - ) + ), ) ) ); From 41c07d5b71da94808e70c154b526960270611dc8 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 7 Oct 2016 11:54:08 +0200 Subject: [PATCH 05/62] also add new hsts panel settings to froxlor.sql for new installs; refs #1660 Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 63ce8661..c09e74a3 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -254,7 +254,7 @@ CREATE TABLE `panel_domains` ( `letsencrypt` tinyint(1) NOT NULL default '0', `hsts` varchar(10) NOT NULL default '0', `hsts_sub` tinyint(1) NOT NULL default '0', - `hsts_preload` tinyint(1) NOT NULL default '1', + `hsts_preload` tinyint(1) NOT NULL default '0', PRIMARY KEY (`id`), KEY `customerid` (`customerid`), KEY `parentdomain` (`parentdomainid`), @@ -542,6 +542,9 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'mail_smtp_auth', '1'), ('system', 'mail_smtp_user', ''), ('system', 'mail_smtp_passwd', ''), + ('system', 'hsts_maxage', '0'), + ('system', 'hsts_sub', '0'), + ('system', 'hsts_preload', '0'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin@SERVERNAME'), ('panel', 'phpmyadmin_url', ''), From 06e44b6e2b17949f40c8ba365ba451b47f4af9a7 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 7 Oct 2016 16:07:23 +0200 Subject: [PATCH 06/62] fix sql-query in customer_domains when updating domain Signed-off-by: Michael Kaufmann (d00p) --- customer_domains.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/customer_domains.php b/customer_domains.php index e79af357..d96d4fa0 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -695,7 +695,7 @@ if ($page == 'overview') { `letsencrypt`= :letsencrypt, `hsts` = :hsts, `hsts_sub` = :hsts_sub, - `hsts_preload` = :hsts_preload, + `hsts_preload` = :hsts_preload WHERE `customerid`= :customerid AND `id`= :id" ); From f1f7d7dd14814df2cc146e50c633d7ee3b26ac8b Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 7 Oct 2016 16:11:23 +0200 Subject: [PATCH 07/62] add db-version to error-reporting Signed-off-by: Michael Kaufmann (d00p) --- admin_index.php | 3 ++- customer_index.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/admin_index.php b/admin_index.php index a6247d05..177278bf 100644 --- a/admin_index.php +++ b/admin_index.php @@ -369,7 +369,8 @@ if ($page == 'overview') { $mail_body .= "File: ".$_error['file'].':'.$_error['line']."\n\n"; $mail_body .= "Trace:\n".trim($_error['trace'])."\n\n"; $mail_body .= "-------------------------------------------------------------\n\n"; - $mail_body .= "Froxlor-version: ".$version."\n\n"; + $mail_body .= "Froxlor-version: ".$version."\n"; + $mail_body .= "DB-version: ".$dbversion."\n\n"; $mail_body .= "End of report"; $mail_html = nl2br($mail_body); diff --git a/customer_index.php b/customer_index.php index 25f390dd..5e6c2aaf 100644 --- a/customer_index.php +++ b/customer_index.php @@ -274,7 +274,8 @@ if ($page == 'overview') { $mail_body .= "File: ".$_error['file'].':'.$_error['line']."\n\n"; $mail_body .= "Trace:\n".trim($_error['trace'])."\n\n"; $mail_body .= "-------------------------------------------------------------\n\n"; - $mail_body .= "Froxlor-version: ".$version."\n\n"; + $mail_body .= "Froxlor-version: ".$version."\n"; + $mail_body .= "DB-version: ".$dbversion."\n\n"; $mail_body .= "End of report"; $mail_html = str_replace("\n", "
", $mail_body); From 75d8d0b39752dfb40d9c128f247ac87c6caf5ea5 Mon Sep 17 00:00:00 2001 From: Florian Aders Date: Fri, 7 Oct 2016 19:08:32 +0200 Subject: [PATCH 08/62] Fix sslsettings in hsts for nginx --- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index 3a79d610..6c454e12 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -608,14 +608,14 @@ class nginx extends HttpConfigBase } if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] >= 0) { - $vhost_content .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; + $sslsettings .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; if ($domain_or_ip['hsts_sub'] == 1) { - $vhost_content .= '; includeSubDomains'; + $sslsettings .= '; includeSubDomains'; } if ($domain_or_ip['hsts_preload'] == 1) { - $vhost_content .= '; preload'; + $sslsettings .= '; preload'; } - $vhost_content .= '";' . "\n"; + $sslsettings .= '";' . "\n"; } } } From 91c2d4efbe1dc1ea852b2d9e327d2712e31c96aa Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 11 Oct 2016 07:49:52 +0200 Subject: [PATCH 09/62] do not redirect when requesting let's encrypt certificates in nginx (same as we do in apache) Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index 6c454e12..6f765162 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -217,7 +217,9 @@ class nginx extends HttpConfigBase } else { $_sslport = $this->checkAlternativeSslPort(); $mypath = 'https://' . Settings::Get('system.hostname') . $_sslport . '/'; - $this->nginx_data[$vhost_filename] .= "\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'if ($request_uri !~ "^/\.well-known/acme-challenge/\w+$") {' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; } } @@ -458,7 +460,9 @@ class nginx extends HttpConfigBase if (substr($uri, - 1) == '/') { $uri = substr($uri, 0, - 1); } - $vhost_content .= "\t" . 'return 301 ' . $uri . '$request_uri;' . "\n"; + $vhost_content .= "\t" . 'if ($request_uri !~ "^/\.well-known/acme-challenge/\w+$") {' . "\n"; + $vhost_content .= "\t\t" . 'return 301 ' . $uri . '$request_uri;' . "\n"; + $vhost_content .= "\t" . '}' . "\n"; } else { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); From 58c14376d6839e6d85257a9f5e16b8ec3a684c24 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 11 Oct 2016 07:50:25 +0200 Subject: [PATCH 10/62] set version to 0.9.38-rc1 for upcoming release candidate Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 6 ++++++ lib/version.inc.php | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index c09e74a3..c17abf45 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -575,7 +575,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_numeric', '0'), ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), - ('panel', 'version', '0.9.37'), + ('panel', 'version', '0.9.38-rc1'), ('panel', 'db_version', '201610070'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 66fea160..3767ec8a 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3501,3 +3501,9 @@ if (isDatabaseVersion('201609240')) { updateToDbVersion('201610070'); } + +if (isFroxlorVersion('0.9.37')) { + + showUpdateStep("Updating from 0.9.37 to 0.9.38-rc1", false); + updateToVersion('0.9.38-rc1'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index 52a85722..7fa046a2 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.37'; +$version = '0.9.38-rc1'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201610070'; From fc2ae594cbf2da6e96e954fc18c893a50941ba5a Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 13 Oct 2016 09:51:57 +0200 Subject: [PATCH 11/62] enable custom redirect codes also for nginx Signed-off-by: Michael Kaufmann (d00p) --- lib/formfields/customer/domains/formfield.domains_add.php | 2 +- lib/formfields/customer/domains/formfield.domains_edit.php | 2 +- scripts/jobs/cron_tasks.inc.http.10.apache.php | 2 ++ scripts/jobs/cron_tasks.inc.http.30.nginx.php | 7 ++++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index e25302b0..714a3eb9 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -54,7 +54,7 @@ return array( 'type' => 'text' ), 'redirectcode' => array( - 'visible' => ((Settings::Get('system.webserver') == 'apache2' && Settings::Get('customredirect.enabled') == '1') ? true : false), + 'visible' => ((Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('customredirect.enabled') == '1') ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index 2e753e21..dc3403fd 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -54,7 +54,7 @@ return array( 'value' => $urlvalue ), 'redirectcode' => array( - 'visible' => ((Settings::Get('system.webserver') == 'apache2' && Settings::Get('customredirect.enabled') == '1') ? true : false), + 'visible' => ((Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('customredirect.enabled') == '1') ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 07ec5752..8fce5cc0 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -862,6 +862,8 @@ class apache extends HttpConfigBase if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $corrected_docroot = $this->idnaConvert->encode_uri($domain['documentroot']); + // prevent empty return-cde + $code = "301"; // Get domain's redirect code $code = getDomainRedirectCode($domain['id']); $modrew_red = ''; diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index 6f765162..a9e2c457 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -460,8 +460,13 @@ class nginx extends HttpConfigBase if (substr($uri, - 1) == '/') { $uri = substr($uri, 0, - 1); } + // prevent empty return-cde + $code = "301"; + // Get domain's redirect code + $code = getDomainRedirectCode($domain['id']); + $vhost_content .= "\t" . 'if ($request_uri !~ "^/\.well-known/acme-challenge/\w+$") {' . "\n"; - $vhost_content .= "\t\t" . 'return 301 ' . $uri . '$request_uri;' . "\n"; + $vhost_content .= "\t\t" . 'return ' . $code .' ' . $uri . '$request_uri;' . "\n"; $vhost_content .= "\t" . '}' . "\n"; } else { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); From ce31a0b3fdd67835396a66944e4e0d87c1d64ca3 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 13 Oct 2016 10:16:17 +0200 Subject: [PATCH 12/62] enable custom redirect codes also for lighttpd Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/130.webserver.php | 12 ++---------- .../customer/domains/formfield.domains_add.php | 2 +- .../customer/domains/formfield.domains_edit.php | 2 +- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 9 ++++++++- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php index b6cfc9a8..4374b148 100644 --- a/actions/admin/settings/130.webserver.php +++ b/actions/admin/settings/130.webserver.php @@ -260,11 +260,7 @@ return array( 'varname' => 'enabled', 'type' => 'bool', 'default' => false, - 'save_method' => 'storeSettingField', - 'websrv_avail' => array( - 'apache2', - 'lighttpd' - ) + 'save_method' => 'storeSettingField' ), 'customredirect_default' => array( 'label' => $lng['serversettings']['customredirect_default'], @@ -274,11 +270,7 @@ return array( 'default' => '1', 'option_mode' => 'one', 'option_options_method' => 'getRedirectCodes', - 'save_method' => 'storeSettingField', - 'websrv_avail' => array( - 'apache2', - 'lighttpd' - ) + 'save_method' => 'storeSettingField' ) ) ) diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index 714a3eb9..fb9adc47 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -54,7 +54,7 @@ return array( 'type' => 'text' ), 'redirectcode' => array( - 'visible' => ((Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('customredirect.enabled') == '1') ? true : false), + 'visible' => (Settings::Get('customredirect.enabled') == '1' ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index dc3403fd..2a7b593b 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -54,7 +54,7 @@ return array( 'value' => $urlvalue ), 'redirectcode' => array( - 'visible' => ((Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('customredirect.enabled') == '1') ? true : false), + 'visible' => (Settings::Get('customredirect.enabled') == '1' ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 651f80db..7c38b3c6 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -429,8 +429,15 @@ class lighttpd extends HttpConfigBase $domain['documentroot'] = trim($domain['documentroot']); if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { + $uri = $this->idnaConvert->encode_uri($domain['documentroot']); + // prevent empty return-cde + $code = "301"; + // Get domain's redirect code + $code = getDomainRedirectCode($domain['id']); + + $vhost_content .= ' url.redirect-code = ' . $code. "\n"; $vhost_content .= ' url.redirect = (' . "\n"; - $vhost_content .= ' "^/(.*)$" => "' . $this->idnaConvert->encode_uri($domain['documentroot']) . '$1"' . "\n"; + $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; $vhost_content .= ' )' . "\n"; } else { From f406962dfd2b2ea63ee75c4f46d4058b8785cd8e Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 13 Oct 2016 10:48:28 +0200 Subject: [PATCH 13/62] allow empty select-value for panel.customer_hide_options Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/100.panel.php | 1 + .../formfields/option/function.validateFormFieldOption.php | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/actions/admin/settings/100.panel.php b/actions/admin/settings/100.panel.php index 9a262377..49308bed 100644 --- a/actions/admin/settings/100.panel.php +++ b/actions/admin/settings/100.panel.php @@ -234,6 +234,7 @@ return array( 'type' => 'option', 'default' => '', 'option_mode' => 'multiple', + 'option_emptyallowed' => true, 'option_options' => array( 'email' => $lng['menue']['email']['email'], 'mysql' => $lng['menue']['mysql']['mysql'], diff --git a/lib/functions/formfields/option/function.validateFormFieldOption.php b/lib/functions/formfields/option/function.validateFormFieldOption.php index bbfa80ff..cbda0408 100644 --- a/lib/functions/formfields/option/function.validateFormFieldOption.php +++ b/lib/functions/formfields/option/function.validateFormFieldOption.php @@ -20,7 +20,7 @@ function validateFormFieldOption($fieldname, $fielddata, $newfieldvalue) { $returnvalue = true; - + if(isset($fielddata['option_mode']) && $fielddata['option_mode'] == 'multiple') { $options = explode(',', $newfieldvalue); @@ -33,13 +33,16 @@ function validateFormFieldOption($fieldname, $fielddata, $newfieldvalue) { $returnvalue = isset($fielddata['option_options'][$newfieldvalue]); } - + if($returnvalue === true) { return true; } else { + if (isset($fielddata['option_emptyallowed']) && $fielddata['option_emptyallowed']) { + return true; + } return 'not in option'; } } From 3597a89da30f17dcf4d6a59ce3d7534397d68c05 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 13 Oct 2016 11:08:26 +0200 Subject: [PATCH 14/62] add missing customer_hide_option for fresh installs Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/install/froxlor.sql b/install/froxlor.sql index c17abf45..840d6301 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -575,6 +575,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_numeric', '0'), ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), + ('panel', 'customer_hide_options', ''), ('panel', 'version', '0.9.38-rc1'), ('panel', 'db_version', '201610070'); From 2bee58166b5b3e9d4005b0ae4c45e07e23e56667 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 18 Oct 2016 09:07:20 +0200 Subject: [PATCH 15/62] show also Subject-alternative-names in ssl-overview Signed-off-by: Michael Kaufmann (d00p) --- ssl_certificates.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ssl_certificates.php b/ssl_certificates.php index bfe81553..9733faf4 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -119,6 +119,18 @@ if (count($all_certs) == 0) { $isValid = false; } + $san_list = ""; + if (isset($cert_data['extensions']['subjectAltName']) && !empty($cert_data['extensions']['subjectAltName'])) { + $SANs = explode(",", $cert_data['extensions']['subjectAltName']); + $SANs = array_map('trim', $SANs); + foreach ($SANs as $san) { + $san = str_replace("DNS:", "", $san); + if ($san != $cert_data['subject']['CN'] && strpos($san, "othername:") === false) { + $san_list .= $san."
"; + } + } + } + $row = htmlentities_array($cert); eval("\$certificates.=\"" . getTemplate("ssl_certificates/certs_cert", true) . "\";"); } else { From 979b1b0ad836fd5238a6ec564716479740c760f2 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 18 Oct 2016 13:23:35 +0200 Subject: [PATCH 16/62] forgot to add template for subjectAlternativeName stuff in ssl-overview Signed-off-by: Michael Kaufmann (d00p) --- templates/Sparkle/ssl_certificates/certs_cert.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/Sparkle/ssl_certificates/certs_cert.tpl b/templates/Sparkle/ssl_certificates/certs_cert.tpl index 90d502fa..250a57f1 100644 --- a/templates/Sparkle/ssl_certificates/certs_cert.tpl +++ b/templates/Sparkle/ssl_certificates/certs_cert.tpl @@ -5,6 +5,7 @@ {$cert_data['subject']['CN']} +
SAN: {$san_list}
{$cert_data['issuer']['O']} From b4e8458076b0773d766f0282f4ae80511cece7dc Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 18 Oct 2016 15:32:14 +0200 Subject: [PATCH 17/62] enhance findDirs function and filter awstats/webalizer (sub)folders for target-directory selection Signed-off-by: Michael Kaufmann (d00p) --- lib/functions/filedir/function.findDirs.php | 75 +++++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/lib/functions/filedir/function.findDirs.php b/lib/functions/filedir/function.findDirs.php index 8d1c0669..fb8f57e5 100644 --- a/lib/functions/filedir/function.findDirs.php +++ b/lib/functions/filedir/function.findDirs.php @@ -17,27 +17,57 @@ * */ + /** * Returns an array of found directories * * This function checks every found directory if they match either $uid or $gid, if they do * the found directory is valid. It uses recursive-iterators to find subdirectories. * - * @param string $path the path to start searching in - * @param int $uid the uid which must match the found directories - * @param int $gid the gid which must match the found direcotries + * @param string $path + * the path to start searching in + * @param int $uid + * the uid which must match the found directories + * @param int $gid + * the gid which must match the found direcotries * * @return array Array of found valid paths */ -function findDirs($path, $uid, $gid) { - - $_fileList = array (); +function findDirs($path, $uid, $gid) +{ + $_fileList = array(); $path = makeCorrectDir($path); // valid directory? if (is_dir($path)) { + + // Will exclude everything under these directories + $exclude = array( + 'awstats', + 'webalizer' + ); + + /** + * + * @param SplFileInfo $file + * @param mixed $key + * @param RecursiveCallbackFilterIterator $iterator + * @return bool True if you need to recurse or if the item is acceptable + */ + $filter = function ($file, $key, $iterator) use ($exclude) { + if (in_array($file->getFilename(), $exclude)) { + return false; + } + return true; + }; + // create RecursiveIteratorIterator - $its = new RecursiveIteratorIterator(new IgnorantRecursiveDirectoryIterator($path)); + $its = new RecursiveIteratorIterator( + new RecursiveCallbackFilterIterator( + new IgnorantRecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), + $filter + ) + ); // we can limit the recursion-depth, but will it be helpful or // will people start asking "why do I only see 2 subdirectories, i want to use /a/b/c" // let's keep this in mind and see whether it will be useful @@ -50,24 +80,27 @@ function findDirs($path, $uid, $gid) { $_fileList[] = makeCorrectDir(dirname($fullFileName)); } } + $_fileList[] = $path; } return array_unique($_fileList); - } /** -* If you use RecursiveDirectoryIterator with RecursiveIteratorIterator and run -* into UnexpectedValueException you may use this little hack to ignore those -* directories, such as lost+found on linux. -* (User "antennen" @ http://php.net/manual/en/class.recursivedirectoryiterator.php#101654) -**/ -class IgnorantRecursiveDirectoryIterator extends RecursiveDirectoryIterator { - function getChildren() { - try { - return new IgnorantRecursiveDirectoryIterator($this->getPathname()); - } catch(UnexpectedValueException $e) { - return new RecursiveArrayIterator(array()); - } - } + * If you use RecursiveDirectoryIterator with RecursiveIteratorIterator and run + * into UnexpectedValueException you may use this little hack to ignore those + * directories, such as lost+found on linux. + * (User "antennen" @ http://php.net/manual/en/class.recursivedirectoryiterator.php#101654) + */ +class IgnorantRecursiveDirectoryIterator extends RecursiveDirectoryIterator +{ + + function getChildren() + { + try { + return new IgnorantRecursiveDirectoryIterator($this->getPathname()); + } catch (UnexpectedValueException $e) { + return new RecursiveArrayIterator(array()); + } + } } From fa45de6586a489bf84915ace9e04f170ad6e255f Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Wed, 19 Oct 2016 19:22:52 +0200 Subject: [PATCH 18/62] fix empty dir parameter for makeCorrectDir() when directory-selection is set to 'Dropdown', thx to D2Red for letting me debug on his system Signed-off-by: Michael Kaufmann (d00p) --- lib/functions/filedir/function.makeCorrectDir.php | 2 +- lib/functions/filedir/function.makePathfield.php | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/functions/filedir/function.makeCorrectDir.php b/lib/functions/filedir/function.makeCorrectDir.php index f457818b..75dc00d1 100644 --- a/lib/functions/filedir/function.makeCorrectDir.php +++ b/lib/functions/filedir/function.makeCorrectDir.php @@ -26,7 +26,7 @@ */ function makeCorrectDir($dir) { - assert('is_string($dir) && strlen($dir) > 0 /* $dir does not look like an actual folder name */'); + assert('is_string($dir) && strlen($dir) > 0', 'Value "' . $dir .'" does not look like an actual folder name'); $dir = trim($dir); diff --git a/lib/functions/filedir/function.makePathfield.php b/lib/functions/filedir/function.makePathfield.php index 3cc8c762..c5815dfe 100644 --- a/lib/functions/filedir/function.makePathfield.php +++ b/lib/functions/filedir/function.makePathfield.php @@ -64,7 +64,12 @@ function makePathfield($path, $uid, $gid, $value = '', $dom = false) { $_field = ''; foreach ($dirList as $key => $dir) { if (strpos($dir, $path) === 0) { - $dir = makeCorrectDir(substr($dir, strlen($path))); + $dir = substr($dir, strlen($path)); + // docroot cut off of current directory == empty -> directory is the docroot + if (empty($dir)) { + $dir = '/'; + } + $dir = makeCorrectDir($dir); } $_field.= makeoption($dir, $dir, $value); } From af77453bfe2e7163bd1167bb53fe72d0bd29f73e Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 20 Oct 2016 09:23:44 +0200 Subject: [PATCH 19/62] do not generate ssl-vhost-container without a certificate Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.10.apache.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 8fce5cc0..a39c068d 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -183,6 +183,10 @@ class apache extends HttpConfigBase } if ($row_ipsandports['vhostcontainer'] == '1') { + + $without_vhost = $this->virtualhosts_data[$vhosts_filename]; + $close_vhost = true; + $this->virtualhosts_data[$vhosts_filename] .= '' . "\n"; $mypath = $this->getMyPath($row_ipsandports); @@ -332,7 +336,7 @@ class apache extends HttpConfigBase 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'guid' => Settings::Get('system.httpuser'), + 'guid' => Settings::Get('system.httpuser'), 'openbasedir' => 0, 'email' => Settings::Get('panel.adminmail'), 'loginname' => 'froxlor.panel', @@ -443,10 +447,19 @@ class apache extends HttpConfigBase } } } + } else { + // if there is no cert-file specified but we are generating a ssl-vhost, + // we should return an empty string because this vhost would suck dick, ref #1583 + $this->logger->logAction(CRON_ACTION, LOG_ERR, $domain['domain'] . ' :: empty certificate file! Cannot create ssl-directives'); + $this->virtualhosts_data[$vhosts_filename] = $without_vhost; + $this->virtualhosts_data[$vhosts_filename] .= '# no ssl-certificate was specified for this domain, therefore no explicit vhost-container is being generated'; + $close_vhost = false; } } - $this->virtualhosts_data[$vhosts_filename] .= '' . "\n"; + if ($close_vhost) { + $this->virtualhosts_data[$vhosts_filename] .= '' . "\n"; + } $this->logger->logAction(CRON_ACTION, LOG_DEBUG, $ipport . ' :: inserted vhostcontainer'); } unset($vhosts_filename); From 884b2ed9137cf4d68b2875f86bd6bdd597be6932 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 25 Oct 2016 12:24:57 +0200 Subject: [PATCH 20/62] various fixes for idn converted domains + fix undefined index alias when editing a domain with alias Signed-off-by: Michael Kaufmann (d00p) --- admin_domains.php | 2 +- scripts/jobs/cron_tasks.inc.http.10.apache.php | 18 +++++++++--------- ssl_certificates.php | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index 99dc415d..e1bbff05 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -1227,7 +1227,7 @@ if ($page == 'domains' || $page == 'overview') { $adminid = $result['adminid']; } - $aliasdomain = intval($_POST['alias']); + $aliasdomain = isset($_POST['alias']) ? intval($_POST['alias']) : 0; $issubof = intval($_POST['issubof']); $subcanemaildomain = intval($_POST['subcanemaildomain']); $caneditdomain = isset($_POST['caneditdomain']) ? intval($_POST['caneditdomain']) : 0; diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index a39c068d..95be0e1c 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -1,5 +1,4 @@ -Part (starter is created in apache_fcgid) if (Settings::Get('system.mod_fcgid_ownvhost') == '1' && Settings::Get('system.mod_fcgid') == '1') { $configdir = makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname')); @@ -278,13 +277,14 @@ class apache extends HttpConfigBase } $this->virtualhosts_data[$vhosts_filename] .= ' ' . "\n"; } - } // create php-fpm -Part (config is created in apache_fcgid) + } elseif (Settings::Get('phpfpm.enabled') == '1') { + // create php-fpm -Part (config is created in apache_fcgid) $domain = array( 'id' => 'none', 'domain' => Settings::Get('system.hostname'), 'adminid' => 1, /* first admin-user (superadmin) */ - 'mod_fcgid_starter' => - 1, + 'mod_fcgid_starter' => - 1, 'mod_fcgid_maxrequests' => - 1, 'guid' => Settings::Get('phpfpm.vhost_httpuser'), 'openbasedir' => 0, @@ -615,10 +615,10 @@ class apache extends HttpConfigBase } else { $stats_text .= ' Alias /webalizer "' . makeCorrectFile($domain['customerroot'] . '/webalizer') . '"' . "\n"; } - } // if the docroots are equal, we still have to set an alias for awstats - // because the stats are in /awstats/[domain], not just /awstats/ - // also, the awstats-icons are someplace else too! - // -> webalizer does not need this! + } // if the docroots are equal, we still have to set an alias for awstats + // because the stats are in /awstats/[domain], not just /awstats/ + // also, the awstats-icons are someplace else too! + // -> webalizer does not need this! elseif (Settings::Get('system.awstats_enabled') == '1') { $stats_text .= ' Alias /awstats "' . makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; $stats_text .= ' Alias /awstats-icon "' . makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; @@ -873,7 +873,7 @@ class apache extends HttpConfigBase $domain['documentroot'] = trim($domain['documentroot']); if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { - $corrected_docroot = $this->idnaConvert->encode_uri($domain['documentroot']); + $corrected_docroot = $domain['documentroot']; // prevent empty return-cde $code = "301"; diff --git a/ssl_certificates.php b/ssl_certificates.php index 9733faf4..8c59c63b 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -96,7 +96,7 @@ if (count($all_certs) == 0) { $cert_data = openssl_x509_parse($cert['ssl_cert_file']); - $cert['domain'] = $idna_convert->encode($cert['domain']); + $cert['domain'] = $idna_convert->decode($cert['domain']); $adminCustomerLink = ""; if (AREA == 'admin') { From 462fca732801e8ea26d4adc483a8e328d945516c Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 28 Oct 2016 10:57:51 +0200 Subject: [PATCH 21/62] do not add www.[froxlorfqdn] to SAN list of certificate request for Let's Encrypt froxlor-vhost certificate; fixes #1662 Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_letsencrypt.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/jobs/cron_letsencrypt.php b/scripts/jobs/cron_letsencrypt.php index 8df9055f..2101fcca 100644 --- a/scripts/jobs/cron_letsencrypt.php +++ b/scripts/jobs/cron_letsencrypt.php @@ -141,8 +141,7 @@ if (Settings::Get('system.le_froxlor_enabled') == '1') { if ($insert_or_update_required) { $domains = array( - $certrow['domain'], - 'www.' . $certrow['domain'] + $certrow['domain'] ); // Only renew let's encrypt certificate if no broken ssl_redirect is enabled From 304926260fbd6479329cafbfd2e938c0fb2fe378 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sat, 29 Oct 2016 14:20:50 +0200 Subject: [PATCH 22/62] PowerDNS does not like multi-line-format, thx to Marc Signed-off-by: Michael Kaufmann (d00p) --- lib/functions/dns/function.createDomainZone.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/functions/dns/function.createDomainZone.php b/lib/functions/dns/function.createDomainZone.php index 938d7200..ad21ee45 100644 --- a/lib/functions/dns/function.createDomainZone.php +++ b/lib/functions/dns/function.createDomainZone.php @@ -275,13 +275,11 @@ function createDomainZone($domain_id, $froxlorhostname = false, $isMainButSubTo Database::pexecute($upd_stmt, array('serial' => $domain['bindserial'], 'id' => $domain['id'])); } - $soa_content = $primary_ns . " " . escapeSoaAdminMail(Settings::Get('panel.adminmail')) . " (" . PHP_EOL; - $soa_content .= $domain['bindserial'] . "\t; serial" . PHP_EOL; + // PowerDNS does not like multi-line-format + $soa_content = $primary_ns . " " . escapeSoaAdminMail(Settings::Get('panel.adminmail')) . " "; + $soa_content .= $domain['bindserial'] . " "; // TODO for now, dummy time-periods - $soa_content .= "1800\t; refresh (30 mins)" . PHP_EOL; - $soa_content .= "900\t; retry (15 mins)" . PHP_EOL; - $soa_content .= "604800\t; expire (7 days)" . PHP_EOL; - $soa_content .= "1200\t)\t; minimum (20 mins)"; + $soa_content .= "1800 900 604800 1200"; $soa_record = new DnsEntry('@', 'SOA', $soa_content); array_unshift($zonerecords, $soa_record); From a44be363a67881b1e3655aa80cadf57ee2bc1d33 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Mon, 31 Oct 2016 10:53:18 +0100 Subject: [PATCH 23/62] set domain, letsencrypt-flag and loginname for froxlor-hostname in ssl-overview because the certificate will get removed as invalid otherwise, thx to Tbyte Signed-off-by: Michael Kaufmann (d00p) --- ssl_certificates.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ssl_certificates.php b/ssl_certificates.php index 8c59c63b..0d4f9c03 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -86,11 +86,21 @@ if (count($all_certs) == 0) { foreach ($all_certs as $idx => $cert) { if ($paging->checkDisplay($idx)) { + // respect froxlor-hostname + if ($cert['domainid'] == 0) { + $cert['domain'] = Settings::Get('system.hostname'); + $cert['letsencrypt'] = Settings::Get('system.le_froxlor_enabled'); + $cert['loginname'] = 'froxlor.panel'; + } + if (empty($cert['domain']) || empty($cert['ssl_cert_file'])) { // no domain found to the entry or empty entry - safely delete it from the DB + /* Database::pexecute($del_stmt, array( 'id' => $cert['id'] )); + */ + echo "no domain found to the entry or empty entry - safely delete it from the DB"; continue; } @@ -99,7 +109,7 @@ if (count($all_certs) == 0) { $cert['domain'] = $idna_convert->decode($cert['domain']); $adminCustomerLink = ""; - if (AREA == 'admin') { + if (AREA == 'admin' && $cert['domainid'] > 0) { if (! empty($cert['loginname'])) { $adminCustomerLink = ' ( Date: Mon, 31 Oct 2016 11:17:56 +0100 Subject: [PATCH 24/62] disable tlsv1.1 for ssl settings Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.10.apache.php | 4 ++-- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 4 ++++ scripts/jobs/cron_tasks.inc.http.30.nginx.php | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 95be0e1c..30644a56 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -412,7 +412,7 @@ class apache extends HttpConfigBase } else { $this->virtualhosts_data[$vhosts_filename] .= ' SSLEngine On' . "\n"; - $this->virtualhosts_data[$vhosts_filename] .= ' SSLProtocol ALL -SSLv2 -SSLv3' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLProtocol -ALL +TLSv1.0 +TLSv1.2' . "\n"; // this makes it more secure, thx to Marcel (08/2013) $this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; @@ -830,7 +830,7 @@ class apache extends HttpConfigBase if ($domain['ssl_cert_file'] != '') { $vhost_content .= ' SSLEngine On' . "\n"; - $vhost_content .= ' SSLProtocol ALL -SSLv2 -SSLv3' . "\n"; + $vhost_content .= ' SSLProtocol -ALL +TLSv1.0 +TLSv1.2' . "\n"; // this makes it more secure, thx to Marcel (08/2013) $vhost_content .= ' SSLHonorCipherOrder On' . "\n"; $vhost_content .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 7c38b3c6..a8cd208e 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -210,7 +210,9 @@ class lighttpd extends HttpConfigBase echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create SSL-directives' . "\n"; } else { $this->lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n"; + $this->lighttpd_data[$vhost_filename] .= 'ssl.use-compression = "disable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.use-sslv2 = "disable"' . "\n"; + $this->lighttpd_data[$vhost_filename] .= 'ssl.use-sslv3 = "disable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.cipher-list = "' . Settings::Get('system.ssl_cipher_list') . '"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.honor-cipher-order = "enable"' . "\n"; $this->lighttpd_data[$vhost_filename] .= 'ssl.pemfile = "' . makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; @@ -517,7 +519,9 @@ class lighttpd extends HttpConfigBase if ($domain['ssl_cert_file'] != '') { $ssl_settings .= 'ssl.engine = "enable"' . "\n"; + $ssl_settings .= 'ssl.use-compression = "disable"' . "\n"; $ssl_settings .= 'ssl.use-sslv2 = "disable"' . "\n"; + $ssl_settings .= 'ssl.use-sslv3 = "disable"' . "\n"; $ssl_settings .= 'ssl.cipher-list = "' . Settings::Get('system.ssl_cipher_list') . '"' . "\n"; $ssl_settings .= 'ssl.honor-cipher-order = "enable"' . "\n"; $ssl_settings .= 'ssl.pemfile = "' . makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index a9e2c457..d4baa6c8 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -601,7 +601,7 @@ class nginx extends HttpConfigBase } else { // obsolete: ssl on now belongs to the listen block as 'ssl' at the end // $sslsettings .= "\t" . 'ssl on;' . "\n"; - $sslsettings .= "\t" . 'ssl_protocols TLSv1 TLSv1.1 TLSv1.2;' . "\n"; + $sslsettings .= "\t" . 'ssl_protocols TLSv1 TLSv1.2;' . "\n"; $sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n"; $sslsettings .= "\t" . 'ssl_ecdh_curve secp384r1;' . "\n"; $sslsettings .= "\t" . 'ssl_prefer_server_ciphers on;' . "\n"; From ec6ddd054dde84d316d38fab96bc996baddaf883 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Mon, 31 Oct 2016 11:18:40 +0100 Subject: [PATCH 25/62] remove certificate entry for LE if admin/customer disables LE for a domain Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/122.froxlorvhost.php | 2 +- admin_domains.php | 18 ++++++++- customer_domains.php | 19 +++++++--- ...function.storeSettingClearCertificates.php | 37 +++++++++++++++++++ 4 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 lib/functions/settings/function.storeSettingClearCertificates.php diff --git a/actions/admin/settings/122.froxlorvhost.php b/actions/admin/settings/122.froxlorvhost.php index e92fa582..75e138b4 100644 --- a/actions/admin/settings/122.froxlorvhost.php +++ b/actions/admin/settings/122.froxlorvhost.php @@ -39,7 +39,7 @@ return array( 'varname' => 'le_froxlor_enabled', 'type' => 'bool', 'default' => false, - 'save_method' => 'storeSettingField', + 'save_method' => 'storeSettingClearCertificates', 'visible' => Settings::Get('system.leenabled') ), 'system_le_froxlor_redirect' => array( diff --git a/admin_domains.php b/admin_domains.php index e1bbff05..42125117 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -1081,8 +1081,12 @@ if ($page == 'domains' || $page == 'overview') { } elseif ($action == 'edit' && $id != 0) { $result_stmt = Database::prepare(" - SELECT `d`.*, `c`.`customerid` FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) - WHERE `d`.`parentdomainid` = '0' AND `d`.`id` = :id" . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid")); + SELECT `d`.*, `c`.`customerid` + FROM `" . TABLE_PANEL_DOMAINS . "` `d` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) + WHERE `d`.`parentdomainid` = '0' + AND `d`.`id` = :id" . ($userinfo['customers_see_all'] ? '' : " AND `d`.`adminid` = :adminid") + ); $params = array( 'id' => $id ); @@ -1640,6 +1644,16 @@ if ($page == 'domains' || $page == 'overview') { $log->logAction(ADM_ACTION, LOG_NOTICE, "deleted domain #" . $id . " from mail-tables"); } + // check whether LE has been disabled, so we remove the certificate + if ($letsencrypt == '0' && $result['letsencrypt'] == '1') { + $del_stmt = Database::prepare(" + DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :id + "); + Database::pexecute($del_stmt, array( + 'id' => $id + )); + } + $updatechildren = ''; if ($subcanemaildomain == '0' && $result['subcanemaildomain'] != '0') { diff --git a/customer_domains.php b/customer_domains.php index d96d4fa0..43e444af 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -720,11 +720,20 @@ if ($page == 'overview') { // trigger when domain id for alias destination has changed: both for old and new destination triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $log); triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log); - } else - if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { - // or when wwwserveralias or letsencrypt was changed - triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log); - } + } elseif ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) { + // or when wwwserveralias or letsencrypt was changed + triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log); + } + + // check whether LE has been disabled, so we remove the certificate + if ($letsencrypt == '0' && $result['letsencrypt'] == '1') { + $del_stmt = Database::prepare(" + DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = :id + "); + Database::pexecute($del_stmt, array( + 'id' => $id + )); + } inserttask('1'); diff --git a/lib/functions/settings/function.storeSettingClearCertificates.php b/lib/functions/settings/function.storeSettingClearCertificates.php new file mode 100644 index 00000000..32d19944 --- /dev/null +++ b/lib/functions/settings/function.storeSettingClearCertificates.php @@ -0,0 +1,37 @@ + (2010-) +* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt +* @package Functions +* +*/ + +function storeSettingClearCertificates($fieldname, $fielddata, $newfieldvalue) { + + $returnvalue = storeSettingField($fieldname, $fielddata, $newfieldvalue); + + if ($returnvalue !== false + && is_array($fielddata) + && isset($fielddata['settinggroup']) + && $fielddata['settinggroup'] == 'system' + && isset($fielddata['varname']) + && $fielddata['varname'] == 'le_froxlor_enabled' + && $newfieldvalue == '0' + ) { + Database::query(" + DELETE FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` WHERE `domainid` = '0' + "); + } + + return $returnvalue; +} From 60c1babd93b4db6663e507a34f56f551e5db2b1f Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Mon, 31 Oct 2016 20:44:31 +0100 Subject: [PATCH 26/62] fix wrong protocol name for apache Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.10.apache.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 30644a56..156435a3 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -412,7 +412,7 @@ class apache extends HttpConfigBase } else { $this->virtualhosts_data[$vhosts_filename] .= ' SSLEngine On' . "\n"; - $this->virtualhosts_data[$vhosts_filename] .= ' SSLProtocol -ALL +TLSv1.0 +TLSv1.2' . "\n"; + $this->virtualhosts_data[$vhosts_filename] .= ' SSLProtocol -ALL +TLSv1 +TLSv1.2' . "\n"; // this makes it more secure, thx to Marcel (08/2013) $this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; @@ -830,7 +830,7 @@ class apache extends HttpConfigBase if ($domain['ssl_cert_file'] != '') { $vhost_content .= ' SSLEngine On' . "\n"; - $vhost_content .= ' SSLProtocol -ALL +TLSv1.0 +TLSv1.2' . "\n"; + $vhost_content .= ' SSLProtocol -ALL +TLSv1 +TLSv1.2' . "\n"; // this makes it more secure, thx to Marcel (08/2013) $vhost_content .= ' SSLHonorCipherOrder On' . "\n"; $vhost_content .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; From 4274b8a73764b85dc4e40a6d5407872dbbfd6f67 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 3 Nov 2016 10:52:33 +0100 Subject: [PATCH 27/62] fix setting of hsts values when security questions are asked; insert config-rebuild task if only hsts stuff changes; fix undefined variable regarding alias domain Signed-off-by: Michael Kaufmann (d00p) --- admin_domains.php | 16 ++++++++-------- customer_domains.php | 8 ++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/admin_domains.php b/admin_domains.php index 42125117..0f86f7b6 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -777,7 +777,7 @@ if ($page == 'domains' || $page == 'overview') { 'termination_date' => $termination_date, 'issubof' => $issubof, 'letsencrypt' => $letsencrypt, - 'hsts' => $hsts_maxage, + 'hsts_maxage' => $hsts_maxage, 'hsts_sub' => $hsts_sub, 'hsts_preload' => $hsts_preload ); @@ -1402,6 +1402,11 @@ if ($page == 'domains' || $page == 'overview') { $letsencrypt = (int) $_POST['letsencrypt']; } + // HSTS + $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; + $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; + $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; + $ssl_ipandports = array(); if (isset($_POST['ssl_ipandport']) && ! is_array($_POST['ssl_ipandport'])) { $_POST['ssl_ipandport'] = unserialize($_POST['ssl_ipandport']); @@ -1428,11 +1433,6 @@ if ($page == 'domains' || $page == 'overview') { } } - // HSTS - $hsts_maxage = isset($_POST['hsts_maxage']) ? (int)$_POST['hsts_maxage'] : 0; - $hsts_sub = isset($_POST['hsts_sub']) && (int)$_POST['hsts_sub'] == 1 ? 1 : 0; - $hsts_preload = isset($_POST['hsts_preload']) && (int)$_POST['hsts_preload'] == 1 ? 1 : 0; - } else { $ssl_redirect = 0; $letsencrypt = 0; @@ -1594,7 +1594,7 @@ if ($page == 'domains' || $page == 'overview') { 'ipandport' => serialize($ipandports), 'ssl_ipandport' => serialize($ssl_ipandports), 'letsencrypt' => $letsencrypt, - 'hsts' => $hsts_maxage, + 'hsts_maxage' => $hsts_maxage, 'hsts_sub' => $hsts_sub, 'hsts_preload' => $hsts_preload ); @@ -1615,7 +1615,7 @@ if ($page == 'domains' || $page == 'overview') { $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; - if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt']) { + if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload']) { inserttask('1'); } diff --git a/customer_domains.php b/customer_domains.php index 43e444af..06471cb8 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -578,7 +578,7 @@ if ($page == 'overview') { $_doredirect = true; } - $aliasdomain = intval($_POST['alias']); + $aliasdomain = isset($_POST['alias']) ? intval($_POST['alias']) : 0; if (isset($_POST['selectserveralias'])) { $iswildcarddomain = ($_POST['selectserveralias'] == '0') ? '1' : '0'; @@ -681,7 +681,11 @@ if ($page == 'overview') { || $aliasdomain != $result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] || $ssl_redirect != $result['ssl_redirect'] - || $letsencrypt != $result['letsencrypt']) { + || $letsencrypt != $result['letsencrypt'] + || $hsts_maxage != $result['hsts'] + || $hsts_sub != $result['hsts_sub'] + || $hsts_preload != $result['hsts_preload'] + ) { $log->logAction(USR_ACTION, LOG_INFO, "edited domain '" . $idna_convert->decode($result['domain']) . "'"); $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET From c409d8a6bacd35338d9daa73b91ff5a57e44fcb1 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 3 Nov 2016 14:14:33 +0100 Subject: [PATCH 28/62] re-enable removing of orphaned entries, fixes #1666 Signed-off-by: Michael Kaufmann (d00p) --- ssl_certificates.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/ssl_certificates.php b/ssl_certificates.php index 0d4f9c03..5a8547d7 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -95,12 +95,9 @@ if (count($all_certs) == 0) { if (empty($cert['domain']) || empty($cert['ssl_cert_file'])) { // no domain found to the entry or empty entry - safely delete it from the DB - /* Database::pexecute($del_stmt, array( 'id' => $cert['id'] )); - */ - echo "no domain found to the entry or empty entry - safely delete it from the DB"; continue; } From d6b56262cef78e1cce8271b82f18387c221f78f9 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 4 Nov 2016 18:28:32 +0100 Subject: [PATCH 29/62] fix unnecessary idn encoding Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 2 +- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index a8cd208e..1f37d4c8 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -431,7 +431,7 @@ class lighttpd extends HttpConfigBase $domain['documentroot'] = trim($domain['documentroot']); if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { - $uri = $this->idnaConvert->encode_uri($domain['documentroot']); + $uri = $domain['documentroot']; // prevent empty return-cde $code = "301"; // Get domain's redirect code diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index d4baa6c8..b282b1e1 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -456,7 +456,7 @@ class nginx extends HttpConfigBase // if the documentroot is an URL we just redirect if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { - $uri = $this->idnaConvert->encode_uri($domain['documentroot']); + $uri = $domain['documentroot']; if (substr($uri, - 1) == '/') { $uri = substr($uri, 0, - 1); } From fad607c6e8de772ddaa8efd5e1e5750b17dacf6b Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Mon, 7 Nov 2016 07:28:58 +0100 Subject: [PATCH 30/62] set version to 0.9.38-rc2 for second release candidate --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 6 ++++++ lib/version.inc.php | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 840d6301..e8ad16bb 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -576,7 +576,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38-rc1'), + ('panel', 'version', '0.9.38-rc2'), ('panel', 'db_version', '201610070'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 3767ec8a..c9968770 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3507,3 +3507,9 @@ if (isFroxlorVersion('0.9.37')) { showUpdateStep("Updating from 0.9.37 to 0.9.38-rc1", false); updateToVersion('0.9.38-rc1'); } + +if (isFroxlorVersion('0.9.38-rc1')) { + + showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); + updateToVersion('0.9.38-rc2'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index 7fa046a2..ef48a2b2 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38-rc1'; +$version = '0.9.38-rc2'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201610070'; From 7e4164da265bbd54dccdb8b2365abd41bfcaa427 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 10 Nov 2016 10:07:00 +0100 Subject: [PATCH 31/62] do not double validate openbasedir-values, as appendOpenbasedirPath() already takes care of that; also fix /dev/urandom as openbasedir-path-value to be treated as file correctly, fixes #1669 Signed-off-by: Michael Kaufmann (d00p) --- .../phpinterface/class.phpinterface_fcgid.php | 9 --- .../phpinterface/class.phpinterface_fpm.php | 9 --- .../function.appendOpenbasedirPath.php | 65 ++++++++++--------- 3 files changed, 34 insertions(+), 49 deletions(-) diff --git a/lib/classes/phpinterface/class.phpinterface_fcgid.php b/lib/classes/phpinterface/class.phpinterface_fcgid.php index 1cb21dd1..ca611661 100644 --- a/lib/classes/phpinterface/class.phpinterface_fcgid.php +++ b/lib/classes/phpinterface/class.phpinterface_fcgid.php @@ -135,15 +135,6 @@ class phpinterface_fcgid { $openbasedir .= appendOpenBasedirPath($this->getTempDir()); $openbasedir .= $_phpappendopenbasedir; - $openbasedir = explode(':', $openbasedir); - $clean_openbasedir = array(); - foreach ($openbasedir as $number => $path) { - if (trim($path) != '/') { - $clean_openbasedir[] = makeCorrectDir($path); - } - } - $openbasedir = implode(':', $clean_openbasedir); - } else { $openbasedir = 'none'; $openbasedirc = ';'; diff --git a/lib/classes/phpinterface/class.phpinterface_fpm.php b/lib/classes/phpinterface/class.phpinterface_fpm.php index 156940ba..5c39d00b 100644 --- a/lib/classes/phpinterface/class.phpinterface_fpm.php +++ b/lib/classes/phpinterface/class.phpinterface_fpm.php @@ -267,15 +267,6 @@ class phpinterface_fpm { $openbasedir .= appendOpenBasedirPath($this->getTempDir()); $openbasedir .= $_phpappendopenbasedir; - - $openbasedir = explode(':', $openbasedir); - $clean_openbasedir = array(); - foreach ($openbasedir as $number => $path) { - if (trim($path) != '/') { - $clean_openbasedir[] = makeCorrectDir($path); - } - } - $openbasedir = implode(':', $clean_openbasedir); } } $fpm_config.= 'php_admin_value[session.save_path] = ' . makeCorrectDir(Settings::Get('phpfpm.tmpdir') . '/' . $this->_domain['loginname'] . '/') . "\n"; diff --git a/lib/functions/validate/function.appendOpenbasedirPath.php b/lib/functions/validate/function.appendOpenbasedirPath.php index 51c0db99..cdcc11f6 100644 --- a/lib/functions/validate/function.appendOpenbasedirPath.php +++ b/lib/functions/validate/function.appendOpenbasedirPath.php @@ -21,40 +21,43 @@ * to a line for a open_basedir directive * * @param string $path - * the path to check and append + * the path to check and append * @param boolean $first - * if true, no ':' will be prefixed to the path - * + * if true, no ':' will be prefixed to the path + * * @return string */ function appendOpenBasedirPath($path = '', $first = false) { - if ($path != '' && $path != '/' - && (! preg_match("#^/dev#i", $path) || preg_match("#^/dev/urandom#i", $path)) - && ! preg_match("#^/proc#i", $path) - && ! preg_match("#^/etc#i", $path) - && ! preg_match("#^/sys#i", $path) - && ! preg_match("#:#", $path) - ) { - - $path = makeCorrectDir($path); - - // check for php-version that requires the trailing - // slash to be removed as it does not allow the usage - // of the subfolders within the given folder, fixes #797 - if ((PHP_MINOR_VERSION == 2 && PHP_VERSION_ID >= 50216) || PHP_VERSION_ID >= 50304) { - // check trailing slash - if (substr($path, - 1, 1) == '/') { - // remove it - $path = substr($path, 0, - 1); - } - } - - if ($first) { - return $path; - } - - return ':' . $path; - } - return ''; + if ($path != '' && $path != '/' && + (! preg_match("#^/dev#i", $path) || preg_match("#^/dev/urandom#i", $path)) + && ! preg_match("#^/proc#i", $path) + && ! preg_match("#^/etc#i", $path) + && ! preg_match("#^/sys#i", $path) + && ! preg_match("#:#", $path)) { + + if (preg_match("#^/dev/urandom#i", $path)) { + $path = makeCorrectFile($path); + } else { + $path = makeCorrectDir($path); + } + + // check for php-version that requires the trailing + // slash to be removed as it does not allow the usage + // of the subfolders within the given folder, fixes #797 + if ((PHP_MINOR_VERSION == 2 && PHP_VERSION_ID >= 50216) || PHP_VERSION_ID >= 50304) { + // check trailing slash + if (substr($path, - 1, 1) == '/') { + // remove it + $path = substr($path, 0, - 1); + } + } + + if ($first) { + return $path; + } + + return ':' . $path; + } + return ''; } From b0326c640c15470c495ee23312961d84ab175179 Mon Sep 17 00:00:00 2001 From: Dominic Schallert Date: Sun, 13 Nov 2016 14:41:39 +0100 Subject: [PATCH 32/62] Feature #1671 Checkbox to enable/disable PHP (vhost settings + fpm pool) for an entire vhost --- admin_domains.php | 23 ++++++++++++++++++- install/froxlor.sql | 1 + .../updates/froxlor/0.9/update_0.9.inc.php | 11 +++++++++ .../admin/domains/formfield.domains_add.php | 8 +++++++ .../admin/domains/formfield.domains_edit.php | 8 +++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/admin_domains.php b/admin_domains.php index 0f86f7b6..93fe910c 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -453,6 +453,7 @@ if ($page == 'domains' || $page == 'overview') { if ($userinfo['caneditphpsettings'] == '1' || $userinfo['change_serversettings'] == '1') { + $phpenabled = isset($POST_['phpenabled']) ? intval($_POST['phpenabled']) : 0; $openbasedir = isset($_POST['openbasedir']) ? intval($_POST['openbasedir']) : 0; if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { @@ -493,7 +494,9 @@ if ($page == 'domains' || $page == 'overview') { } } else { + $phpenabled = '1'; $openbasedir = '1'; + if ((int) Settings::Get('phpfpm.enabled') == 1) { $phpsettingid = Settings::Get('phpfpm.defaultini'); } else { @@ -688,6 +691,10 @@ if ($page == 'domains' || $page == 'overview') { if (count($ipandports) == 0) { standard_error('noipportgiven'); } + + if($phpenabled != '1') { + $phpenabled = '0'; + } if ($openbasedir != '1') { $openbasedir = '0'; @@ -768,6 +775,7 @@ if ($page == 'domains' || $page == 'overview') { 'ipandport' => serialize($ipandports), 'ssl_redirect' => $ssl_redirect, 'ssl_ipandport' => serialize($ssl_ipandports), + 'phpenabled' => $phpenabled, 'openbasedir' => $openbasedir, 'phpsettingid' => $phpsettingid, 'mod_fcgid_starter' => $mod_fcgid_starter, @@ -816,6 +824,7 @@ if ($page == 'domains' || $page == 'overview') { 'email_only' => $email_only, 'subcanemaildomain' => $subcanemaildomain, 'caneditdomain' => $caneditdomain, + 'phpenabled' => $phpenabled, 'openbasedir' => $openbasedir, 'speciallogfile' => $speciallogfile, 'specialsettings' => $specialsettings, @@ -852,6 +861,7 @@ if ($page == 'domains' || $page == 'overview') { `email_only` = :email_only, `subcanemaildomain` = :subcanemaildomain, `caneditdomain` = :caneditdomain, + `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `speciallogfile` = :speciallogfile, `specialsettings` = :specialsettings, @@ -1326,6 +1336,7 @@ if ($page == 'domains' || $page == 'overview') { if ($userinfo['caneditphpsettings'] == '1' || $userinfo['change_serversettings'] == '1') { + $phpenabled = isset($_POST['phpenabled']) ? intval($_POST['phpenabled']) : 0; $openbasedir = isset($_POST['openbasedir']) ? intval($_POST['openbasedir']) : 0; if ((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) { @@ -1360,6 +1371,7 @@ if ($page == 'domains' || $page == 'overview') { $mod_fcgid_maxrequests = $result['mod_fcgid_maxrequests']; } } else { + $phpenabled = $result['phpenabled']; $openbasedir = $result['openbasedir']; $phpsettingid = $result['phpsettingid']; $mod_fcgid_starter = $result['mod_fcgid_starter']; @@ -1471,6 +1483,10 @@ if ($page == 'domains' || $page == 'overview') { if (! preg_match('/^https?\:\/\//', $documentroot)) { $documentroot = makeCorrectDir($documentroot); } + + if ($phpenabled != '1') { + $phpenabled = '0'; + } if ($openbasedir != '1') { $openbasedir = '0'; @@ -1580,6 +1596,7 @@ if ($page == 'domains' || $page == 'overview') { 'dkim' => $dkim, 'selectserveralias' => $serveraliasoption, 'ssl_redirect' => $ssl_redirect, + 'phpenabled' => $phpenabled, 'openbasedir' => $openbasedir, 'phpsettingid' => $phpsettingid, 'mod_fcgid_starter' => $mod_fcgid_starter, @@ -1615,7 +1632,7 @@ if ($page == 'domains' || $page == 'overview') { $wwwserveralias = ($serveraliasoption == '1') ? '1' : '0'; $iswildcarddomain = ($serveraliasoption == '0') ? '1' : '0'; - if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload']) { + if ($documentroot != $result['documentroot'] || $ssl_redirect != $result['ssl_redirect'] || $wwwserveralias != $result['wwwserveralias'] || $iswildcarddomain != $result['iswildcarddomain'] || $phpenabled != $result['phpenabled'] || $openbasedir != $result['openbasedir'] || $phpsettingid != $result['phpsettingid'] || $mod_fcgid_starter != $result['mod_fcgid_starter'] || $mod_fcgid_maxrequests != $result['mod_fcgid_maxrequests'] || $specialsettings != $result['specialsettings'] || $aliasdomain != $result['aliasdomain'] || $issubof != $result['ismainbutsubto'] || $email_only != $result['email_only'] || ($speciallogfile != $result['speciallogfile'] && $speciallogverified == '1') || $letsencrypt != $result['letsencrypt'] || $hsts_maxage != $result['hsts'] || $hsts_sub != $result['hsts_sub'] || $hsts_preload != $result['hsts_preload']) { inserttask('1'); } @@ -1756,6 +1773,7 @@ if ($page == 'domains' || $page == 'overview') { $update_data['zonefile'] = $zonefile; $update_data['wwwserveralias'] = $wwwserveralias; $update_data['iswildcarddomain'] = $iswildcarddomain; + $update_data['phpenabled'] = $phpenabled; $update_data['openbasedir'] = $openbasedir; $update_data['speciallogfile'] = $speciallogfile; $update_data['phpsettingid'] = $phpsettingid; @@ -1787,6 +1805,7 @@ if ($page == 'domains' || $page == 'overview') { `zonefile` = :zonefile, `wwwserveralias` = :wwwserveralias, `iswildcarddomain` = :iswildcarddomain, + `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `speciallogfile` = :speciallogfile, `phpsettingid` = :phpsettingid, @@ -1806,6 +1825,7 @@ if ($page == 'domains' || $page == 'overview') { $_update_data['customerid'] = $customerid; $_update_data['adminid'] = $adminid; + $_update_data['phpenabled'] = $phpenabled; $_update_data['openbasedir'] = $openbasedir; $_update_data['phpsettingid'] = $phpsettingid; $_update_data['mod_fcgid_starter'] = $mod_fcgid_starter; @@ -1824,6 +1844,7 @@ if ($page == 'domains' || $page == 'overview') { UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `customerid` = :customerid, `adminid` = :adminid, + `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `phpsettingid` = :phpsettingid, `mod_fcgid_starter` = :mod_fcgid_starter, diff --git a/install/froxlor.sql b/install/froxlor.sql index e8ad16bb..c81dc912 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -237,6 +237,7 @@ CREATE TABLE `panel_domains` ( `dkim_pubkey` text, `wwwserveralias` tinyint(1) NOT NULL default '1', `parentdomainid` int(11) NOT NULL default '0', + `phpenabled` tinyint(1) NOT NULL default '0', `openbasedir` tinyint(1) NOT NULL default '0', `openbasedir_path` tinyint(1) NOT NULL default '0', `speciallogfile` tinyint(1) NOT NULL default '0', diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index c9968770..36f5aad1 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3513,3 +3513,14 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } + +if (isFroxlorVersion('0.9.38-rc2')) { + + showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38-rc3", false); + + showUpdateStep("Updating database table definition for panel_domains"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `openbasedir`;"); + lastStepStatus(0); + + updateToVersion('0.9.38-rc3'); +} diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index 15ca70e4..bce5b886 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -202,6 +202,14 @@ return array( 'image' => 'icons/domain_add.png', 'visible' => (($userinfo['change_serversettings'] == '1' || $userinfo['caneditphpsettings'] == '1') ? true : false), 'fields' => array( + 'phpenabled' => array( + 'label' => $lng['admin']['phpenabled'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array('1') + ), 'openbasedir' => array( 'label' => 'OpenBasedir', 'type' => 'checkbox', diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 11b6c6bc..73e00497 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -225,6 +225,14 @@ return array( 'image' => 'icons/domain_edit.png', 'visible' => (($userinfo['change_serversettings'] == '1' || $userinfo['caneditphpsettings'] == '1') ? true : false), 'fields' => array( + 'phpenabled' => array( + 'label' => $lng['admin']['phpenabled'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array('1') + ), 'openbasedir' => array( 'label' => 'OpenBasedir', 'type' => 'checkbox', From 1519db16373f487ccee3305bb6fb5adc5a4f1f0e Mon Sep 17 00:00:00 2001 From: Dominic Date: Sun, 13 Nov 2016 14:48:50 +0100 Subject: [PATCH 33/62] Update update_0.9.inc.php --- install/updates/froxlor/0.9/update_0.9.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 36f5aad1..71e7441e 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3519,7 +3519,7 @@ if (isFroxlorVersion('0.9.38-rc2')) { showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38-rc3", false); showUpdateStep("Updating database table definition for panel_domains"); - Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `openbasedir`;"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `parentdomainid`;"); lastStepStatus(0); updateToVersion('0.9.38-rc3'); From e5053bad154b505e5cb6ca7f5dd34aa1163aeb31 Mon Sep 17 00:00:00 2001 From: Dominic Schallert Date: Sun, 13 Nov 2016 15:15:43 +0100 Subject: [PATCH 34/62] Introduced phpenabled_customer and phpenabled_vhost, updated cron scripts, updated dbversion --- install/froxlor.sql | 2 +- .../updates/froxlor/0.9/update_0.9.inc.php | 20 +++++++++---------- lib/classes/webserver/class.WebserverBase.php | 5 +++-- lib/version.inc.php | 2 +- .../jobs/cron_tasks.inc.http.10.apache.php | 2 +- .../cron_tasks.inc.http.15.apache_fcgid.php | 2 +- .../cron_tasks.inc.http.25.lighttpd_fcgid.php | 2 +- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 6 +++--- .../cron_tasks.inc.http.35.nginx_phpfpm.php | 2 +- 9 files changed, 21 insertions(+), 22 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index c81dc912..a8dc13c3 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -578,7 +578,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'version', '0.9.38-rc2'), - ('panel', 'db_version', '201610070'); + ('panel', 'db_version', '201611130'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 71e7441e..cce1ebfd 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3502,6 +3502,15 @@ if (isDatabaseVersion('201609240')) { updateToDbVersion('201610070'); } +if (isDatabaseVersion('201610070')) { + + showUpdateStep("Updating database table definition for panel_domains"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `parentdomainid`;"); + lastStepStatus(0); + + updateToDbVersion('201611130'); +} + if (isFroxlorVersion('0.9.37')) { showUpdateStep("Updating from 0.9.37 to 0.9.38-rc1", false); @@ -3513,14 +3522,3 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } - -if (isFroxlorVersion('0.9.38-rc2')) { - - showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38-rc3", false); - - showUpdateStep("Updating database table definition for panel_domains"); - Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `parentdomainid`;"); - lastStepStatus(0); - - updateToVersion('0.9.38-rc3'); -} diff --git a/lib/classes/webserver/class.WebserverBase.php b/lib/classes/webserver/class.WebserverBase.php index d67b9868..b827f04c 100644 --- a/lib/classes/webserver/class.WebserverBase.php +++ b/lib/classes/webserver/class.WebserverBase.php @@ -31,8 +31,9 @@ class WebserverBase { $query = "SELECT `d`.*, `pd`.`domain` AS `parentdomain`, `c`.`loginname`, `d`.`phpsettingid`, `c`.`adminid`, `c`.`guid`, `c`.`email`, `c`.`documentroot` AS `customerroot`, `c`.`deactivated`, - `c`.`phpenabled` AS `phpenabled`, `d`.`mod_fcgid_starter`, - `d`.`mod_fcgid_maxrequests` + `c`.`phpenabled` AS `phpenabled_customer`, + `d`.`phpenabled` AS `phpenabled_vhost`, + `d`.`mod_fcgid_starter`,`d`.`mod_fcgid_maxrequests` FROM `".TABLE_PANEL_DOMAINS."` `d` LEFT JOIN `".TABLE_PANEL_CUSTOMERS."` `c` USING(`customerid`) diff --git a/lib/version.inc.php b/lib/version.inc.php index ef48a2b2..72c746d7 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.9.38-rc2'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201610070'; +$dbversion = '201611130'; // Distribution branding-tag (used for Debian etc.) $branding = ''; diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 156435a3..f597dcad 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -488,7 +488,7 @@ class apache extends HttpConfigBase { $php_options_text = ''; - if ($domain['phpenabled'] == '1') { + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { // This vHost has PHP enabled and we are using the regular mod_php if ($domain['openbasedir'] == '1') { diff --git a/scripts/jobs/cron_tasks.inc.http.15.apache_fcgid.php b/scripts/jobs/cron_tasks.inc.http.15.apache_fcgid.php index 6e569d8f..6c9bd2a2 100644 --- a/scripts/jobs/cron_tasks.inc.http.15.apache_fcgid.php +++ b/scripts/jobs/cron_tasks.inc.http.15.apache_fcgid.php @@ -23,7 +23,7 @@ class apache_fcgid extends apache { $php_options_text = ''; - if($domain['phpenabled'] == '1') + if($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']); diff --git a/scripts/jobs/cron_tasks.inc.http.25.lighttpd_fcgid.php b/scripts/jobs/cron_tasks.inc.http.25.lighttpd_fcgid.php index 9f2e4ad2..a53c4b24 100644 --- a/scripts/jobs/cron_tasks.inc.http.25.lighttpd_fcgid.php +++ b/scripts/jobs/cron_tasks.inc.http.25.lighttpd_fcgid.php @@ -21,7 +21,7 @@ class lighttpd_fcgid extends lighttpd { $php_options_text = ''; - if($domain['phpenabled'] == '1') + if($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']); diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index b282b1e1..6d2fb617 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -838,7 +838,7 @@ class nginx extends HttpConfigBase protected function composePhpOptions($domain, $ssl_vhost = false) { $phpopts = ''; - if ($domain['phpenabled'] == '1') { + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $phpopts = "\tlocation ~ \.php {\n"; $phpopts .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n"; $phpopts .= "\t" . '}' . "\n\n"; @@ -874,7 +874,7 @@ class nginx extends HttpConfigBase $webroot_text .= "\n\t" . 'location / {' . "\n"; - if ($domain['phpenabled'] == '1') { + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $webroot_text .= "\t" . 'index index.php index.html index.htm;' . "\n"; $webroot_text .= "\t\t" . 'try_files $uri $uri/ @rewrites;' . "\n"; } else { @@ -887,7 +887,7 @@ class nginx extends HttpConfigBase } $webroot_text .= "\t" . '}' . "\n\n"; - if ($domain['phpenabled'] == '1') { + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $webroot_text .= "\tlocation @rewrites {\n"; $webroot_text .= "\t\trewrite ^ /index.php last;\n"; $webroot_text .= "\t}\n\n"; diff --git a/scripts/jobs/cron_tasks.inc.http.35.nginx_phpfpm.php b/scripts/jobs/cron_tasks.inc.http.35.nginx_phpfpm.php index f47ccd82..4a94c51d 100644 --- a/scripts/jobs/cron_tasks.inc.http.35.nginx_phpfpm.php +++ b/scripts/jobs/cron_tasks.inc.http.35.nginx_phpfpm.php @@ -20,7 +20,7 @@ class nginx_phpfpm extends nginx protected function composePhpOptions($domain, $ssl_vhost = false) { $php_options_text = ''; - if ($domain['phpenabled'] == '1') { + if ($domain['phpenabled_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $php = new phpinterface($domain); $phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']); From d93cfff1729d7e0cd1756f0a2997d68dd3941d07 Mon Sep 17 00:00:00 2001 From: Dominic Schallert Date: Sun, 13 Nov 2016 15:18:07 +0100 Subject: [PATCH 35/62] updates always at the end of the file --- install/updates/froxlor/0.9/update_0.9.inc.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index cce1ebfd..7f2387ae 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3502,15 +3502,6 @@ if (isDatabaseVersion('201609240')) { updateToDbVersion('201610070'); } -if (isDatabaseVersion('201610070')) { - - showUpdateStep("Updating database table definition for panel_domains"); - Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `parentdomainid`;"); - lastStepStatus(0); - - updateToDbVersion('201611130'); -} - if (isFroxlorVersion('0.9.37')) { showUpdateStep("Updating from 0.9.37 to 0.9.38-rc1", false); @@ -3522,3 +3513,12 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } + +if (isDatabaseVersion('201610070')) { + + showUpdateStep("Updating database table definition for panel_domains"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `phpenabled` tinyint(1) NOT NULL default '1' AFTER `parentdomainid`;"); + lastStepStatus(0); + + updateToDbVersion('201611130'); +} From 30087548b0b7cbb0ca8e35cb304b9841a8dba50d Mon Sep 17 00:00:00 2001 From: Dominic Schallert Date: Sun, 13 Nov 2016 15:33:56 +0100 Subject: [PATCH 36/62] Fixed the checkbox value --- lib/formfields/admin/domains/formfield.domains_edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 73e00497..d458b5d3 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -231,7 +231,7 @@ return array( 'values' => array( array ('label' => $lng['panel']['yes'], 'value' => '1') ), - 'value' => array('1') + 'value' => array($result['phpenabled']) ), 'openbasedir' => array( 'label' => 'OpenBasedir', From 432645431c1be3191676f3604809ec4827a7beea Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 15 Nov 2016 08:03:34 +0100 Subject: [PATCH 37/62] allow CIDR values in AXFR setting, fixes #1672 Signed-off-by: Michael Kaufmann (d00p) --- .../function.validateFormFieldString.php | 2 +- .../validate/function.validate_ip.php | 28 ++++++++++++++++--- scripts/jobs/cron_tasks.inc.dns.10.bind.php | 4 +-- scripts/jobs/cron_tasks.inc.dns.20.pdns.php | 6 ++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/functions/formfields/string/function.validateFormFieldString.php b/lib/functions/formfields/string/function.validateFormFieldString.php index addfc8b6..45544a18 100644 --- a/lib/functions/formfields/string/function.validateFormFieldString.php +++ b/lib/functions/formfields/string/function.validateFormFieldString.php @@ -122,7 +122,7 @@ function validateFormFieldString($fieldname, $fielddata, $newfieldvalue) $newfieldvalue = ''; $returnvalue = 'stringmustntbeempty'; } else { - $newfieldvalue = validate_ip2($newfieldvalue, true, true, true); + $newfieldvalue = validate_ip2($newfieldvalue, true, 'invalidip', true, true, true); $returnvalue = ($newfieldvalue !== false ? true : 'invalidip'); } } diff --git a/lib/functions/validate/function.validate_ip.php b/lib/functions/validate/function.validate_ip.php index bd8055cc..f3caa492 100644 --- a/lib/functions/validate/function.validate_ip.php +++ b/lib/functions/validate/function.validate_ip.php @@ -49,23 +49,43 @@ function validate_ip($ip, $return_bool = false, $lng = 'invalidip') { * @param string $lng index for error-message (if $return_bool is false) * @param bool $allow_localhost whether to allow 127.0.0.1 * @param bool $allow_priv whether to allow private network addresses + * @param bool $allow_cidr whether to allow CIDR values e.g. 10.10.10.10/16 * * @return string|bool ip address on success, false on failure */ -function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false) { +function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false) { - $filter_lan = $allow_priv ? FILTER_FLAG_NO_RES_RANGE : (FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE); + $cidr = ""; + if ($allow_cidr) { + $org_ip = $ip; + $ip_cidr = explode("/", $ip); + if (count($ip_cidr) == 2) { + $ip = $ip_cidr[0]; + $cidr = "/".$ip_cidr[1]; + } else { + $ip = $org_ip; + } + } elseif (strpos($ip, "/") !== false) { + if ($return_bool) { + return false; + } else { + standard_error($lng, $ip); + exit(); + } + } + + $filter_lan = $allow_priv ? FILTER_FLAG_NO_RES_RANGE : (FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE); if ((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) && filter_var($ip, FILTER_VALIDATE_IP, $filter_lan) ) { - return $ip; + return $ip.$cidr; } // special case where localhost ip is allowed (mysql-access-hosts for example) if ($allow_localhost && $ip == '127.0.0.1') { - return $ip; + return $ip.$cidr; } if ($return_bool) { diff --git a/scripts/jobs/cron_tasks.inc.dns.10.bind.php b/scripts/jobs/cron_tasks.inc.dns.10.bind.php index 06fbc9c8..2934e2a6 100644 --- a/scripts/jobs/cron_tasks.inc.dns.10.bind.php +++ b/scripts/jobs/cron_tasks.inc.dns.10.bind.php @@ -129,9 +129,7 @@ class bind extends DnsBase // AXFR server #100 if (count($this->_axfr) > 0) { foreach ($this->_axfr as $axfrserver) { - if (validate_ip($axfrserver, true) !== false) { - $bindconf_file .= ' ' . $axfrserver . ';' . "\n"; - } + $bindconf_file .= ' ' . $axfrserver . ';' . "\n"; } } // close allow-transfer diff --git a/scripts/jobs/cron_tasks.inc.dns.20.pdns.php b/scripts/jobs/cron_tasks.inc.dns.20.pdns.php index fac7a736..27a63632 100644 --- a/scripts/jobs/cron_tasks.inc.dns.20.pdns.php +++ b/scripts/jobs/cron_tasks.inc.dns.20.pdns.php @@ -194,10 +194,8 @@ class pdns extends DnsBase // AXFR server #100 if (count($this->_axfr) > 0) { foreach ($this->_axfr as $axfrserver) { - if (validate_ip($axfrserver, true) !== false) { - $ins_data['value'] = $axfrserver; - $ins_stmt->execute($ins_data); - } + $ins_data['value'] = $axfrserver; + $ins_stmt->execute($ins_data); } } } From 5f899a5510792a5269f608371a2cd8955346e16e Mon Sep 17 00:00:00 2001 From: Janos Muzsi Date: Thu, 17 Nov 2016 22:50:11 +0100 Subject: [PATCH 38/62] Add support for http2 option to nginx --- actions/admin/settings/130.webserver.php | 11 +++++++++++ install/froxlor.sql | 1 + install/updates/froxlor/0.9/update_0.9.inc.php | 10 ++++++++++ lng/english.lng.php | 3 +++ scripts/jobs/cron_tasks.inc.http.30.nginx.php | 8 ++++++-- 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php index 4374b148..8a117d5c 100644 --- a/actions/admin/settings/130.webserver.php +++ b/actions/admin/settings/130.webserver.php @@ -179,6 +179,17 @@ return array( 'nginx' ) ), + 'system_nginx_http2_support' => array( + 'label' => $lng['serversettings']['nginx_http2_support'], + 'settinggroup' => 'system', + 'varname' => 'nginx_http2_support', + 'type' => 'bool', + 'default' => false, + 'save_method' => 'storeSettingField', + 'websrv_avail' => array( + 'nginx' + ) + ), 'system_nginx_php_backend' => array( 'label' => $lng['serversettings']['nginx_php_backend'], 'settinggroup' => 'system', diff --git a/install/froxlor.sql b/install/froxlor.sql index e8ad16bb..24805a1b 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -496,6 +496,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'ssl_cert_chainfile', ''), ('system', 'ssl_cipher_list', 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128'), ('system', 'nginx_php_backend', '127.0.0.1:8888'), + ('system', 'nginx_http2_support', '0'), ('system', 'perl_server', 'unix:/var/run/nginx/cgiwrap-dispatch.sock'), ('system', 'phpreload_command', ''), ('system', 'apache24', '0'), diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index c9968770..f625fbc3 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3513,3 +3513,13 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } +/* +if (isDatabaseVersion('201610070')) { + + showUpdateStep("Add Nginx http2 setting"); + Settings::AddNew("system.nginx_http2_support", 0); + lastStepStatus(0); + + updateToDbVersion('201610270'); +} + */ \ No newline at end of file diff --git a/lng/english.lng.php b/lng/english.lng.php index 036cf118..45996cd0 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2062,3 +2062,6 @@ $lng['admin']['domain_hsts_incsub']['title'] = 'Include HSTS for any subdomain'; $lng['admin']['domain_hsts_incsub']['description'] = 'The optional "includeSubDomains" directive, if present, signals the UA that the HSTS Policy applies to this HSTS Host as well as any subdomains of the host\'s domain name.'; $lng['admin']['domain_hsts_preload']['title'] = 'Include domain in HSTS preload list'; $lng['admin']['domain_hsts_preload']['description'] = 'If you would like this domain to be included in the HSTS preload list maintained by Chrome (and used by Firefox and Safari), then use activate this.
Sending the preload directive from your site can have PERMANENT CONSEQUENCES and prevent users from accessing your site and any of its subdomains.
Please read the details at hstspreload.appspot.com/#removal before sending the header with "preload".'; + +$lng['serversettings']['nginx_http2_support']['title'] = 'Nginx HTTP2 Support'; +$lng['serversettings']['nginx_http2_support']['description'] = 'enable http2 support for ssl. ENABLE ONLY IF YOUR Nginx SUPPORT THIS FEATURE. (version 1.9.5+)'; diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index b282b1e1..dcff6ff1 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -196,10 +196,12 @@ class nginx extends HttpConfigBase } } + $http2 = $ssl_vhost == true && Settings::Get('system.nginx_http2_support') == '1'; + /** * this HAS to be set for the default host in nginx or else no vhost will work */ - $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'server_name ' . Settings::Get('system.hostname') . ';' . "\n"; @@ -411,7 +413,9 @@ class nginx extends HttpConfigBase $_vhost_content .= $this->processSpecialConfigTemplate($ipandport['default_vhostconf_domain'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; } - $vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; + $http2 = $ssl_vhost == true && Settings::Get('system.nginx_http2_support') == '1'; + + $vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n"; } // get all server-names From d245bca445af99dad1cf53f6411bf8d9d7dbcdc6 Mon Sep 17 00:00:00 2001 From: Janos Muzsi Date: Fri, 18 Nov 2016 08:32:23 +0100 Subject: [PATCH 39/62] correcting the update --- install/updates/froxlor/0.9/update_0.9.inc.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index f625fbc3..821e500d 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3513,13 +3513,12 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } -/* + if (isDatabaseVersion('201610070')) { showUpdateStep("Add Nginx http2 setting"); Settings::AddNew("system.nginx_http2_support", 0); lastStepStatus(0); - updateToDbVersion('201610270'); + updateToDbVersion('201611180'); } - */ \ No newline at end of file From 547140bafb4e936cfc469858e4b11e9ef93c207b Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 08:36:35 +0100 Subject: [PATCH 40/62] set version to 0.9.38 for upcoming release Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 6 ++++++ lib/version.inc.php | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index e8ad16bb..71897be7 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -576,7 +576,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38-rc2'), + ('panel', 'version', '0.9.38'), ('panel', 'db_version', '201610070'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index c9968770..ad448a61 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3513,3 +3513,9 @@ if (isFroxlorVersion('0.9.38-rc1')) { showUpdateStep("Updating from 0.9.38-rc1 to 0.9.38-rc2", false); updateToVersion('0.9.38-rc2'); } + +if (isFroxlorVersion('0.9.38-rc2')) { + + showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38 final", false); + updateToVersion('0.9.38'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index ef48a2b2..d959ebf8 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38-rc2'; +$version = '0.9.38'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201610070'; From 1984aced9de8fe7de8a0bb4fff9c61b14498587c Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 08:52:40 +0100 Subject: [PATCH 41/62] set db_version correctly everywhere Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- lib/version.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 5a64a175..20cffe56 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -578,7 +578,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), ('panel', 'version', '0.9.38'), - ('panel', 'db_version', '201610070'); + ('panel', 'db_version', '201611180'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/lib/version.inc.php b/lib/version.inc.php index d959ebf8..b66c0485 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.9.38'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201610070'; +$dbversion = '201611180'; // Distribution branding-tag (used for Debian etc.) $branding = ''; From 9540cb158cfe8c05b2edf38d681d4a0be02740f9 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 10:10:03 +0100 Subject: [PATCH 42/62] set version to 0.9.38.1 b/c of hsts includeSubdomains flag for domains not being saved; added http2-flag for nginx as setting Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 10 ++++++++-- lib/formfields/admin/domains/formfield.domains_add.php | 2 +- .../admin/domains/formfield.domains_edit.php | 2 +- lib/version.inc.php | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 20cffe56..92471885 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -577,7 +577,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38'), + ('panel', 'version', '0.9.38.1'), ('panel', 'db_version', '201611180'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 9f286d9c..926b54e5 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3516,8 +3516,8 @@ if (isFroxlorVersion('0.9.38-rc1')) { if (isFroxlorVersion('0.9.38-rc2')) { - showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38 final", false); - updateToVersion('0.9.38'); + showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38 final", false); + updateToVersion('0.9.38'); } if (isDatabaseVersion('201610070')) { @@ -3528,3 +3528,9 @@ if (isDatabaseVersion('201610070')) { updateToDbVersion('201611180'); } + +if (isFroxlorVersion('0.9.38')) { + + showUpdateStep("Updating from 0.9.38 to 0.9.38.1", false); + updateToVersion('0.9.38.1'); +} diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index 15ca70e4..1f92f599 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -175,7 +175,7 @@ return array( 'int_max' => 94608000, // 3-years 'value' => 0 ), - 'hsts_incsub' => array( + 'hsts_sub' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 11b6c6bc..cff9b974 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -198,7 +198,7 @@ return array( 'int_max' => 94608000, // 3-years 'value' => $result['hsts'] ), - 'hsts_incsub' => array( + 'hsts_sub' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], diff --git a/lib/version.inc.php b/lib/version.inc.php index b66c0485..527b8454 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38'; +$version = '0.9.38.1'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201611180'; From 60a482dce6eca5d4720597495f717aba8770bd29 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 10:21:02 +0100 Subject: [PATCH 43/62] damn, forgot to save the two files to handle customer-side domain-settings regarding the hsts-includeSubdomain issue; version set to 0.9.38.2 Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 4 ++-- install/updates/froxlor/0.9/update_0.9.inc.php | 6 ++++++ lib/formfields/customer/domains/formfield.domains_add.php | 2 +- lib/formfields/customer/domains/formfield.domains_edit.php | 2 +- lib/version.inc.php | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 92471885..129c6bb6 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -496,7 +496,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'ssl_cert_chainfile', ''), ('system', 'ssl_cipher_list', 'ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128'), ('system', 'nginx_php_backend', '127.0.0.1:8888'), - ('system', 'nginx_http2_support', '0'), + ('system', 'nginx_http2_support', '0'), ('system', 'perl_server', 'unix:/var/run/nginx/cgiwrap-dispatch.sock'), ('system', 'phpreload_command', ''), ('system', 'apache24', '0'), @@ -577,7 +577,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38.1'), + ('panel', 'version', '0.9.38.2'), ('panel', 'db_version', '201611180'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 926b54e5..380ba153 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3534,3 +3534,9 @@ if (isFroxlorVersion('0.9.38')) { showUpdateStep("Updating from 0.9.38 to 0.9.38.1", false); updateToVersion('0.9.38.1'); } + +if (isFroxlorVersion('0.9.38')) { + + showUpdateStep("Updating from 0.9.38.1 to 0.9.38.2", false); + updateToVersion('0.9.38.2'); +} diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index fb9adc47..1371e579 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -107,7 +107,7 @@ return array( 'int_max' => 94608000, // 3-years 'value' => 0 ), - 'hsts_incsub' => array( + 'hsts_sub' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index 2a7b593b..94bab096 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -118,7 +118,7 @@ return array( 'int_max' => 94608000, // 3-years 'value' => $result['hsts'] ), - 'hsts_incsub' => array( + 'hsts_sub' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], diff --git a/lib/version.inc.php b/lib/version.inc.php index 527b8454..045cd82a 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38.1'; +$version = '0.9.38.2'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201611180'; From 16f547bce0db7e11725f2d7dcfa2251b7d1d9c42 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 10:27:11 +0100 Subject: [PATCH 44/62] last time....0.9.38.3....what a day Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 8 +++++++- lib/version.inc.php | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 129c6bb6..24bbb15e 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -577,7 +577,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38.2'), + ('panel', 'version', '0.9.38.3'), ('panel', 'db_version', '201611180'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 380ba153..8fb02c7a 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3535,8 +3535,14 @@ if (isFroxlorVersion('0.9.38')) { updateToVersion('0.9.38.1'); } -if (isFroxlorVersion('0.9.38')) { +if (isFroxlorVersion('0.9.38.1')) { showUpdateStep("Updating from 0.9.38.1 to 0.9.38.2", false); updateToVersion('0.9.38.2'); } + +if (isFroxlorVersion('0.9.38.2')) { + + showUpdateStep("Updating from 0.9.38.2 to 0.9.38.3", false); + updateToVersion('0.9.38.3'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index 045cd82a..915532b7 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38.2'; +$version = '0.9.38.3'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201611180'; From 16e9fd6bd99324649b1df9f860831c5eaba87610 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 18 Nov 2016 21:19:18 +0100 Subject: [PATCH 45/62] stay php-5.3 compatible Signed-off-by: Michael Kaufmann (d00p) --- lib/functions/filedir/function.makeCorrectDir.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/functions/filedir/function.makeCorrectDir.php b/lib/functions/filedir/function.makeCorrectDir.php index 75dc00d1..dcc91ca2 100644 --- a/lib/functions/filedir/function.makeCorrectDir.php +++ b/lib/functions/filedir/function.makeCorrectDir.php @@ -26,7 +26,11 @@ */ function makeCorrectDir($dir) { - assert('is_string($dir) && strlen($dir) > 0', 'Value "' . $dir .'" does not look like an actual folder name'); + if (version_compare("5.4.6", PHP_VERSION, ">")) { + assert('is_string($dir) && strlen($dir) > 0 /* $dir does not look like an actual folder name */'); + } else { + assert('is_string($dir) && strlen($dir) > 0', 'Value "' . $dir .'" does not look like an actual folder name'); + } $dir = trim($dir); From 43ca4a28e4302c72b0abebb297a8ba4ebb19d2ca Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Mon, 21 Nov 2016 08:19:33 +0100 Subject: [PATCH 46/62] add acme.conf alias also to froxlor vhost in case the acme-challenge path is not within the froxlor-docroot; fix empty redirect-code, fixes #1674 Signed-off-by: Michael Kaufmann (d00p) --- .../output/function.RedirectCode.php | 35 ++++++++++--------- .../jobs/cron_tasks.inc.http.10.apache.php | 4 +-- .../jobs/cron_tasks.inc.http.20.lighttpd.php | 5 ++- scripts/jobs/cron_tasks.inc.http.30.nginx.php | 22 +++++++----- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/lib/functions/output/function.RedirectCode.php b/lib/functions/output/function.RedirectCode.php index b970e3b0..37bd10e1 100644 --- a/lib/functions/output/function.RedirectCode.php +++ b/lib/functions/output/function.RedirectCode.php @@ -16,11 +16,11 @@ /** * return an array of all enabled redirect-codes - * + * * @return array array of enabled redirect-codes */ function getRedirectCodesArray() { - + $sql = "SELECT * FROM `".TABLE_PANEL_REDIRECTCODES."` WHERE `enabled` = '1' ORDER BY `id` ASC"; $result_stmt = Database::query($sql); @@ -35,13 +35,13 @@ function getRedirectCodesArray() { /** * return an array of all enabled redirect-codes * for the settings form - * + * * @return array array of enabled redirect-codes */ function getRedirectCodes() { global $lng; - + $sql = "SELECT * FROM `".TABLE_PANEL_REDIRECTCODES."` WHERE `enabled` = '1' ORDER BY `id` ASC"; $result_stmt = Database::query($sql); @@ -54,16 +54,17 @@ function getRedirectCodes() { } /** - * returns the redirect-code for a given + * returns the redirect-code for a given * domain-id - * + * * @param integer $domainid id of the domain - * + * @param string $default + * * @return string redirect-code */ -function getDomainRedirectCode($domainid = 0) { +function getDomainRedirectCode($domainid = 0, $default = '') { - $code = ''; + $code = $default; if ($domainid > 0) { $result_stmt = Database::prepare(" @@ -83,11 +84,11 @@ function getDomainRedirectCode($domainid = 0) { } /** - * returns the redirect-id for a given + * returns the redirect-id for a given * domain-id - * + * * @param integer $domainid id of the domain - * + * * @return integer redirect-code-id */ function getDomainRedirectId($domainid = 0) { @@ -112,10 +113,10 @@ function getDomainRedirectId($domainid = 0) { /** * adds a redirectcode for a domain - * + * * @param integer $domainid id of the domain to add the code for - * @param integer $redirect selected redirect-id - * + * @param integer $redirect selected redirect-id + * * @return null */ function addRedirectToDomain($domainid = 0, $redirect = 1) { @@ -130,10 +131,10 @@ function addRedirectToDomain($domainid = 0, $redirect = 1) { /** * updates the redirectcode of a domain * if redirect-code is false, nothing happens - * + * * @param integer $domainid id of the domain to update * @param integer $redirect selected redirect-id or false - * + * * @return null */ function updateRedirectOfDomain($domainid = 0, $redirect = false) { diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 156435a3..b6a9697a 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -875,10 +875,8 @@ class apache extends HttpConfigBase if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $corrected_docroot = $domain['documentroot']; - // prevent empty return-cde - $code = "301"; // Get domain's redirect code - $code = getDomainRedirectCode($domain['id']); + $code = getDomainRedirectCode($domain['id'], '301'); $modrew_red = ''; if ($code != '') { $modrew_red = ' [R=' . $code . ';L,NE]'; diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 1f37d4c8..a069d056 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -432,10 +432,9 @@ class lighttpd extends HttpConfigBase if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { $uri = $domain['documentroot']; - // prevent empty return-cde - $code = "301"; + // Get domain's redirect code - $code = getDomainRedirectCode($domain['id']); + $code = getDomainRedirectCode($domain['id'], '301'); $vhost_content .= ' url.redirect-code = ' . $code. "\n"; $vhost_content .= ' url.redirect = (' . "\n"; diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index dcff6ff1..a99f41bf 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -196,17 +196,22 @@ class nginx extends HttpConfigBase } } - $http2 = $ssl_vhost == true && Settings::Get('system.nginx_http2_support') == '1'; - + $http2 = $ssl_vhost == true && Settings::Get('system.nginx_http2_support') == '1'; + /** * this HAS to be set for the default host in nginx or else no vhost will work */ - $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'server_name ' . Settings::Get('system.hostname') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'access_log /var/log/nginx/access.log;' . "\n"; + if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.leenabled') == '1' && Settings::Get('system.le_froxlor_enabled') == '1') { + $acmeConfFilename = Settings::Get('system.letsencryptacmeconf'); + $this->nginx_data[$vhost_filename] .= "\t" . 'include ' . $acmeConfFilename . ';' . "\n"; + } + $is_redirect = false; // check for SSL redirect if ($row_ipsandports['ssl'] == '0' && Settings::Get('system.le_froxlor_redirect') == '1') { @@ -219,7 +224,7 @@ class nginx extends HttpConfigBase } else { $_sslport = $this->checkAlternativeSslPort(); $mypath = 'https://' . Settings::Get('system.hostname') . $_sslport . '/'; - $this->nginx_data[$vhost_filename] .= "\t" . 'if ($request_uri !~ "^/\.well-known/acme-challenge/\w+$") {' . "\n"; + $this->nginx_data[$vhost_filename] .= "\t" . 'if ($request_uri !~ ^/.well-known/acme-challenge/\w+$) {' . "\n"; $this->nginx_data[$vhost_filename] .= "\t\t" . 'return 301 ' . $mypath . '$request_uri;' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n"; } @@ -464,12 +469,11 @@ class nginx extends HttpConfigBase if (substr($uri, - 1) == '/') { $uri = substr($uri, 0, - 1); } - // prevent empty return-cde - $code = "301"; - // Get domain's redirect code - $code = getDomainRedirectCode($domain['id']); - $vhost_content .= "\t" . 'if ($request_uri !~ "^/\.well-known/acme-challenge/\w+$") {' . "\n"; + // Get domain's redirect code + $code = getDomainRedirectCode($domain['id'], '301'); + + $vhost_content .= "\t" . 'if ($request_uri !~ ^/.well-known/acme-challenge/\w+$) {' . "\n"; $vhost_content .= "\t\t" . 'return ' . $code .' ' . $uri . '$request_uri;' . "\n"; $vhost_content .= "\t" . '}' . "\n"; } else { From 192e00c71770e320a3151e7cf731e4670d5c9aa4 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 22 Nov 2016 08:04:11 +0100 Subject: [PATCH 47/62] do not show NameVirtualHost in IP/Port overview when using apache-2.4 (as NameVirtualHost does not exist there anymore) Signed-off-by: Michael Kaufmann (d00p) --- templates/Sparkle/admin/ipsandports/ipsandports.tpl | 2 +- templates/Sparkle/admin/ipsandports/ipsandports_ipandport.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/Sparkle/admin/ipsandports/ipsandports.tpl b/templates/Sparkle/admin/ipsandports/ipsandports.tpl index 753aa1bd..4112553f 100644 --- a/templates/Sparkle/admin/ipsandports/ipsandports.tpl +++ b/templates/Sparkle/admin/ipsandports/ipsandports.tpl @@ -27,7 +27,7 @@ $header {$lng['admin']['ipsandports']['ip']} {$arrowcode['ip']} {$lng['admin']['ipsandports']['port']} {$arrowcode['port']} Listen - NameVirtualHost + NameVirtualHost vHost-Container Specialsettings ServerName diff --git a/templates/Sparkle/admin/ipsandports/ipsandports_ipandport.tpl b/templates/Sparkle/admin/ipsandports/ipsandports_ipandport.tpl index 245ba681..720c486a 100644 --- a/templates/Sparkle/admin/ipsandports/ipsandports_ipandport.tpl +++ b/templates/Sparkle/admin/ipsandports/ipsandports_ipandport.tpl @@ -2,7 +2,7 @@ {$row['ip']} {$row['port']} {$lng['panel']['yes']}{$lng['panel']['no']} - {$lng['panel']['yes']}{$lng['panel']['no']} + {$lng['panel']['yes']}{$lng['panel']['no']} {$lng['panel']['yes']}{$lng['panel']['no']} {$lng['panel']['yes']}{$lng['panel']['no']} {$lng['panel']['yes']}{$lng['panel']['no']} From 9838ff4da564a4e4dfc3123b11225cfbc1f8cebd Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 22 Nov 2016 08:16:35 +0100 Subject: [PATCH 48/62] fix hsts settings for lighttpd, fixes #1677 Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index a069d056..a1869a42 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -531,14 +531,14 @@ class lighttpd extends HttpConfigBase if ($domain['hsts'] >= 0) { - $vhost_content .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts']; + $ssl_settings .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts']; if ($domain['hsts_sub'] == 1) { - $vhost_content .= '; includeSubDomains'; + $ssl_settings .= '; includeSubDomains'; } if ($domain['hsts_preload'] == 1) { - $vhost_content .= '; preload'; + $ssl_settings .= '; preload'; } - $vhost_content .= '") }' . "\n"; + $ssl_settings .= '") }' . "\n"; } } } From f8996ad7674462d7e897ec83b29784a1707614f3 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 22 Nov 2016 15:08:42 +0100 Subject: [PATCH 49/62] catch exception thrown by new IdnaConverter when encoding a non-valid domain, fixes #1678 Signed-off-by: Michael Kaufmann (d00p) --- lib/functions/validate/function.validateUrl.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/functions/validate/function.validateUrl.php b/lib/functions/validate/function.validateUrl.php index 07ce29ac..0515e48d 100644 --- a/lib/functions/validate/function.validateUrl.php +++ b/lib/functions/validate/function.validateUrl.php @@ -37,7 +37,11 @@ function validateUrl($url) { } // needs converting - $url = $idna_convert->encode($url); + try { + $url = $idna_convert->encode($url); + } catch (Exception $e) { + return false; + } $pattern = "/^https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\:[0-9]+)?\/?(.+)?$/i"; if (preg_match($pattern, $url)) { From 54200427ab221507b51700d962ae1bc8d305b135 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Thu, 24 Nov 2016 10:40:28 +0100 Subject: [PATCH 50/62] fix undefined variable when deleting a customer-domain as admin Signed-off-by: Michael Kaufmann (d00p) --- admin_domains.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/admin_domains.php b/admin_domains.php index 0f86f7b6..43f0811b 100644 --- a/admin_domains.php +++ b/admin_domains.php @@ -210,6 +210,8 @@ if ($page == 'domains' || $page == 'overview') { 'id' => $id )); + $deleted_domains = $del_stmt->rowCount(); + $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `subdomains_used` = `subdomains_used` - :domaincount From 2c00f982d8beb14a6e74a460f8fffabd409d5f4c Mon Sep 17 00:00:00 2001 From: Janos Muzsi Date: Thu, 24 Nov 2016 22:55:57 +0100 Subject: [PATCH 51/62] Change redirect host from main domain name to requested domain name --- scripts/jobs/cron_tasks.inc.http.10.apache.php | 2 +- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 14 ++++++++------ scripts/jobs/cron_tasks.inc.http.30.nginx.php | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index b6a9697a..16cf71e8 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -808,7 +808,7 @@ class apache extends HttpConfigBase $_sslport = ":" . $ssldestport['port']; } - $domain['documentroot'] = 'https://' . $domain['domain'] . $_sslport . '/'; + $domain['documentroot'] = 'https://%{HTTP_HOST}' . $_sslport . '/'; } if ($ssl_vhost === true && $domain['ssl'] == '1' && Settings::Get('system.use_ssl') == '1') { diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index a1869a42..9ca21da1 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -424,7 +424,7 @@ class lighttpd extends HttpConfigBase $_sslport = ":" . $ssldestport['port']; } - $domain['documentroot'] = 'https://' . $domain['domain'] . $_sslport . '/'; + $domain['documentroot'] = 'https://%1' . $_sslport . '/'; } // avoid using any whitespaces @@ -435,11 +435,13 @@ class lighttpd extends HttpConfigBase // Get domain's redirect code $code = getDomainRedirectCode($domain['id'], '301'); - - $vhost_content .= ' url.redirect-code = ' . $code. "\n"; - $vhost_content .= ' url.redirect = (' . "\n"; - $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; - $vhost_content .= ' )' . "\n"; + + $vhost_content .= ' $HTTP["host"] =~ "^(.*)$" {'. "\n"; + $vhost_content .= ' url.redirect-code = ' . $code. "\n"; + $vhost_content .= ' url.redirect = (' . "\n"; + $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; + $vhost_content .= ' )' . "\n"; + $vhost_content .= ' }' . "\n"; } else { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php index a99f41bf..4d93ab23 100644 --- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php +++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php @@ -447,7 +447,7 @@ class nginx extends HttpConfigBase $_sslport = ":" . $ssldestport['port']; } - $domain['documentroot'] = 'https://' . $domain['domain'] . $_sslport . '/'; + $domain['documentroot'] = 'https://$host' . $_sslport . '/'; } // avoid using any whitespaces From 18b45c749daea040b78ef0726ea4ea27584b1dab Mon Sep 17 00:00:00 2001 From: Michael Wyraz Date: Fri, 25 Nov 2016 09:54:47 +0100 Subject: [PATCH 52/62] Better handling for letsencrypt errors after failed registration or changed license --- .../updates/froxlor/0.9/update_0.9.inc.php | 26 ++++ lib/classes/ssl/class.lescript.php | 118 +++++++++++++++--- lib/version.inc.php | 2 +- scripts/jobs/cron_letsencrypt.php | 2 + 4 files changed, 133 insertions(+), 15 deletions(-) diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 8fb02c7a..3fd04142 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3546,3 +3546,29 @@ if (isFroxlorVersion('0.9.38.2')) { showUpdateStep("Updating from 0.9.38.2 to 0.9.38.3", false); updateToVersion('0.9.38.3'); } + +if (isDatabaseVersion('201611180')) { + + showUpdateStep("Adding field to reflect let's-encrypt registration status"); + Database::query("ALTER TABLE `".TABLE_PANEL_CUSTOMERS."` add `leregistered` TINYINT(1) NOT NULL DEFAULT 0;"); + lastStepStatus(0); + + updateToDbVersion('201611240'); +} + +if (isDatabaseVersion('201611240')) { + + showUpdateStep("Adding new setting to reflect let's-encrypt registration status"); + $stmt = Database::prepare(" + INSERT INTO `" . TABLE_PANEL_SETTINGS . "` SET + `settinggroup` = 'system', + `varname` = :varname, + `value` = :value"); + Database::pexecute($stmt, array( + 'varname' => 'leregistered', + 'value' => '0' + )); + lastStepStatus(0); + + updateToDbVersion('201611241'); +} diff --git a/lib/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php index dc8ec83b..1d3aa5bb 100644 --- a/lib/classes/ssl/class.lescript.php +++ b/lib/classes/ssl/class.lescript.php @@ -38,6 +38,12 @@ class lescript private $accountKey; + private $customerid; + + private $isFroxlorVhost; + + private $isLeProduction; + private $version; public function __construct($logger, $version = '1') @@ -57,44 +63,71 @@ class lescript { // Let's see if we have the private accountkey $this->accountKey = $certrow['leprivatekey']; - if (! $this->accountKey || $this->accountKey == 'unset' || Settings::Get('system.letsencryptca') != 'production') { + $this->customerId = $certrow['customerid']; + $this->isFroxlorVhost = $isFroxlorVhost; + $this->isLeProduction = (Settings::Get('system.letsencryptca') == 'production'); + + $leregistered=$certrow['leregistered']; + + if (! $this->accountKey || $this->accountKey == 'unset' || !$this->isLeProduction) { // generate and save new private key for account // --------------------------------------------- - $this->log('Starting new account registration'); + $this->log('Creating new account key'); $keys = $this->generateKey(); // Only store the accountkey in production, in staging always generate a new key - if (Settings::Get('system.letsencryptca') == 'production') { + if ($this->isLeProduction) { if ($isFroxlorVhost) { Settings::Set('system.lepublickey', $keys['public']); Settings::Set('system.leprivatekey', $keys['private']); + Settings::Set('system.leregistered', 0); // key is not registered } else { - $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `lepublickey` = :public, `leprivatekey` = :private " . "WHERE `customerid` = :customerid;"); + $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `lepublickey` = :public, `leprivatekey` = :private, `leregistered` = :registered " . "WHERE `customerid` = :customerid;"); Database::pexecute($upd_stmt, array( 'public' => $keys['public'], 'private' => $keys['private'], - 'customerid' => $certrow['customerid'] + 'registered' => 0, + 'customerid' => $this->customerId )); } } + $leregistered=0; $this->accountKey = $keys['private']; + } else { + $this->log('Using existing account key'); + } + if ($leregistered==0) { // Account not registered + + $this->log('Starting new account registration'); $response = $this->postNewReg(); - if ($this->client->getLastCode() != 201) { + if ($this->client->getLastCode() == 409) { + $this->log('The key was already registered. Using existing account.'); + } else if ($this->client->getLastCode() == 201) { + $this->log('New account registered.'); + } else { throw new \RuntimeException("Account not initialized, probably due to rate limiting. Whole response: " . json_encode($response)); } + $accountUrl=$this->client->getLastLocation(); + + $this->log('Accepting lets encrypt Terms of Service'); + $this->license = $this->client->getAgreementURL(); - // Terms of Servce are optional according to ACME specs; if no ToS are presented, no need to update registration + // Terms of Service are optional according to ACME specs; if no ToS are presented, no need to update registration if (!empty($this->license)) { - $this->postRegAgreement(parse_url($this->client->getLastLocation(), PHP_URL_PATH)); + $response = $this->postRegAgreement(parse_url($accountUrl, PHP_URL_PATH)); + if ($this->client->getLastCode() != 202) { + throw new \RuntimeException("Terms of Service not accepted. Whole response: " . json_encode($response)); + } } - $this->log('New account certificate registered'); - } else { - $this->log('Account already registered. Continuing.'); + $leregistered=1; + $this->setLeRegisteredState($leregistered); // Account registered + $this->log('Lets encrypt Terms of Service accepted'); } + } /** @@ -136,11 +169,17 @@ class lescript ) )); + if ($this->client->getLastCode() == 403) { + $this->log("Got status 403 - setting LE status to unregistered."); + $this->setLeRegisteredState(0); + throw new RuntimeException("Got 'unauthorized' response - we need to re-register at next run. Whole response: " . json_encode($response)); + } + // if response is not an array but a string, it's most likely a server-error, e.g. // ErrorAn error occurred while processing your request. //

Reference #179.d8be1402.1458059103.3613c4db if (! is_array($response)) { - throw new RuntimeException("Invalid response from LE for domain $domain. Whole response: " . $response); + throw new RuntimeException("Invalid response from LE for domain $domain. Whole response: " . json_encode($response)); } if (! array_key_exists('challenges', $response)) { @@ -309,6 +348,21 @@ class lescript ); } + private function setLeRegisteredState($state) + { + if ($this->isLeProduction) { + if ($this->isFroxlorVhost) { + Settings::Set('system.leregistered', $state); + } else { + $upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `leregistered` = :registered " . "WHERE `customerid` = :customerid;"); + Database::pexecute($upd_stmt, array( + 'registered' => $state, + 'customerid' => $this->customerId + )); + } + } + } + private function parsePemFromBody($body) { $pem = chunk_split(base64_encode($body), 64, "\n"); @@ -537,10 +591,46 @@ class Client return $matches[1]; } + public function getAgreementURLFromLastResponse() + { + if (preg_match_all('~Link: <(.+)>;rel="terms-of-service"~', $this->lastHeader, $matches)) { + return $matches[1][0]; + } + return ""; + } + public function getAgreementURLFromDirectory() + { + // FIXME: Current license should be found in /directory but LE does not implement this yet + // $this->curl('GET', '/directory'); + return ""; + } + public function getAgreementURLFromTermsUrl() + { + $this->curl('GET', '/terms'); + if (preg_match_all('~Location: (.+)~', $this->lastHeader, $matches)) { + return trim($matches[1][0]); + } + return ""; + } + public function getAgreementURL() { - preg_match_all('~Link: <(.+)>;rel="terms-of-service"~', $this->lastHeader, $matches); - return $matches[1][0]; + // 1. check the header of the last response + $license=$this->getAgreementURLFromLastResponse(); + if (!empty($license)) return $license; + + // 2. query directory for license + $license=$this->getAgreementURLFromDirectory(); + if (!empty($license)) return $license; + + // 3. query /terms endpoint (not ACME standard but implemented by let's enrypt) + $license=$this->getAgreementURLFromTermsUrl(); + if (!empty($license)) return $license; + + // Fallback: use latest known license. This is only valid for let's encrypt and should be removed as soon as there is an official + // ACME-endpoint to get the current ToS + return "xxxhttps://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf]"; + // return ""; } } diff --git a/lib/version.inc.php b/lib/version.inc.php index 915532b7..056ce6e4 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -19,7 +19,7 @@ $version = '0.9.38.3'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201611180'; +$dbversion = '201611241'; // Distribution branding-tag (used for Debian etc.) $branding = ''; diff --git a/scripts/jobs/cron_letsencrypt.php b/scripts/jobs/cron_letsencrypt.php index 2101fcca..126d7dcd 100644 --- a/scripts/jobs/cron_letsencrypt.php +++ b/scripts/jobs/cron_letsencrypt.php @@ -43,6 +43,7 @@ $certificates_stmt = Database::query(" dom.`ssl_redirect`, cust.`leprivatekey`, cust.`lepublickey`, + cust.`leregistered`, cust.`customerid`, cust.`loginname` FROM @@ -103,6 +104,7 @@ if (Settings::Get('system.le_froxlor_enabled') == '1') { 'documentroot' => FROXLOR_INSTALL_DIR, 'leprivatekey' => Settings::Get('system.leprivatekey'), 'lepublickey' => Settings::Get('system.lepublickey'), + 'leregistered' => Settings::Get('system.leregistered'), 'ssl_redirect' => Settings::Get('system.le_froxlor_redirect'), 'expirationdate' => null, 'ssl_cert_file' => null, From 559bd6d892dff34777d60164ac7e392403c2174e Mon Sep 17 00:00:00 2001 From: Michael Wyraz Date: Fri, 25 Nov 2016 10:52:50 +0100 Subject: [PATCH 53/62] Better db update --- .../updates/froxlor/0.9/update_0.9.inc.php | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 3fd04142..d6288caf 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3549,25 +3549,12 @@ if (isFroxlorVersion('0.9.38.2')) { if (isDatabaseVersion('201611180')) { - showUpdateStep("Adding field to reflect let's-encrypt registration status"); + showUpdateStep("Adding field for let's-encrypt registration status"); Database::query("ALTER TABLE `".TABLE_PANEL_CUSTOMERS."` add `leregistered` TINYINT(1) NOT NULL DEFAULT 0;"); lastStepStatus(0); - updateToDbVersion('201611240'); -} - -if (isDatabaseVersion('201611240')) { - - showUpdateStep("Adding new setting to reflect let's-encrypt registration status"); - $stmt = Database::prepare(" - INSERT INTO `" . TABLE_PANEL_SETTINGS . "` SET - `settinggroup` = 'system', - `varname` = :varname, - `value` = :value"); - Database::pexecute($stmt, array( - 'varname' => 'leregistered', - 'value' => '0' - )); + showUpdateStep("Adding system setting for let's-encrypt registration status"); + Settings::AddNew('system.leregistered', '0'); lastStepStatus(0); updateToDbVersion('201611241'); From 301dadaa023dafb2191cf5d49d4fdf05ced1db0e Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sun, 27 Nov 2016 10:46:50 +0100 Subject: [PATCH 54/62] fix global hsts-includeSubdomain setting, thx to iam Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/131.ssl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index dc03f926..126e5559 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -164,10 +164,10 @@ return array( 'default' => 0, 'save_method' => 'storeSettingField' ), - 'system_hsts_incsub' => array( + 'system_hsts_sub' => array( 'label' => $lng['admin']['domain_hsts_incsub'], 'settinggroup' => 'system', - 'varname' => 'hsts_incsub', + 'varname' => 'hsts_sub', 'type' => 'bool', 'default' => false, 'save_method' => 'storeSettingField' From c00abc3b927dea5404c5626675a2712dee21b464 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sun, 27 Nov 2016 11:40:33 +0100 Subject: [PATCH 55/62] move froxlor hsts settings to 'froxlor vhost settings' to make clear it's only for froxlor anbd not a system-wide default for all domains; fix superfluous english text from german language file Signed-off-by: Michael Kaufmann (d00p) --- actions/admin/settings/122.froxlorvhost.php | 31 ++++++++++++++++++++- actions/admin/settings/131.ssl.php | 28 +------------------ lng/german.lng.php | 2 +- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/actions/admin/settings/122.froxlorvhost.php b/actions/admin/settings/122.froxlorvhost.php index 75e138b4..6175bb73 100644 --- a/actions/admin/settings/122.froxlorvhost.php +++ b/actions/admin/settings/122.froxlorvhost.php @@ -49,7 +49,36 @@ return array( 'type' => 'bool', 'default' => false, 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.leenabled') + 'visible' => Settings::Get('system.use_ssl') + ), + 'system_hsts_maxage' => array( + 'label' => $lng['admin']['domain_hsts_maxage'], + 'settinggroup' => 'system', + 'varname' => 'hsts_maxage', + 'type' => 'int', + 'int_min' => 0, + 'int_max' => 94608000, // 3-years + 'default' => 0, + 'save_method' => 'storeSettingField', + 'visible' => Settings::Get('system.use_ssl') + ), + 'system_hsts_incsub' => array( + 'label' => $lng['admin']['domain_hsts_incsub'], + 'settinggroup' => 'system', + 'varname' => 'hsts_incsub', + 'type' => 'bool', + 'default' => false, + 'save_method' => 'storeSettingField', + 'visible' => Settings::Get('system.use_ssl') + ), + 'system_hsts_preload' => array( + 'label' => $lng['admin']['domain_hsts_preload'], + 'settinggroup' => 'system', + 'varname' => 'hsts_preload', + 'type' => 'bool', + 'default' => false, + 'save_method' => 'storeSettingField', + 'visible' => Settings::Get('system.use_ssl') ), /** * FCGID diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php index 126e5559..56c27cd5 100644 --- a/actions/admin/settings/131.ssl.php +++ b/actions/admin/settings/131.ssl.php @@ -153,33 +153,7 @@ return array( 'type' => 'bool', 'default' => false, 'save_method' => 'storeSettingField' - ), - 'system_hsts_maxage' => array( - 'label' => $lng['admin']['domain_hsts_maxage'], - 'settinggroup' => 'system', - 'varname' => 'hsts_maxage', - 'type' => 'int', - 'int_min' => 0, - 'int_max' => 94608000, // 3-years - 'default' => 0, - 'save_method' => 'storeSettingField' - ), - 'system_hsts_sub' => array( - 'label' => $lng['admin']['domain_hsts_incsub'], - 'settinggroup' => 'system', - 'varname' => 'hsts_sub', - 'type' => 'bool', - 'default' => false, - 'save_method' => 'storeSettingField' - ), - 'system_hsts_preload' => array( - 'label' => $lng['admin']['domain_hsts_preload'], - 'settinggroup' => 'system', - 'varname' => 'hsts_preload', - 'type' => 'bool', - 'default' => false, - 'save_method' => 'storeSettingField' - ), + ) ) ) ) diff --git a/lng/german.lng.php b/lng/german.lng.php index 0af16748..490d2651 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1710,6 +1710,6 @@ $lng['admin']['webserversettings_ssl'] = 'Webserver SSL-Einstellungen'; $lng['admin']['domain_hsts_maxage']['title'] = 'HTTP Strict Transport Security (HSTS)'; $lng['admin']['domain_hsts_maxage']['description'] = '"max-age" Wert für den Strict-Transport-Security Header
Der Wert 0 deaktiviert HSTS für diese Domain. Meist wird der Wert 31536000 gerne genutzt (ein Jahr).'; $lng['admin']['domain_hsts_incsub']['title'] = 'Inkludiere HSTS für jede Subdomain'; -$lng['admin']['domain_hsts_incsub']['description'] = 'Die optionale "includeSubDomains" Direktive, wenn vorhanden, signalisiert dem UA, dass die HSTS that the HSTS Regel für diese Domain und auch jede Subdomain dieser gilt.'; +$lng['admin']['domain_hsts_incsub']['description'] = 'Die optionale "includeSubDomains" Direktive, wenn vorhanden, signalisiert dem UA, dass die HSTS Regel für diese Domain und auch jede Subdomain dieser gilt.'; $lng['admin']['domain_hsts_preload']['title'] = 'Füge Domain in die HSTS preload Liste hinzu'; $lng['admin']['domain_hsts_preload']['description'] = 'Wenn die Domain in die HSTS preload Liste, verwaltet von Chrome (und genutzt von Firefox und Safari), hinzugefügt werden soll, dann aktiviere diese Einstellung.
Die preload-Direktive zu senden kann PERMANTENTE KONSEQUENZEN haben und dazu führen, dass Benutzer auf diese Domain und auch Subdomains nicht zugreifen können.
Beachte Details unter hstspreload.appspot.com/#removal bevor ein Header mit "preload" gesendet wird.'; From 56276a19d137e8310a16c32d7b6156451b9c6b98 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sun, 27 Nov 2016 12:12:22 +0100 Subject: [PATCH 56/62] set version to 0.9.38.4 for upcoming bugfix release Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 2 +- install/updates/froxlor/0.9/update_0.9.inc.php | 6 ++++++ lib/version.inc.php | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 24bbb15e..b1962ab5 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -577,7 +577,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'customer_hide_options', ''), - ('panel', 'version', '0.9.38.3'), + ('panel', 'version', '0.9.38.4'), ('panel', 'db_version', '201611180'); diff --git a/install/updates/froxlor/0.9/update_0.9.inc.php b/install/updates/froxlor/0.9/update_0.9.inc.php index 8fb02c7a..72c39d89 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3546,3 +3546,9 @@ if (isFroxlorVersion('0.9.38.2')) { showUpdateStep("Updating from 0.9.38.2 to 0.9.38.3", false); updateToVersion('0.9.38.3'); } + +if (isFroxlorVersion('0.9.38.3')) { + + showUpdateStep("Updating from 0.9.38.3 to 0.9.38.4", false); + updateToVersion('0.9.38.4'); +} diff --git a/lib/version.inc.php b/lib/version.inc.php index 915532b7..6e9c41fb 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,7 +16,7 @@ */ // Main version variable -$version = '0.9.38.3'; +$version = '0.9.38.4'; // Database version (YYYYMMDDC where C is a daily counter) $dbversion = '201611180'; From 7b6bbcec48a40602fbaf9e248420a9deab4a7d93 Mon Sep 17 00:00:00 2001 From: micw Date: Sun, 27 Nov 2016 12:45:06 +0100 Subject: [PATCH 57/62] Fixed default LE license URL (removed testing stuff) --- lib/classes/ssl/class.lescript.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php index 1d3aa5bb..f0d7c11f 100644 --- a/lib/classes/ssl/class.lescript.php +++ b/lib/classes/ssl/class.lescript.php @@ -629,7 +629,7 @@ class Client // Fallback: use latest known license. This is only valid for let's encrypt and should be removed as soon as there is an official // ACME-endpoint to get the current ToS - return "xxxhttps://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf]"; + return "https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"; // return ""; } From 1b18ec45be83088085f0834aa29f8d7f1c4a712b Mon Sep 17 00:00:00 2001 From: Janos Muzsi Date: Sun, 27 Nov 2016 23:18:23 +0100 Subject: [PATCH 58/62] correcting lighttpd settings --- scripts/jobs/cron_tasks.inc.http.20.lighttpd.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 9ca21da1..5b7fc780 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -435,13 +435,11 @@ class lighttpd extends HttpConfigBase // Get domain's redirect code $code = getDomainRedirectCode($domain['id'], '301'); - - $vhost_content .= ' $HTTP["host"] =~ "^(.*)$" {'. "\n"; - $vhost_content .= ' url.redirect-code = ' . $code. "\n"; - $vhost_content .= ' url.redirect = (' . "\n"; - $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; - $vhost_content .= ' )' . "\n"; - $vhost_content .= ' }' . "\n"; + + $vhost_content .= ' url.redirect-code = ' . $code. "\n"; + $vhost_content .= ' url.redirect = (' . "\n"; + $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; + $vhost_content .= ' )' . "\n"; } else { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true, true); From 225539d2e7cf61f6e7c0440c424c9d6bb201ae30 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Tue, 29 Nov 2016 09:34:33 +0100 Subject: [PATCH 59/62] show ssl-related settings only if customer has ssl-ip assigned (not yet checked per domain); fix hsts-includeSubdomain setting for fresh installations Signed-off-by: Michael Kaufmann (d00p) --- customer_domains.php | 16 +++++++++++++--- install/froxlor.sql | 2 +- .../customer/domains/formfield.domains_add.php | 8 ++------ .../customer/domains/formfield.domains_edit.php | 8 ++------ 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/customer_domains.php b/customer_domains.php index 06471cb8..cc2a637e 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -517,7 +517,12 @@ if ($page == 'overview') { // check if we at least have one ssl-ip/port, #1179 $ssl_ipsandports = ''; - $ssl_ip_stmt = Database::prepare("SELECT COUNT(*) as countSSL FROM `panel_ipsandports` WHERE `ssl`='1'"); + $ssl_ip_stmt = Database::prepare(" + SELECT COUNT(*) as countSSL + FROM `".TABLE_PANEL_IPSANDPORTS."` pip + LEFT JOIN `".TABLE_DOMAINTOIP."` dti ON dti.id_ipandports = pip.id + WHERE pip.`ssl`='1' + "); Database::pexecute($ssl_ip_stmt); $resultX = $ssl_ip_stmt->fetch(PDO::FETCH_ASSOC); if (isset($resultX['countSSL']) && (int)$resultX['countSSL'] > 0) { @@ -797,8 +802,13 @@ if ($page == 'overview') { // check if we at least have one ssl-ip/port, #1179 $ssl_ipsandports = ''; - $ssl_ip_stmt = Database::prepare("SELECT COUNT(*) as countSSL FROM `panel_ipsandports` WHERE `ssl`='1'"); - Database::pexecute($ssl_ip_stmt); + $ssl_ip_stmt = Database::prepare(" + SELECT COUNT(*) as countSSL + FROM `".TABLE_PANEL_IPSANDPORTS."` pip + LEFT JOIN `".TABLE_DOMAINTOIP."` dti ON dti.id_ipandports = pip.id + WHERE `dti`.`id_domain` = :id_domain AND pip.`ssl`='1' + "); + Database::pexecute($ssl_ip_stmt, array("id_domain" => $result['id'])); $resultX = $ssl_ip_stmt->fetch(PDO::FETCH_ASSOC); if (isset($resultX['countSSL']) && (int)$resultX['countSSL'] > 0) { $ssl_ipsandports = 'notempty'; diff --git a/install/froxlor.sql b/install/froxlor.sql index b1962ab5..947e6b3a 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -544,7 +544,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'mail_smtp_user', ''), ('system', 'mail_smtp_passwd', ''), ('system', 'hsts_maxage', '0'), - ('system', 'hsts_sub', '0'), + ('system', 'hsts_incsub', '0'), ('system', 'hsts_preload', '0'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin@SERVERNAME'), diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index 1371e579..238adfff 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -76,10 +76,9 @@ return array( 'section_bssl' => array( 'title' => $lng['admin']['webserversettings_ssl'], 'image' => 'icons/domain_add.png', - 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'visible' => Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false, 'fields' => array( 'ssl_redirect' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['domains']['ssl_redirect']['title'], 'desc' => $lng['domains']['ssl_redirect']['description'], 'type' => 'checkbox', @@ -89,7 +88,7 @@ return array( 'value' => array() ), 'letsencrypt' => array( - 'visible' => (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), + 'visible' => (Settings::Get('system.leenabled') == '1' ? true : false), 'label' => $lng['customer']['letsencrypt']['title'], 'desc' => $lng['customer']['letsencrypt']['description'], 'type' => 'checkbox', @@ -99,7 +98,6 @@ return array( 'value' => array() ), 'hsts_maxage' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_maxage']['title'], 'desc' => $lng['admin']['domain_hsts_maxage']['description'], 'type' => 'int', @@ -108,7 +106,6 @@ return array( 'value' => 0 ), 'hsts_sub' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], 'type' => 'checkbox', @@ -118,7 +115,6 @@ return array( 'value' => array() ), 'hsts_preload' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_preload']['title'], 'desc' => $lng['admin']['domain_hsts_preload']['description'], 'type' => 'checkbox', diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index 94bab096..6ac6d186 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -87,10 +87,9 @@ return array( 'section_bssl' => array( 'title' => $lng['admin']['webserversettings_ssl'], 'image' => 'icons/domain_edit.png', - 'visible' => Settings::Get('system.use_ssl') == '1' ? true : false, + 'visible' => Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false, 'fields' => array( 'ssl_redirect' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false), 'label' => $lng['domains']['ssl_redirect']['title'], 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''), 'type' => 'checkbox', @@ -100,7 +99,7 @@ return array( 'value' => array($result['ssl_redirect']) ), 'letsencrypt' => array( - 'visible' => (Settings::Get('system.use_ssl') == '1' ? (Settings::Get('system.leenabled') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false) : false), + 'visible' => Settings::Get('system.leenabled') == '1' ? true : false, 'label' => $lng['customer']['letsencrypt']['title'], 'desc' => $lng['customer']['letsencrypt']['description'], 'type' => 'checkbox', @@ -110,7 +109,6 @@ return array( 'value' => array($result['letsencrypt']) ), 'hsts_maxage' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_maxage']['title'], 'desc' => $lng['admin']['domain_hsts_maxage']['description'], 'type' => 'int', @@ -119,7 +117,6 @@ return array( 'value' => $result['hsts'] ), 'hsts_sub' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_incsub']['title'], 'desc' => $lng['admin']['domain_hsts_incsub']['description'], 'type' => 'checkbox', @@ -129,7 +126,6 @@ return array( 'value' => array($result['hsts_sub']) ), 'hsts_preload' => array( - 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['admin']['domain_hsts_preload']['title'], 'desc' => $lng['admin']['domain_hsts_preload']['description'], 'type' => 'checkbox', From 001786dd9719cd117225c4aebc1bb95c1e9bafb7 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Fri, 9 Dec 2016 13:33:57 +0100 Subject: [PATCH 60/62] fix incorrect User-Agent header in let's encrypt class, fixes #1683 Signed-off-by: Michael Kaufmann (d00p) --- lib/classes/ssl/class.lescript.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php index dc8ec83b..82f3056f 100644 --- a/lib/classes/ssl/class.lescript.php +++ b/lib/classes/ssl/class.lescript.php @@ -188,7 +188,7 @@ class lescript $this->log("Token for $domain saved at $tokenPath and should be available at $uri"); // simple self check - $selfcheckContextOptions = array('http' => array('header' => "User Agent: Froxlor/".$this->version)); + $selfcheckContextOptions = array('http' => array('header' => "User-Agent: Froxlor/".$this->version)); $selfcheckContext = stream_context_create($selfcheckContextOptions); if ($payload !== trim(@file_get_contents($uri, false, $selfcheckContext))) { $errmsg = json_encode(error_get_last()); From 18514f018069c1a5f9b3b812ff775a82fcf702e6 Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sat, 10 Dec 2016 21:43:28 +0100 Subject: [PATCH 61/62] fix undefined array when processing specialsettings, fixes #1684 Signed-off-by: Michael Kaufmann (d00p) --- scripts/jobs/cron_tasks.inc.http.10.apache.php | 9 +++++++++ .../jobs/cron_tasks.inc.http.20.lighttpd.php | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index b6a9697a..1f45d934 100644 --- a/scripts/jobs/cron_tasks.inc.http.10.apache.php +++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php @@ -344,6 +344,15 @@ class apache extends HttpConfigBase ); } } // end of ssl-redirect check + else + { + // fallback of froxlor domain-data for processSpecialConfigTemplate() + $domain = array( + 'domain' => Settings::Get('system.hostname'), + 'loginname' => 'froxlor.panel', + 'documentroot' => $mypath + ); + } /** * dirprotection, see #72 diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index a1869a42..aa06b527 100644 --- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php +++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php @@ -162,7 +162,25 @@ class lighttpd extends HttpConfigBase $this->lighttpd_data[$vhost_filename] .= "\t" . ')' . "\n"; $this->lighttpd_data[$vhost_filename] .= "\t" . ')' . "\n"; $this->lighttpd_data[$vhost_filename] .= ' )' . "\n"; + } else { + $domain = array( + 'id' => 'none', + 'domain' => Settings::Get('system.hostname'), + 'adminid' => 1, /* first admin-user (superadmin) */ + 'guid' => Settings::Get('system.httpuser'), + 'openbasedir' => 0, + 'email' => Settings::Get('panel.adminmail'), + 'loginname' => 'froxlor.panel', + 'documentroot' => $mypath + ); } + } else { + // fallback of froxlor domain-data for processSpecialConfigTemplate() + $domain = array( + 'domain' => Settings::Get('system.hostname'), + 'loginname' => 'froxlor.panel', + 'documentroot' => $mypath + ); } if ($row_ipsandports['specialsettings'] != '') { From 3a8996aee2125e85872aff2e5b29381dd94258db Mon Sep 17 00:00:00 2001 From: "Michael Kaufmann (d00p)" Date: Sun, 11 Dec 2016 08:29:54 +0100 Subject: [PATCH 62/62] add missing fields that are only added via update Signed-off-by: Michael Kaufmann (d00p) --- install/froxlor.sql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/install/froxlor.sql b/install/froxlor.sql index 8856efbf..ea9da93f 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -195,8 +195,9 @@ CREATE TABLE `panel_customers` ( `theme` varchar(255) NOT NULL default 'Sparkle', `custom_notes` text, `custom_notes_show` tinyint(1) NOT NULL default '0', - `lepublickey` mediumtext DEFAULT NULL, - `leprivatekey` mediumtext DEFAULT NULL, + `lepublickey` mediumtext default NULL, + `leprivatekey` mediumtext default NULL, + `leregistered` tinyint(1) NOT NULL default '0' PRIMARY KEY (`customerid`), UNIQUE KEY `loginname` (`loginname`) ) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci; @@ -547,6 +548,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES ('system', 'hsts_maxage', '0'), ('system', 'hsts_incsub', '0'), ('system', 'hsts_preload', '0'), + ('system', 'leregistered', '0'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin@SERVERNAME'), ('panel', 'phpmyadmin_url', ''),