add HSTS for domains (admin-side) and froxlor-vhost; fixes #1660

Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann (d00p)
2016-10-07 11:01:45 +02:00
parent 074d85b40f
commit 4a3e02c1f0
13 changed files with 534 additions and 394 deletions

View File

@@ -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'
),
)
)
)

View File

@@ -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`;

View File

@@ -3486,3 +3486,18 @@ if (isDatabaseVersion('201609200')) {
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');
}

View File

@@ -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;
}
}

View File

@@ -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',

View File

@@ -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',

View File

@@ -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
*/

View File

@@ -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 = '';

View File

@@ -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'] = '<strong class="red">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!!!</strong>';
$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<br>The value <i>0</i> will disable HSTS for the domain. Most user set a value of <i>31536000</i> (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 <a href="https://hstspreload.appspot.com/" target="_blank">HSTS preload list</a>';
$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.<br>Sending the preload directive from your site can have PERMANENT CONSEQUENCES and prevent users from accessing your site and any of its subdomains.<br>Please read the details at <a href="hstspreload.appspot.com/#removal" target="_blank">hstspreload.appspot.com/#removal</a> before sending the header with "preload".';

View File

@@ -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'] = '<strong class="red">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!!!</strong>';
$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<br>Der Wert <i>0</i> deaktiviert HSTS für diese Domain. Meist wird der Wert <i>31536000</i> 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 <a href="https://hstspreload.appspot.com/" target="_blank">HSTS preload Liste</a> 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.<br>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.<br>Beachte Details unter <a href="hstspreload.appspot.com/#removal" target="_blank">hstspreload.appspot.com/#removal</a> bevor ein Header mit "preload" gesendet wird.';

View File

@@ -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 .= ' <IfModule mod_headers.c>' . "\n";
$vhost_content .= ' Header always set Strict-Transport-Security "max-age=' . $domain['hsts'];
if ($domain['hsts_sub'] == 1) {

View File

@@ -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) {

View File

@@ -1,4 +1,7 @@
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
<?php
if (! defined('MASTER_CRONJOB'))
die('You cannot access this file directly!');
/**
* This file is part of the Froxlor project.
@@ -17,20 +20,32 @@
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,23 +54,22 @@ 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) {
@@ -64,17 +78,12 @@ class nginx extends HttpConfigBase {
}
}
/**
* 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'));
@@ -88,7 +97,12 @@ class nginx extends HttpConfigBase {
$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);
@@ -101,16 +115,14 @@ class nginx extends HttpConfigBase {
}
}
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
");
@@ -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
@@ -217,14 +229,11 @@ class nginx extends HttpConfigBase {
}
if ($row_ipsandports['specialsettings'] != '') {
$this->nginx_data[$vhost_filename].= $this->processSpecialConfigTemplate(
$row_ipsandports['specialsettings'],
array('domain'=> Settings::Get('system.hostname'),
$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";
'documentroot' => $mypath
), $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
}
/**
@@ -258,7 +267,7 @@ class nginx extends HttpConfigBase {
'openbasedir' => 0,
'email' => Settings::Get('panel.adminmail'),
'loginname' => 'froxlor.panel',
'documentroot' => $mypath,
'documentroot' => $mypath
);
$php = new phpinterface($domain);
@@ -284,12 +293,11 @@ class nginx extends HttpConfigBase {
$this->_createStandardErrorHandler();
}
/**
* create vhosts
*/
protected function createNginxHosts() {
protected function createNginxHosts()
{
$domains = WebserverBase::getVhostsToCreate();
foreach ($domains as $domain) {
@@ -303,10 +311,7 @@ class nginx extends HttpConfigBase {
$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
@@ -323,18 +328,11 @@ 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
@@ -350,12 +348,9 @@ class nginx extends HttpConfigBase {
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 '';
}
@@ -371,9 +366,7 @@ class nginx extends HttpConfigBase {
$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;";
@@ -385,7 +378,9 @@ class nginx extends HttpConfigBase {
$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,12 +406,7 @@ 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";
@@ -426,23 +416,21 @@ class nginx extends HttpConfigBase {
$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`
$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'];
@@ -455,15 +443,11 @@ 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'
) {
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";
}
@@ -489,13 +473,7 @@ class nginx extends HttpConfigBase {
$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,14 +490,21 @@ 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
@@ -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'] == '') {
@@ -628,7 +607,7 @@ class nginx extends HttpConfigBase {
}
}
if (isset($domain_or_ip['hsts']) && $domain_or_ip['hsts'] > 0) {
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';
@@ -644,15 +623,17 @@ class nginx extends HttpConfigBase {
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);
@@ -739,9 +720,7 @@ class nginx extends HttpConfigBase {
* 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']);
@@ -756,7 +735,6 @@ class nginx extends HttpConfigBase {
$path_options .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ';' . "\n";
$path_options .= "\t" . '}' . "\n";
}
}
// now the rest of the htpasswds
@@ -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;
@@ -846,8 +826,8 @@ 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";
@@ -866,18 +846,15 @@ class nginx extends HttpConfigBase {
$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') != ''
) {
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;
@@ -888,13 +865,10 @@ class nginx extends HttpConfigBase {
$webroot_text .= "\n\t" . 'location / {' . "\n";
if ($domain['phpenabled'] == '1')
{
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
{
} else {
$webroot_text .= "\t" . 'index index.html index.htm;' . "\n";
}
@@ -904,8 +878,7 @@ class nginx extends HttpConfigBase {
}
$webroot_text .= "\t" . '}' . "\n\n";
if ($domain['phpenabled'] == '1')
{
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
@@ -955,8 +928,8 @@ class nginx extends HttpConfigBase {
return $stats_text;
}
protected function getLogFiles($domain) {
protected function getLogFiles($domain)
{
$logfiles_text = '';
$speciallogfile = '';
@@ -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'];
@@ -1067,8 +1043,8 @@ class nginx extends HttpConfigBase {
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'));
@@ -1111,7 +1087,6 @@ class nginx extends HttpConfigBase {
fwrite($vhosts_file_handler, $vhosts_file);
fclose($vhosts_file_handler);
}
}
}
@@ -1138,6 +1113,4 @@ class nginx extends HttpConfigBase {
}
}
}
}