diff --git a/install/froxlor.sql b/install/froxlor.sql index 6c08cef8..4d86f8e8 100644 --- a/install/froxlor.sql +++ b/install/froxlor.sql @@ -268,6 +268,10 @@ CREATE TABLE `panel_domains` ( `notryfiles` tinyint(1) DEFAULT '0', `writeaccesslog` tinyint(1) DEFAULT '1', `writeerrorlog` tinyint(1) DEFAULT '1', + `override_tls` tinyint(1) DEFAULT '0', + `ssl_protocols` text, + `ssl_cipher_list` text, + `tlsv13_cipher_list` text, PRIMARY KEY (`id`), KEY `customerid` (`customerid`), KEY `parentdomain` (`parentdomainid`), @@ -692,7 +696,7 @@ opcache.interned_strings_buffer'), ('panel', 'customer_hide_options', ''), ('panel', 'is_configured', '0'), ('panel', 'version', '0.10.2'), - ('panel', 'db_version', '201910120'); + ('panel', 'db_version', '201910200'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php index def561cd..7355ea8e 100644 --- a/install/updates/froxlor/0.10/update_0.10.inc.php +++ b/install/updates/froxlor/0.10/update_0.10.inc.php @@ -410,3 +410,15 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.1')) { showUpdateStep("Updating from 0.10.1 to 0.10.2", false); \Froxlor\Froxlor::updateToVersion('0.10.2'); } + +if (\Froxlor\Froxlor::isDatabaseVersion('201910120')) { + + showUpdateStep("Adding new TLS options to domains-table"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `override_tls` tinyint(1) DEFAULT '0' AFTER `writeerrorlog`;"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_protocols` text AFTER `override_tls`;"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `ssl_cipher_list` text AFTER `ssl_protocols`;"); + Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ADD `tlsv13_cipher_list` text AFTER `ssl_cipher_list`;"); + lastStepStatus(0); + + \Froxlor\Froxlor::updateToDbVersion('201910200'); +} diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 035a15fd..8fb5c190 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -187,6 +187,14 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn * optional whether or not to preload HSTS header value * @param bool $ocsp_stapling * optional whether to enable ocsp-stapling for this domain. default 0 (false), requires SSL + * @param bool $override_tls + * optional whether or not to override system-tls settings like protocol, ssl-ciphers and if applicable tls-1.3 ciphers, requires change_serversettings flag for the admin, default false + * @param array $ssl_protocols + * optional list of allowed/used ssl/tls protocols, see system.ssl_protocols setting, only used/required if $override_tls is true, default empty or system.ssl_protocols setting if $override_tls is true + * @param string $ssl_cipher_list + * optional list of allowed/used ssl/tls ciphers, see system.ssl_cipher_list setting, only used/required if $override_tls is true, default empty or system.ssl_cipher_list setting if $override_tls is true + * @param string $tlsv13_cipher_list + * optional list of allowed/used tls-1.3 specific ciphers, see system.tlsv13_cipher_list setting, only used/required if $override_tls is true, default empty or system.tlsv13_cipher_list setting if $override_tls is true * * @access admin * @throws \Exception @@ -239,6 +247,19 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $hsts_preload = $this->getBoolParam('hsts_preload', true, 0); $ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, 0); + $override_tls = $this->getBoolParam('override_tls', true, 0); + $p_ssl_protocols = array(); + $ssl_cipher_list = ""; + $tlsv13_cipher_list = ""; + + if ($this->getUserDetail('change_serversettings') == '1') { + if ($override_tls) { + $p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', Settings::Get('system.ssl_protocols'))); + $ssl_cipher_list = $this->getParam('ssl_cipher_list', true, Settings::Get('system.ssl_cipher_list')); + $tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, Settings::Get('system.tlsv13_cipher_list')); + } + } + // validation if ($p_domain == Settings::Get('system.hostname')) { \Froxlor\UI\Response::standard_error('admin_domain_emailsystemhostname', '', true); @@ -325,6 +346,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn } else { $documentroot = $_documentroot; } + + $ssl_protocols = array(); + if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { + $p_ssl_protocols = array( + $p_ssl_protocols + ); + } + if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) { + $p_ssl_protocols = json_decode($p_ssl_protocols, true); + } + if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { + $protocols_available = array( + 'TLSv1', + 'TLSv1.1', + 'TLSv1.2', + 'TLSv1.3' + ); + foreach ($p_ssl_protocols as $ssl_protocol) { + if (! in_array(trim($ssl_protocol), $protocols_available)) { + $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); + continue; + } + $ssl_protocols[] = $ssl_protocol; + } + } + if (empty($ssl_protocols)) { + $override_tls = '0'; + } } else { $isbinddomain = '0'; if (Settings::Get('system.bind_enable') == '1') { @@ -340,6 +389,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $writeaccesslog = '1'; $writeerrorlog = '1'; $documentroot = $_documentroot; + $override_tls = '0'; + $ssl_protocols = array(); } if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { @@ -574,7 +625,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn 'hsts' => $hsts_maxage, 'hsts_sub' => $hsts_sub, 'hsts_preload' => $hsts_preload, - 'ocsp_stapling' => $ocsp_stapling + 'ocsp_stapling' => $ocsp_stapling, + 'override_tls' => $override_tls, + 'ssl_protocols' => implode(",", $ssl_protocols), + 'ssl_cipher_list' => $ssl_cipher_list, + 'tlsv13_cipher_list' => $tlsv13_cipher_list ); $ins_stmt = Database::prepare(" @@ -618,7 +673,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, - `ocsp_stapling` = :ocsp_stapling + `ocsp_stapling` = :ocsp_stapling, + `override_tls` = :override_tls, + `ssl_protocols` = :ssl_protocols, + `ssl_cipher_list` = :ssl_cipher_list, + `tlsv13_cipher_list` = :tlsv13_cipher_list "); Database::pexecute($ins_stmt, $ins_data, true, true); $domainid = Database::lastInsertId(); @@ -823,6 +882,24 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $hsts_preload = $this->getBoolParam('hsts_preload', true, $result['hsts_preload']); $ocsp_stapling = $this->getBoolParam('ocsp_stapling', true, $result['ocsp_stapling']); + $override_tls = $this->getBoolParam('override_tls', true, $result['override_tls']); + + if ($this->getUserDetail('change_serversettings') == '1') { + if ($override_tls) { + $p_ssl_protocols = $this->getParam('ssl_protocols', true, explode(',', $result['ssl_protocols'])); + $ssl_cipher_list = $this->getParam('ssl_cipher_list', true, $result['ssl_cipher_list']); + $tlsv13_cipher_list = $this->getParam('tlsv13_cipher_list', true, $result['tlsv13_cipher_list']); + } else { + $p_ssl_protocols = array(); + $ssl_cipher_list = ""; + $tlsv13_cipher_list = ""; + } + } else { + $p_ssl_protocols = explode(',', $result['ssl_protocols']); + $ssl_cipher_list = $result['ssl_cipher_list']; + $tlsv13_cipher_list = $result['tlsv13_cipher_list']; + } + // count subdomain usage of source-domain $subdomains_stmt = Database::prepare(" SELECT COUNT(`id`) AS count FROM `" . TABLE_PANEL_DOMAINS . "` WHERE @@ -992,6 +1069,34 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn if (! preg_match('/^https?\:\/\//', $documentroot) && strstr($documentroot, ":") !== false) { \Froxlor\UI\Response::standard_error('pathmaynotcontaincolon', '', true); } + + $ssl_protocols = array(); + if (! empty($p_ssl_protocols) && is_numeric($p_ssl_protocols)) { + $p_ssl_protocols = array( + $p_ssl_protocols + ); + } + if (! empty($p_ssl_protocols) && ! is_array($p_ssl_protocols)) { + $p_ssl_protocols = json_decode($p_ssl_protocols, true); + } + if (! empty($p_ssl_protocols) && is_array($p_ssl_protocols)) { + $protocols_available = array( + 'TLSv1', + 'TLSv1.1', + 'TLSv1.2', + 'TLSv1.3' + ); + foreach ($p_ssl_protocols as $ssl_protocol) { + if (! in_array(trim($ssl_protocol), $protocols_available)) { + $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_DEBUG, "[API] unknown SSL protocol '" . trim($ssl_protocol) . "'"); + continue; + } + $ssl_protocols[] = $ssl_protocol; + } + } + if (empty($ssl_protocols)) { + $override_tls = '0'; + } } else { $isbinddomain = $result['isbinddomain']; $zonefile = $result['zonefile']; @@ -1004,6 +1109,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $writeaccesslog = $result['writeaccesslog']; $writeerrorlog = $result['writeerrorlog']; $documentroot = $result['documentroot']; + + $override_tls = $result['override_tls']; } if ($this->getUserDetail('caneditphpsettings') == '1' || $this->getUserDetail('change_serversettings') == '1') { @@ -1337,6 +1444,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $update_data['hsts_sub'] = $hsts_sub; $update_data['hsts_preload'] = $hsts_preload; $update_data['ocsp_stapling'] = $ocsp_stapling; + $update_data['override_tls'] = $override_tls; + $update_data['ssl_protocols'] = implode(",", $ssl_protocols); + $update_data['ssl_cipher_list'] = $ssl_cipher_list; + $update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list; $update_data['id'] = $id; $update_stmt = Database::prepare(" @@ -1375,7 +1486,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn `hsts` = :hsts, `hsts_sub` = :hsts_sub, `hsts_preload` = :hsts_preload, - `ocsp_stapling` = :ocsp_stapling + `ocsp_stapling` = :ocsp_stapling, + `override_tls` = :override_tls, + `ssl_protocols` = :ssl_protocols, + `ssl_cipher_list` = :ssl_cipher_list, + `tlsv13_cipher_list` = :tlsv13_cipher_list WHERE `id` = :id "); Database::pexecute($update_stmt, $update_data, true, true); @@ -1386,6 +1501,10 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn $_update_data['openbasedir'] = $openbasedir; $_update_data['mod_fcgid_starter'] = $mod_fcgid_starter; $_update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; + $_update_data['override_tls'] = $override_tls; + $_update_data['ssl_protocols'] = implode(",", $ssl_protocols); + $_update_data['ssl_cipher_list'] = $ssl_cipher_list; + $_update_data['tlsv13_cipher_list'] = $tlsv13_cipher_list; $_update_data['parentdomainid'] = $id; // if php config is to be set for all subdomains, check here @@ -1410,7 +1529,11 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `mod_fcgid_starter` = :mod_fcgid_starter, - `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests + `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, + `override_tls` = :override_tls, + `ssl_protocols` = :ssl_protocols, + `ssl_cipher_list` = :ssl_cipher_list, + `tlsv13_cipher_list` = :tlsv13_cipher_list " . $update_phpconfig . $upd_specialsettings . $updatechildren . $update_sslredirect . " WHERE `parentdomainid` = :parentdomainid "); diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 5aeb1cf0..00847da9 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -270,7 +270,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc `http2` = :http2, `hsts` = :hsts, `hsts_sub` = :hsts_sub, - `hsts_preload` = :hsts_preload + `hsts_preload` = :hsts_preload, + `ocsp_stapling` = :ocsp_stapling, + `override_tls` = :override_tls, + `ssl_protocols` = :ssl_protocols, + `ssl_cipher_list` = :ssl_cipher_list, + `tlsv13_cipher_list` = :tlsv13_cipher_list "); $params = array( "customerid" => $customer['customerid'], @@ -295,7 +300,12 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc "http2" => $http2, "hsts" => $hsts_maxage, "hsts_sub" => $hsts_sub, - "hsts_preload" => $hsts_preload + "hsts_preload" => $hsts_preload, + "ocsp_stapling" => $domain_check['ocsp_stapling'], + "override_tls" => $domain_check['override_tls'], + "ssl_protocols" => $domain_check['ssl_protocols'], + "ssl_cipher_list" => $domain_check['ssl_cipher_list'], + "tlsv13_cipher_list" => $domain_check['tlsv13_cipher_list'] ); Database::pexecute($stmt, $params, true, true); $subdomain_id = Database::lastInsertId(); diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php index c1aba56c..6fd05880 100644 --- a/lib/Froxlor/Cron/Http/Apache.php +++ b/lib/Froxlor/Cron/Http/Apache.php @@ -178,7 +178,7 @@ class Apache extends HttpConfigBase $this->virtualhosts_data[$vhosts_filename] .= ' ServerName ' . Settings::Get('system.hostname') . "\n"; $froxlor_aliases = Settings::Get('system.froxloraliases'); - if (!empty($froxlor_aliases)) { + if (! empty($froxlor_aliases)) { $froxlor_aliases = explode(",", $froxlor_aliases); $aliases = ""; foreach ($froxlor_aliases as $falias) { @@ -187,7 +187,7 @@ class Apache extends HttpConfigBase } } $aliases = trim($aliases); - if (!empty($aliases)) { + if (! empty($aliases)) { $this->virtualhosts_data[$vhosts_filename] .= ' ServerAlias ' . $aliases . "\n"; } } @@ -483,7 +483,7 @@ class Apache extends HttpConfigBase $this->virtualhosts_data[$vhosts_filename] .= ' SSLHonorCipherOrder On' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite ' . Settings::Get('system.ssl_cipher_list') . "\n"; $protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols'))); - if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) { + if (in_array("TLSv1.3", $protocols) && ! empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) { $this->virtualhosts_data[$vhosts_filename] .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n"; } $this->virtualhosts_data[$vhosts_filename] .= ' SSLVerifyDepth 10' . "\n"; @@ -967,8 +967,13 @@ class Apache extends HttpConfigBase } if ($domain['ssl_cert_file'] != '') { + + $ssl_protocols = ($domain['override_tls'] == '1' && ! empty($domain['ssl_protocols'])) ? $domain['ssl_protocols'] : Settings::Get('system.ssl_protocols'); + $ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + $tlsv13_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['tlsv13_cipher_list'])) ? $domain['tlsv13_cipher_list'] : Settings::Get('system.tlsv13_cipher_list'); + $vhost_content .= ' SSLEngine On' . "\n"; - $vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", Settings::Get('system.ssl_protocols')) . "\n"; + $vhost_content .= ' SSLProtocol -ALL +' . str_replace(",", " +", $ssl_protocols) . "\n"; if (Settings::Get('system.apache24') == '1') { if (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1') { $vhost_content .= ' Protocols h2 http/1.1' . "\n"; @@ -984,10 +989,10 @@ class Apache extends HttpConfigBase } // 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"; - $protocols = array_map('trim', explode(",", Settings::Get('system.ssl_protocols'))); - if (in_array("TLSv1.3", $protocols) && !empty(Settings::Get('system.tlsv13_cipher_list')) && Settings::Get('system.apache24') == 1) { - $vhost_content .= ' SSLCipherSuite TLSv1.3 ' . Settings::Get('system.tlsv13_cipher_list') . "\n"; + $vhost_content .= ' SSLCipherSuite ' . $ssl_cipher_list . "\n"; + $protocols = array_map('trim', explode(",", $ssl_protocols)); + if (in_array("TLSv1.3", $protocols) && ! empty($tlsv13_cipher_list) && Settings::Get('system.apache24') == 1) { + $vhost_content .= ' SSLCipherSuite TLSv1.3 ' . $tlsv13_cipher_list . "\n"; } $vhost_content .= ' SSLVerifyDepth 10' . "\n"; $vhost_content .= ' SSLCertificateFile ' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . "\n"; diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php index cdd66ed9..4f94f0f8 100644 --- a/lib/Froxlor/Cron/Http/Lighttpd.php +++ b/lib/Froxlor/Cron/Http/Lighttpd.php @@ -570,6 +570,8 @@ class Lighttpd extends HttpConfigBase if ($domain['ssl_cert_file'] != '') { + $ssl_cipher_list = ($domain['override_tls'] == '1' && ! empty($domain['ssl_cipher_list'])) ? $domain['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + // ssl.engine only necessary once in the ip/port vhost (SERVER['socket'] condition) // $ssl_settings .= 'ssl.engine = "enable"' . "\n"; $ssl_settings .= 'ssl.use-compression = "disable"' . "\n"; @@ -583,7 +585,7 @@ class Lighttpd extends HttpConfigBase } $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.cipher-list = "' . $ssl_cipher_list . '"' . "\n"; $ssl_settings .= 'ssl.honor-cipher-order = "enable"' . "\n"; $ssl_settings .= 'ssl.pemfile = "' . \Froxlor\FileDir::makeCorrectFile($domain['ssl_cert_file']) . '"' . "\n"; diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php index 0f8f9943..84e69f8d 100644 --- a/lib/Froxlor/Cron/Http/Nginx.php +++ b/lib/Froxlor/Cron/Http/Nginx.php @@ -678,10 +678,14 @@ class Nginx extends HttpConfigBase if (! file_exists($domain_or_ip['ssl_cert_file'])) { \Froxlor\FroxlorLogger::getInstanceOf()->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_ERR, $domain_or_ip['domain'] . ' :: certificate file "' . $domain_or_ip['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives'); } else { + + $ssl_protocols = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_protocols'])) ? $domain_or_ip['ssl_protocols'] : Settings::Get('system.ssl_protocols'); + $ssl_cipher_list = (isset($domain_or_ip['override_tls']) && $domain_or_ip['override_tls'] == '1' && ! empty($domain_or_ip['ssl_cipher_list'])) ? $domain_or_ip['ssl_cipher_list'] : Settings::Get('system.ssl_cipher_list'); + // obsolete: ssl on now belongs to the listen block as 'ssl' at the end // $sslsettings .= "\t" . 'ssl on;' . "\n"; - $sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", Settings::Get('system.ssl_protocols')) . ';' . "\n"; - $sslsettings .= "\t" . 'ssl_ciphers ' . Settings::Get('system.ssl_cipher_list') . ';' . "\n"; + $sslsettings .= "\t" . 'ssl_protocols ' . str_replace(",", " ", $ssl_protocols) . ';' . "\n"; + $sslsettings .= "\t" . 'ssl_ciphers ' . $ssl_cipher_list . ';' . "\n"; if (! empty(Settings::Get('system.dhparams_file'))) { $dhparams = \Froxlor\FileDir::makeCorrectFile(Settings::Get('system.dhparams_file')); if (! file_exists($dhparams)) { diff --git a/lib/Froxlor/Cron/Http/WebserverBase.php b/lib/Froxlor/Cron/Http/WebserverBase.php index fa958c05..fbca2677 100644 --- a/lib/Froxlor/Cron/Http/WebserverBase.php +++ b/lib/Froxlor/Cron/Http/WebserverBase.php @@ -36,9 +36,7 @@ class WebserverBase `d`.`phpsettingid`, `c`.`adminid`, `c`.`guid`, `c`.`email`, `c`.`documentroot` AS `customerroot`, `c`.`deactivated`, `c`.`phpenabled` AS `phpenabled_customer`, - `d`.`phpenabled` AS `phpenabled_vhost`, - `d`.`mod_fcgid_starter`,`d`.`mod_fcgid_maxrequests`, - `d`.`ocsp_stapling` + `d`.`phpenabled` AS `phpenabled_vhost` FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index a7f0c7a3..7c214359 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -10,7 +10,7 @@ final class Froxlor const VERSION = '0.10.2'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '201910120'; + const DBVERSION = '201910200'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lib/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index b18aa610..05b4e8f8 100644 --- a/lib/formfields/admin/domains/formfield.domains_add.php +++ b/lib/formfields/admin/domains/formfield.domains_add.php @@ -180,6 +180,12 @@ return array( 'image' => 'icons/domain_add.png', 'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? true : false, 'fields' => array( + 'no_ssl_available_info' => array( + 'visible' => ($ssl_ipsandports == '' ? true : false), + 'label' => 'SSL', + 'type' => 'label', + 'value' => $lng['panel']['nosslipsavailable'] + ), 'ssl_ipandport' => array( 'label' => $lng['domains']['ipandport_ssl_multi']['title'], 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], @@ -188,26 +194,6 @@ return array( 'value' => explode(',', \Froxlor\Settings::Get('system.defaultsslip')), 'is_array' => 1 ), - 'ssl_specialsettings' => array( - 'visible' => ($userinfo['change_serversettings'] == '1' ? true : false), - 'style' => 'align-top', - 'label' => $lng['admin']['ownsslvhostsettings'], - 'desc' => $lng['serversettings']['default_vhostconf']['description'], - 'type' => 'textarea', - 'cols' => 60, - 'rows' => 12 - ), - 'include_specialsettings' => array( - 'label' => $lng['admin']['include_ownvhostsettings'], - 'type' => 'checkbox', - 'values' => array( - array( - 'label' => $lng['panel']['yes'], - 'value' => '1' - ) - ), - 'value' => array() - ), 'ssl_redirect' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['domains']['ssl_redirect']['title'], @@ -247,11 +233,81 @@ return array( ), 'value' => array() ), - 'no_ssl_available_info' => array( - 'visible' => ($ssl_ipsandports == '' ? true : false), - 'label' => 'SSL', - 'type' => 'label', - 'value' => $lng['panel']['nosslipsavailable'] + 'override_tls' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'label' => $lng['admin']['domain_override_tls'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array() + ), + 'ssl_protocols' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' ? true : false), + 'label' => $lng['serversettings']['ssl']['ssl_protocols']['title'], + 'desc' => $lng['serversettings']['ssl']['ssl_protocols']['description'], + 'type' => 'checkbox', + 'value' => array( + 'TLSv1', + 'TLSv1.2' + ), + 'values' => array( + array( + 'value' => 'TLSv1', + 'label' => 'TLSv1
' + ), + array( + 'value' => 'TLSv1.1', + 'label' => 'TLSv1.1
' + ), + array( + 'value' => 'TLSv1.2', + 'label' => 'TLSv1.2
' + ), + array( + 'value' => 'TLSv1.3', + 'label' => 'TLSv1.3
' + ) + ), + 'is_array' => 1 + ), + 'ssl_cipher_list' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'label' => $lng['serversettings']['ssl']['ssl_cipher_list']['title'], + 'desc' => $lng['serversettings']['ssl']['ssl_cipher_list']['description'], + 'type' => 'text', + 'value' => \Froxlor\Settings::Get('system.ssl_cipher_list') + ), + 'tlsv13_cipher_list' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1 ? true : false), + 'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'], + 'desc' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'], + 'type' => 'text', + 'value' => \Froxlor\Settings::Get('system.tlsv13_cipher_list') + ), + 'ssl_specialsettings' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'style' => 'align-top', + 'label' => $lng['admin']['ownsslvhostsettings'], + 'desc' => $lng['serversettings']['default_vhostconf']['description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12 + ), + 'include_specialsettings' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'label' => $lng['admin']['include_ownvhostsettings'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array() ), 'hsts_maxage' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), diff --git a/lib/formfields/admin/domains/formfield.domains_edit.php b/lib/formfields/admin/domains/formfield.domains_edit.php index 2bcee8da..22d9eea2 100644 --- a/lib/formfields/admin/domains/formfield.domains_edit.php +++ b/lib/formfields/admin/domains/formfield.domains_edit.php @@ -212,6 +212,12 @@ return array( 'image' => 'icons/domain_edit.png', 'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? true : false, 'fields' => array( + 'no_ssl_available_info' => array( + 'visible' => ($ssl_ipsandports == '' ? true : false), + 'label' => 'SSL', + 'type' => 'label', + 'value' => $lng['panel']['nosslipsavailable'] + ), 'ssl_ipandport' => array( 'label' => $lng['domains']['ipandport_ssl_multi']['title'], 'desc' => $lng['domains']['ipandport_ssl_multi']['description'], @@ -220,29 +226,6 @@ return array( 'value' => $usedips, 'is_array' => 1 ), - 'ssl_specialsettings' => array( - 'visible' => ($userinfo['change_serversettings'] == '1' ? true : false), - 'style' => 'align-top', - 'label' => $lng['admin']['ownsslvhostsettings'], - 'desc' => $lng['serversettings']['default_vhostconf']['description'], - 'type' => 'textarea', - 'cols' => 60, - 'rows' => 12, - 'value' => $result['ssl_specialsettings'] - ), - 'include_specialsettings' => array( - 'label' => $lng['admin']['include_ownvhostsettings'], - 'type' => 'checkbox', - 'values' => array( - array( - 'label' => $lng['panel']['yes'], - 'value' => '1' - ) - ), - 'value' => array( - $result['include_specialsettings'] - ) - ), 'ssl_redirect' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), 'label' => $lng['domains']['ssl_redirect']['title'], @@ -288,11 +271,82 @@ return array( $result['http2'] ) ), - 'no_ssl_available_info' => array( - 'visible' => ($ssl_ipsandports == '' ? true : false), - 'label' => 'SSL', - 'type' => 'label', - 'value' => $lng['panel']['nosslipsavailable'] + 'override_tls' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'label' => $lng['admin']['domain_override_tls'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array( + $result['override_tls'] + ) + ), + 'ssl_protocols' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' ? true : false), + 'label' => $lng['serversettings']['ssl']['ssl_protocols']['title'], + 'desc' => $lng['serversettings']['ssl']['ssl_protocols']['description'], + 'type' => 'checkbox', + 'value' => !empty($result['ssl_protocols']) ? explode(",", $result['ssl_protocols']) : explode(",", \Froxlor\Settings::Get('system.ssl_protocols')), + 'values' => array( + array( + 'value' => 'TLSv1', + 'label' => 'TLSv1
' + ), + array( + 'value' => 'TLSv1.1', + 'label' => 'TLSv1.1
' + ), + array( + 'value' => 'TLSv1.2', + 'label' => 'TLSv1.2
' + ), + array( + 'value' => 'TLSv1.3', + 'label' => 'TLSv1.3
' + ) + ), + 'is_array' => 1 + ), + 'ssl_cipher_list' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' ? true : false), + 'label' => $lng['serversettings']['ssl']['ssl_cipher_list']['title'], + 'desc' => $lng['serversettings']['ssl']['ssl_cipher_list']['description'], + 'type' => 'text', + 'value' => !empty($result['ssl_cipher_list']) ? $result['ssl_cipher_list'] : \Froxlor\Settings::Get('system.ssl_cipher_list') + ), + 'tlsv13_cipher_list' => array( + 'visible' => (($ssl_ipsandports != '' ? true : false) && $userinfo['change_serversettings'] == '1' && \Froxlor\Settings::Get('system.webserver') == "apache2" && \Froxlor\Settings::Get('system.apache24') == 1 ? true : false), + 'label' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'], + 'desc' => $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'], + 'type' => 'text', + 'value' => !empty($result['tlsv13_cipher_list']) ? $result['tlsv13_cipher_list'] : \Froxlor\Settings::Get('system.tlsv13_cipher_list') + ), + 'ssl_specialsettings' => array( + 'visible' => ($userinfo['change_serversettings'] == '1' ? true : false), + 'style' => 'align-top', + 'label' => $lng['admin']['ownsslvhostsettings'], + 'desc' => $lng['serversettings']['default_vhostconf']['description'], + 'type' => 'textarea', + 'cols' => 60, + 'rows' => 12, + 'value' => $result['ssl_specialsettings'] + ), + 'include_specialsettings' => array( + 'label' => $lng['admin']['include_ownvhostsettings'], + 'type' => 'checkbox', + 'values' => array( + array( + 'label' => $lng['panel']['yes'], + 'value' => '1' + ) + ), + 'value' => array( + $result['include_specialsettings'] + ) ), 'hsts_maxage' => array( 'visible' => ($ssl_ipsandports != '' ? true : false), diff --git a/lng/english.lng.php b/lng/english.lng.php index beb26031..66e85231 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -2078,3 +2078,4 @@ $lng['serversettings']['includedefault_sslvhostconf'] = 'Include non-SSL vHost-s $lng['admin']['ownsslvhostsettings'] = 'Own SSL vHost-settings'; $lng['admin']['ipsandports']['ssl_default_vhostconf_domain'] = 'Default SSL vHost-settings for every domain container'; $lng['customer']['total_diskspace'] = 'Total diskspace (MiB)'; +$lng['admin']['domain_override_tls'] = 'Override system TLS settings'; diff --git a/lng/german.lng.php b/lng/german.lng.php index dde344d5..286a1a9b 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1725,3 +1725,4 @@ $lng['serversettings']['includedefault_sslvhostconf'] = 'Nicht-SSL vHost-Einstel $lng['admin']['ownsslvhostsettings'] = 'Eigene SSL vHost-Einstellungen'; $lng['admin']['ipsandports']['ssl_default_vhostconf_domain'] = 'Standard SSL vHost-Einstellungen für jeden Domain-Container'; $lng['customer']['total_diskspace'] = 'Gesamtspeicherplatz (MiB)'; +$lng['admin']['domain_override_tls'] = 'Überschreibe System TLS Einstellungen'; diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index ead35c02..4efe7798 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -26,11 +26,17 @@ class DomainsTest extends TestCase $customer_userdata = json_decode($json_result, true)['data']; $data = [ 'domain' => 'test.local', - 'customerid' => $customer_userdata['customerid'] + 'customerid' => $customer_userdata['customerid'], + 'override_tls' => 1, + 'ssl_protocols' => array( + 'TLSv1.2', + 'TLSv1.3' + ) ]; $json_result = Domains::getLocal($admin_userdata, $data)->add(); $result = json_decode($json_result, true)['data']; $this->assertEquals($customer_userdata['documentroot'] . 'test.local/', $result['documentroot']); + $this->assertTrue(in_array('TLSv1.3', explode(",", $result['ssl_protocols']))); } /** @@ -153,11 +159,13 @@ class DomainsTest extends TestCase global $admin_userdata; $data = [ 'domainname' => 'test.local', - 'email_only' => 1 + 'email_only' => 1, + 'override_tls' => 0 ]; $json_result = Domains::getLocal($admin_userdata, $data)->update(); $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['email_only']); + $this->assertFalse(in_array('TLSv1.3', explode(",", $result['ssl_protocols']))); } /**