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/actions/admin/settings/122.froxlorvhost.php b/actions/admin/settings/122.froxlorvhost.php index e92fa582..6175bb73 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( @@ -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/130.webserver.php b/actions/admin/settings/130.webserver.php index b6cfc9a8..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', @@ -260,11 +271,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 +281,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/admin_domains.php b/admin_domains.php index 6517e2f4..bb4fe9a3 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 @@ -393,6 +395,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 +405,9 @@ if ($page == 'domains' || $page == 'overview') { '0', '' )); + if ($termination_date == '0000-00-00') { + $termination_date = null; + } if ($userinfo['change_serversettings'] == '1') { @@ -447,6 +455,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) { @@ -487,7 +496,9 @@ if ($page == 'domains' || $page == 'overview') { } } else { + $phpenabled = '1'; $openbasedir = '1'; + if ((int) Settings::Get('phpfpm.enabled') == 1) { $phpsettingid = Settings::Get('phpfpm.defaultini'); } else { @@ -578,12 +589,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; @@ -591,6 +613,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 @@ -666,6 +693,10 @@ if ($page == 'domains' || $page == 'overview') { if (count($ipandports) == 0) { standard_error('noipportgiven'); } + + if($phpenabled != '1') { + $phpenabled = '0'; + } if ($openbasedir != '1') { $openbasedir = '0'; @@ -746,6 +777,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, @@ -754,7 +786,10 @@ if ($page == 'domains' || $page == 'overview') { 'registration_date' => $registration_date, 'termination_date' => $termination_date, 'issubof' => $issubof, - 'letsencrypt' => $letsencrypt + 'letsencrypt' => $letsencrypt, + 'hsts_maxage' => $hsts_maxage, + 'hsts_sub' => $hsts_sub, + 'hsts_preload' => $hsts_preload ); $security_questions = array( @@ -791,6 +826,7 @@ if ($page == 'domains' || $page == 'overview') { 'email_only' => $email_only, 'subcanemaildomain' => $subcanemaildomain, 'caneditdomain' => $caneditdomain, + 'phpenabled' => $phpenabled, 'openbasedir' => $openbasedir, 'speciallogfile' => $speciallogfile, 'specialsettings' => $specialsettings, @@ -802,7 +838,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(" @@ -824,18 +863,22 @@ if ($page == 'domains' || $page == 'overview') { `email_only` = :email_only, `subcanemaildomain` = :subcanemaildomain, `caneditdomain` = :caneditdomain, + `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `speciallogfile` = :speciallogfile, `specialsettings` = :specialsettings, `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(); @@ -1050,8 +1093,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 ); @@ -1196,7 +1243,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; @@ -1206,12 +1253,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'])) { @@ -1285,6 +1338,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) { @@ -1319,6 +1373,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']; @@ -1361,6 +1416,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']); @@ -1386,12 +1446,18 @@ if ($page == 'domains' || $page == 'overview') { $ssl_ipandports[] = $ssl_ipandport; } } + } 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; @@ -1399,6 +1465,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 @@ -1414,6 +1485,10 @@ if ($page == 'domains' || $page == 'overview') { if (! preg_match('/^https?\:\/\//', $documentroot)) { $documentroot = makeCorrectDir($documentroot); } + + if ($phpenabled != '1') { + $phpenabled = '0'; + } if ($openbasedir != '1') { $openbasedir = '0'; @@ -1523,6 +1598,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, @@ -1536,7 +1612,10 @@ if ($page == 'domains' || $page == 'overview') { 'speciallogverified' => $speciallogverified, 'ipandport' => serialize($ipandports), 'ssl_ipandport' => serialize($ssl_ipandports), - 'letsencrypt' => $letsencrypt + 'letsencrypt' => $letsencrypt, + 'hsts_maxage' => $hsts_maxage, + 'hsts_sub' => $hsts_sub, + 'hsts_preload' => $hsts_preload ); $security_questions = array( @@ -1555,7 +1634,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'] || $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'); } @@ -1584,6 +1663,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') { @@ -1686,6 +1775,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; @@ -1696,6 +1786,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(" @@ -1714,6 +1807,7 @@ if ($page == 'domains' || $page == 'overview') { `zonefile` = :zonefile, `wwwserveralias` = :wwwserveralias, `iswildcarddomain` = :iswildcarddomain, + `phpenabled` = :phpenabled, `openbasedir` = :openbasedir, `speciallogfile` = :speciallogfile, `phpsettingid` = :phpsettingid, @@ -1723,13 +1817,17 @@ 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); $_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; @@ -1748,6 +1846,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/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_domains.php b/customer_domains.php index b78053c8..cc2a637e 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); @@ -506,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) { @@ -527,8 +543,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 @@ -568,7 +583,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'; @@ -634,7 +649,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 +657,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 { @@ -666,7 +686,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 @@ -677,7 +701,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 +717,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 ); @@ -699,11 +729,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'); @@ -730,7 +769,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'])); @@ -763,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/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); 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'])); diff --git a/install/froxlor.sql b/install/froxlor.sql index a91c7023..94a3c5ce 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', @@ -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; @@ -237,6 +238,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', @@ -245,8 +247,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', @@ -254,7 +256,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`), @@ -497,6 +499,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'), @@ -543,6 +546,10 @@ 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_incsub', '0'), + ('system', 'hsts_preload', '0'), + ('system', 'leregistered', '0'), ('panel', 'decimal_places', '4'), ('panel', 'adminmail', 'admin@SERVERNAME'), ('panel', 'phpmyadmin_url', ''), @@ -573,8 +580,9 @@ 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', 'db_version', '201609200'); + ('panel', 'customer_hide_options', ''), + ('panel', 'version', '0.9.38.4'), + ('panel', 'db_version', '201612110'); 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 cc2463b7..8cc422dc 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3477,8 +3477,99 @@ if (isDatabaseVersion('201609120')) { } if (isDatabaseVersion('201609200')) { - showUpdateStep("Adding unique key to ipsandports table"); + + 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'); +} + +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'); +} + +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'); +} + +if (isFroxlorVersion('0.9.38-rc2')) { + + showUpdateStep("Updating from 0.9.38-rc2 to 0.9.38 final", false); + updateToVersion('0.9.38'); +} + +if (isDatabaseVersion('201610070')) { + + showUpdateStep("Add Nginx http2 setting"); + Settings::AddNew("system.nginx_http2_support", 0); + lastStepStatus(0); + + updateToDbVersion('201611180'); +} + +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.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'); +} + +if (isFroxlorVersion('0.9.38.3')) { + + showUpdateStep("Updating from 0.9.38.3 to 0.9.38.4", false); + updateToVersion('0.9.38.4'); +} + +if (isDatabaseVersion('201611180')) { + + 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); + + 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); + + showUpdateStep("Adding system setting for let's-encrypt registration status"); + Settings::AddNew('system.leregistered', '0'); + lastStepStatus(0); + + showUpdateStep("Adding unique key to ipsandports table"); Database::query("ALTER TABLE `" . TABLE_PANEL_IPSANDPORTS . "` ADD UNIQUE KEY `ip_port` (`ip`,`port`)"); lastStepStatus(0); - updateToDbVersion('201609270'); + + updateToDbVersion('201612110'); } 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/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/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php index dc8ec83b..2acd0934 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)) { @@ -188,7 +227,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()); @@ -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 "https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"; + // return ""; } } 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/formfields/admin/domains/formfield.domains_add.php b/lib/formfields/admin/domains/formfield.domains_add.php index c85d6500..97f79ee7 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,11 +127,89 @@ 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_sub' => 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', '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 6837da0a..f3a8ab01 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,11 +150,89 @@ 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_sub' => 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', '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($result['phpenabled']) + ), 'openbasedir' => array( 'label' => 'OpenBasedir', 'type' => 'checkbox', diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index 2f24fcae..238adfff 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('customredirect.enabled') == '1' ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', @@ -66,33 +66,65 @@ 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' ? ($ssl_ipsandports != '' ? true : false) : false, + 'fields' => array( + 'ssl_redirect' => array( + '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' ? true : 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( + '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_sub' => array( + '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( + '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..6ac6d186 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('customredirect.enabled') == '1' ? true : false), 'label' => $lng['domains']['redirectifpathisurl'], 'desc' => $lng['domains']['redirectifpathisurlinfo'], 'type' => 'select', @@ -76,26 +76,6 @@ return array( ), 'value' => array($result['isemaildomain']) ), - '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') - ), - '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), - 'label' => $lng['customer']['letsencrypt']['title'], - 'desc' => $lng['customer']['letsencrypt']['description'], - 'type' => 'checkbox', - 'values' => array( - array ('label' => $lng['panel']['yes'], 'value' => '1') - ), - 'value' => array($result['letsencrypt']) - ), 'openbasedir_path' => array( 'visible' => ($result['openbasedir'] == '1') ? true : false, 'label' => $lng['domain']['openbasedirpath'], @@ -103,7 +83,59 @@ return array( 'select_var' => $openbasedir ) ) - ) + ), + 'section_bssl' => array( + 'title' => $lng['admin']['webserversettings_ssl'], + 'image' => 'icons/domain_edit.png', + 'visible' => Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false, + 'fields' => array( + 'ssl_redirect' => array( + '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' ? true : false, + 'label' => $lng['customer']['letsencrypt']['title'], + 'desc' => $lng['customer']['letsencrypt']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array($result['letsencrypt']) + ), + 'hsts_maxage' => array( + '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_sub' => array( + '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( + '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']) + ), + ) + ), ) ) ); 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); 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()); + } + } } diff --git a/lib/functions/filedir/function.makeCorrectDir.php b/lib/functions/filedir/function.makeCorrectDir.php index f457818b..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 /* $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); 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); } 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'; } } 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/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/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; +} 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 ''; } 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)) { 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/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 8a1d56d3..52765f8d 100644 --- a/lib/version.inc.php +++ b/lib/version.inc.php @@ -16,10 +16,10 @@ */ // Main version variable -$version = '0.9.37'; +$version = '0.9.38.4'; // Database version (YYYYMMDDC where C is a daily counter) -$dbversion = '201609200'; +$dbversion = '201612110'; // Distribution branding-tag (used for Debian etc.) $branding = ''; diff --git a/lng/english.lng.php b/lng/english.lng.php index 6859fd06..45996cd0 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,13 @@ $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".'; + +$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/lng/german.lng.php b/lng/german.lng.php index fc6d9489..490d2651 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 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_letsencrypt.php b/scripts/jobs/cron_letsencrypt.php index 8df9055f..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, @@ -141,8 +143,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 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); } } } diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php index 4d6acb46..174ae623 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 @@ virtualhosts_data[$vhosts_filename]; + $close_vhost = true; + $this->virtualhosts_data[$vhosts_filename] .= '' . "\n"; $mypath = $this->getMyPath($row_ipsandports); @@ -224,7 +227,7 @@ class apache extends HttpConfigBase } } - if (!$is_redirect) { + if (! $is_redirect) { // create fcgid -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')); @@ -274,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, @@ -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', @@ -340,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 @@ -408,7 +421,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 +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"; @@ -443,10 +456,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); @@ -475,7 +497,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') { @@ -602,10 +624,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"; @@ -795,7 +817,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') { @@ -817,7 +839,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 +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"; @@ -836,7 +858,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) { @@ -860,10 +882,10 @@ 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']; // 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.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.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php index 90b70cc0..d1ba5d04 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'] != '') { @@ -210,7 +228,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"; @@ -422,15 +442,21 @@ class lighttpd extends HttpConfigBase $_sslport = ":" . $ssldestport['port']; } - $domain['documentroot'] = 'https://' . $domain['domain'] . $_sslport . '/'; + $domain['documentroot'] = 'https://%1' . $_sslport . '/'; } // avoid using any whitespaces $domain['documentroot'] = trim($domain['documentroot']); if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { + $uri = $domain['documentroot']; + + // Get domain's redirect code + $code = getDomainRedirectCode($domain['id'], '301'); + + $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 { @@ -510,7 +536,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"; @@ -519,16 +547,16 @@ 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']; + $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"; } } } 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 81263633..551d43b9 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 @@ -184,14 +196,21 @@ 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"; - $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"; + + 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 @@ -205,26 +224,25 @@ 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"; } } - 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 +250,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 +265,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 +302,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 +337,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 +384,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,70 +415,67 @@ 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"; + $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 $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 . '/'; + $domain['documentroot'] = 'https://$host' . $_sslport . '/'; } // avoid using any whitespaces $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); + $uri = $domain['documentroot']; + if (substr($uri, - 1) == '/') { + $uri = substr($uri, 0, - 1); } - $vhost_content .= "\t".'return 301 '.$uri.'$request_uri;'."\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 { mkDirWithCorrectOwnership($domain['customerroot'], $domain['documentroot'], $domain['guid'], $domain['guid'], true); @@ -484,18 +485,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 +498,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 +507,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 +533,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 +544,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 +562,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 +580,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 +603,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.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) { + $sslsettings .= 'add_header Strict-Transport-Security "max-age=' . $domain_or_ip['hsts']; + if ($domain_or_ip['hsts_sub'] == 1) { + $sslsettings .= '; includeSubDomains'; + } + if ($domain_or_ip['hsts_preload'] == 1) { + $sslsettings .= '; preload'; + } + $sslsettings .= '";' . "\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 +703,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 +781,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 +801,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 +824,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 +833,7 @@ class nginx extends HttpConfigBase { $returnval[$x]['authname'] = $authname; $returnval[$x]['usrf'] = $htpasswd_filename; - $x++; + $x ++; } } @@ -846,66 +843,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"; + 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"; $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_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 { + $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_customer'] == 1 && $domain['phpenabled_vhost'] == '1') { $webroot_text .= "\tlocation @rewrites {\n"; $webroot_text .= "\t\trewrite ^ /index.php last;\n"; $webroot_text .= "\t}\n\n"; @@ -914,8 +904,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 +917,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 +931,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 +945,8 @@ class nginx extends HttpConfigBase { return $stats_text; } - - protected function getLogFiles($domain) { + protected function getLogFiles($domain) + { $logfiles_text = ''; $speciallogfile = ''; @@ -981,11 +971,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 +983,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 +1019,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 +1037,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 +1047,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 +1076,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 +1087,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 +1099,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 +1130,4 @@ class nginx extends HttpConfigBase { } } } - - } 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']); diff --git a/ssl_certificates.php b/ssl_certificates.php index bfe81553..5a8547d7 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -86,6 +86,13 @@ 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( @@ -96,10 +103,10 @@ 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') { + if (AREA == 'admin' && $cert['domainid'] > 0) { if (! empty($cert['loginname'])) { $adminCustomerLink = ' ("; + } + } + } + $row = htmlentities_array($cert); eval("\$certificates.=\"" . getTemplate("ssl_certificates/certs_cert", true) . "\";"); } else { 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']} 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']}