diff --git a/actions/admin/settings/131.ssl.php b/actions/admin/settings/131.ssl.php
index e64ea768..90c7a928 100644
--- a/actions/admin/settings/131.ssl.php
+++ b/actions/admin/settings/131.ssl.php
@@ -108,6 +108,32 @@ return array(
'default' => 'Germany',
'save_method' => 'storeSettingField',
),
+ 'system_letsencryptchallengepath' => array(
+ 'label' => $lng['serversettings']['letsencryptchallengepath'],
+ 'settinggroup' => 'system',
+ 'varname' => 'letsencryptchallengepath',
+ 'type' => 'string',
+ 'string_emptyallowed' => false,
+ 'default' => FROXLOR_INSTALL_DIR,
+ 'save_method' => 'storeSettingField',
+ ),
+ 'system_letsencryptkeysize' => array(
+ 'label' => $lng['serversettings']['letsencryptkeysize'],
+ 'settinggroup' => 'system',
+ 'varname' => 'letsencryptkeysize',
+ 'type' => 'int',
+ 'int_min' => 2048,
+ 'default' => 4096,
+ 'save_method' => 'storeSettingField',
+ ),
+ 'system_letsencryptreuseold' => array(
+ 'label' => $lng['serversettings']['letsencryptreuseold'],
+ 'settinggroup' => 'system',
+ 'varname' => 'letsencryptreuseold',
+ 'type' => 'bool',
+ 'default' => false,
+ 'save_method' => 'storeSettingField',
+ ),
)
)
)
diff --git a/install/froxlor.sql b/install/froxlor.sql
index febce3ab..30e26fe3 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -251,6 +251,9 @@ CREATE TABLE `panel_domains` (
`mod_fcgid_maxrequests` int(4) default '-1',
`ismainbutsubto` int(11) unsigned NOT NULL default '0',
`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',
PRIMARY KEY (`id`),
KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`),
@@ -518,6 +521,9 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('system', 'letsencryptca', 'testing'),
('system', 'letsencryptcountrycode', 'DE'),
('system', 'letsencryptstate', 'Germany'),
+ ('system', 'letsencryptchallengepath', '/var/www/froxlor'),
+ ('system', 'letsencryptkeysize', '4096'),
+ ('system', 'letsencryptreuseold', 0),
('panel', 'decimal_places', '4'),
('panel', 'adminmail', 'admin@SERVERNAME'),
('panel', 'phpmyadmin_url', ''),
@@ -548,7 +554,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('panel', 'password_numeric', '0'),
('panel', 'password_special_char_required', '0'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
- ('panel', 'version', '0.9.35-dev4');
+ ('panel', 'version', '0.9.35-dev5');
DROP TABLE IF EXISTS `panel_tasks`;
@@ -832,6 +838,7 @@ CREATE TABLE IF NOT EXISTS `domain_ssl_settings` (
`ssl_key_file` mediumtext NOT NULL,
`ssl_ca_file` mediumtext,
`ssl_cert_chainfile` mediumtext,
+ `ssl_csr_file` mediumtext,
`expirationdate` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;
diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php
index ef50aa2a..342c6c1c 100644
--- a/install/lib/class.FroxlorInstall.php
+++ b/install/lib/class.FroxlorInstall.php
@@ -472,6 +472,8 @@ class FroxlorInstall {
$this->_updateSetting($upd_stmt, '/etc/nginx/nginx.pem', 'system', 'ssl_cert_file');
$this->_updateSetting($upd_stmt, '/var/run/nginx/', 'phpfpm', 'fastcgi_ipcdir');
}
+
+ $this->_updateSetting($upd_stmt, dirname(dirname(dirname(__FILE__))), 'system', 'letsencryptchallengepath');
// insert the lastcronrun to be the installation date
$this->_updateSetting($upd_stmt, time(), 'system', 'lastcronrun');
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 e274457f..351510b0 100644
--- a/install/updates/froxlor/0.9/update_0.9.inc.php
+++ b/install/updates/froxlor/0.9/update_0.9.inc.php
@@ -3079,3 +3079,19 @@ if (isFroxlorVersion('0.9.35-dev3')) {
updateToVersion('0.9.35-dev4');
}
+
+
+if (isFroxlorVersion('0.9.35-dev4')) {
+
+ showUpdateStep("Adding more Let's Encrypt settings");
+ Settings::AddNew("system.letsencryptchallengepath", FROXLOR_INSTALL_DIR);
+ Settings::AddNew("system.letsencryptkeysize", '4096');
+ Settings::AddNew("system.letsencryptreuseold", 0);
+ Database::query("ALTER TABLE `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` ADD `ssl_csr_file` MEDIUMTEXT AFTER `ssl_cert_chainfile`;");
+ Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` ADD `hsts` VARCHAR(10) NOT NULL DEFAULT '0' AFTER `letsencrypt`");
+ Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` ADD `hsts_sub` TINYINT(1) NOT NULL DEFAULT '0' AFTER `hsts`");
+ Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` ADD `hsts_preload` TINYINT(1) NOT NULL DEFAULT '1' AFTER `hsts_sub`");
+ lastStepStatus(0);
+
+ updateToVersion('0.9.35-dev5');
+}
diff --git a/lib/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php
index f1134a19..0f12c98e 100644
--- a/lib/classes/ssl/class.lescript.php
+++ b/lib/classes/ssl/class.lescript.php
@@ -75,7 +75,7 @@ class lescript
}
}
- public function signDomains(array $domains, $domainkey = null)
+ public function signDomains(array $domains, $domainkey = null, $csr = null)
{
if (!$this->accountKey) {
@@ -117,7 +117,7 @@ class lescript
// 2. saving authentication token for web verification
// ---------------------------------------------------
- $directory = FROXLOR_INSTALL_DIR.'/.well-known/acme-challenge';
+ $directory = Settings::Get('system.letsencryptchallengepath').'/.well-known/acme-challenge';
$tokenPath = $directory.'/'.$challenge['token'];
if(!file_exists($directory) && !@mkdir($directory, 0755, true)) {
@@ -190,7 +190,7 @@ class lescript
// ----------------------
// generate private key for domain if not exist
- if(empty($domainkey)) {
+ if(empty($domainkey) || Settings::Get('system.letsencryptreuseold') == 0) {
$keys = $this->generateKey();
$domainkey = $keys['private'];
}
@@ -199,11 +199,15 @@ class lescript
$privateDomainKey = openssl_pkey_get_private($domainkey);
$this->client->getLastLinks();
+
+ if (empty($csrfile) || Settings::Get('system.letsencryptreuseold') == 0) {
+ $csr = $this->generateCSR($privateDomainKey, $domains);
+ }
// request certificates creation
$result = $this->signedRequest(
"/acme/new-cert",
- array('resource' => 'new-cert', 'csr' => $this->generateCSR($privateDomainKey, $domains))
+ array('resource' => 'new-cert', 'csr' => $csr)
);
if ($this->client->getLastCode() !== 201) {
throw new \RuntimeException("Invalid response code: ".$this->client->getLastCode().", ".json_encode($result));
@@ -249,7 +253,7 @@ class lescript
$chain = implode("\n", $certificates);
$this->log("Done, returning new certificates and key");
- return array('fullchain' => $fullchain, 'crt' => $crt, 'chain' => $chain, 'key' => $domainkey);
+ return array('fullchain' => $fullchain, 'crt' => $crt, 'chain' => $chain, 'key' => $domainkey, 'csr' => $csr);
}
private function parsePemFromBody($body)
@@ -281,7 +285,7 @@ class lescript
'HOME = .
RANDFILE = $ENV::HOME/.rnd
[ req ]
-default_bits = 4096
+default_bits = ' . Settings::Get('system.letsencryptkeysize') . '
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
req_extensions = v3_req
@@ -320,7 +324,7 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
{
$res = openssl_pkey_new(array(
"private_key_type" => OPENSSL_KEYTYPE_RSA,
- "private_key_bits" => 4096,
+ "private_key_bits" => Settings::Get('system.letsencryptkeysize'),
));
if(!openssl_pkey_export($res, $privateKey)) {
diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml
index 77e0c038..f0bd4723 100644
--- a/lib/configfiles/gentoo.xml
+++ b/lib/configfiles/gentoo.xml
@@ -66,8 +66,8 @@
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Order allow,deny
Allow from all
@@ -96,8 +96,8 @@ Alias "/.well-known/acme-challenge" "{{const.FROXLOR_INSTALL_DIR}}/.well-known/a
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Require all granted
]]>
@@ -126,6 +126,7 @@ server.modules = (
"mod_auth",
"mod_fastcgi",
"mod_cgi",
+ "mod_setenv",
"mod_accesslog"
)
@@ -168,7 +169,7 @@ fastcgi.server = (
)
)
-alias.url += ("/.well-known/acme-challenge/" => "{{const.FROXLOR_INSTALL_DIR}}/.well-known/acme-challenge/")
+alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/")
]]>
@@ -265,7 +266,7 @@ fastcgi_param REDIRECT_STATUS 200;
+
@@ -69,8 +70,8 @@
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Require all granted
]]>
@@ -89,6 +90,7 @@ server.modules = (
"mod_compress",
"mod_redirect",
"mod_rewrite",
+ "mod_setenv",
)
server.document-root = "/var/www"
@@ -107,7 +109,7 @@ static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
compress.cache-dir = "/var/cache/lighttpd/compress/"
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )
-alias.url += ("/.well-known/acme-challenge/" => "{{const.FROXLOR_INSTALL_DIR}}/.well-known/acme-challenge/")
+alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/")
# default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
@@ -286,7 +288,7 @@ fastcgi_param REDIRECT_STATUS 200;
+
@@ -67,8 +68,8 @@
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Order allow,deny
Allow from all
@@ -97,6 +98,7 @@ server.modules = (
"mod_auth",
"mod_fastcgi",
"mod_cgi",
+ "mod_setenv",
"mod_accesslog"
)
@@ -136,7 +138,7 @@ fastcgi.server = (
)
)
-alias.url += ("/.well-known/acme-challenge/" => "{{const.FROXLOR_INSTALL_DIR}}/.well-known/acme-challenge/")
+alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/")
#### external configuration files
## mimetype mapping
@@ -245,7 +247,7 @@ fastcgi_param REDIRECT_STATUS 200;
+
@@ -49,8 +50,8 @@
//service[@type='http']/general/commands
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Require all granted
]]>
diff --git a/lib/configfiles/trusty.xml b/lib/configfiles/trusty.xml
index 330b2699..d5640c40 100644
--- a/lib/configfiles/trusty.xml
+++ b/lib/configfiles/trusty.xml
@@ -41,6 +41,7 @@
+
@@ -67,8 +68,8 @@
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Order Deny,Allow
Deny from All
@@ -97,8 +98,8 @@ Alias "/.well-known/acme-challenge" "{{const.FROXLOR_INSTALL_DIR}}/.well-known/a
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Require all granted
]]>
@@ -126,6 +127,7 @@ server.modules = (
"mod_auth",
"mod_fastcgi",
"mod_cgi",
+ "mod_setenv",
"mod_accesslog"
)
@@ -165,7 +167,7 @@ fastcgi.server = (
)
)
-alias.url += ("/.well-known/acme-challenge/" => "{{const.FROXLOR_INSTALL_DIR}}/.well-known/acme-challenge/")
+alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/")
#### external configuration files
## mimetype mapping
@@ -274,7 +276,7 @@ fastcgi_param REDIRECT_STATUS 200;
+
@@ -67,8 +68,8 @@
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Order Deny,Allow
Deny from All
@@ -97,8 +98,8 @@ Alias "/.well-known/acme-challenge" "{{const.FROXLOR_INSTALL_DIR}}/.well-known/a
+Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge"
+
Require all granted
]]>
@@ -116,6 +117,7 @@ server.modules = (
"mod_alias",
"mod_compress",
"mod_redirect",
+ "mod_setenv",
"mod_rewrite",
)
@@ -135,7 +137,7 @@ static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
compress.cache-dir = "/var/cache/lighttpd/compress/"
compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" )
-alias.url += ("/.well-known/acme-challenge/" => "{{const.FROXLOR_INSTALL_DIR}}/.well-known/acme-challenge/")
+alias.url += ("/.well-known/acme-challenge/" => "{{settings.system.letsencryptchallengepath}}/.well-known/acme-challenge/")
# default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
@@ -314,7 +316,7 @@ fastcgi_param REDIRECT_STATUS 200;
ATTENTION:Let's Encrypt is still in beta";
$lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt state";
$lng['serversettings']['letsencryptstate']['description'] = "State used to generate Let's Encrypt certificates.
ATTENTION:Let's Encrypt is still in beta";
+$lng['serversettings']['letsencryptchallengepath']['title'] = "Path for Let's Encrypt challenges";
+$lng['serversettings']['letsencryptchallengepath']['description'] = "Directory where the Let's Encrypt challenges should be offered from via a global alias.
ATTENTION:Let's Encrypt is still in beta";
+$lng['serversettings']['letsencryptkeysize']['title'] = "Key size for new Let's Encrypt certificates";
+$lng['serversettings']['letsencryptkeysize']['description'] = "Size of the key in Bits for new Let's Encrypt certificates.
ATTENTION:Let's Encrypt is still in beta";
+$lng['serversettings']['letsencryptreuseold']['title'] = "Re-use Let's Encrypt key / CSR";
+$lng['serversettings']['letsencryptreuseold']['description'] = "If activated, the same key and CSR will be used for every renew, otherwise a new key / CSR will be generated every time.
ATTENTION:Let's Encrypt is still in beta";
$lng['domains']['ssl_redirect_temporarilydisabled'] = "
The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
// Autoupdate
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 91e84a23..70166614 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -1584,20 +1584,26 @@ $lng['admin']['mod_fcgid_umask']['title'] = 'Umask (Standard: 022)';
// Added for let's encrypt
$lng['admin']['letsencrypt']['title'] = 'Benutze Let\'s Encrypt';
-$lng['admin']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von Let\'s Encrypt. Das Zertifikat wird automatisch erstellt und verlänger.
ACHTUNG:Wenn Wildcards aktiviert sind, wird diese Option automatisch deaktiviert. Dieses Feature befindet sich noch im Test.';
+$lng['admin']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von Let\'s Encrypt. Das Zertifikat wird automatisch erstellt und verlängert.
ACHTUNG:Wenn Wildcards aktiviert sind, wird diese Option automatisch deaktiviert. Dieses Feature befindet sich noch im Test.';
$lng['customer']['letsencrypt']['title'] = 'Benutze Let\'s Encrypt';
-$lng['customer']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von Let\'s Encrypt. Das Zertifikat wird automatisch erstellt und verlängert.
ACHTUNG:Dieses Feature befindet sich noch im Test.';
-$lng['error']['sslredirectonlypossiblewithsslipport'] = 'Die Nutzung von Let\'s Encrypt ist nur möglich, wenn die Domain mindestens eine IP/Port - Kombination mit aktiviertem SSL zugewiesen hat.';
+$lng['customer']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von Let\'s Encrypt. Das Zertifikat wird automatisch erstellt und verlängert.
ACHTUNG:Dieses Feature befindet sich noch im Test.';
+$lng['error']['sslredirectonlypossiblewithsslipport'] = 'Die Nutzung von Let\'s Encrypt ist nur möglich, wenn die Domain mindestens eine IP/Port - Kombination mit aktiviertem SSL zugewiesen hat.';
$lng['error']['nowildcardwithletsencrypt'] = 'Let\'s Encrypt kann (noch) nicht mit Wildcard-Domains umgehen. Bitte den ServerAlias auf WWW setzen oder deaktivieren';
$lng['panel']['letsencrypt'] = 'Benutzt Let\'s encrypt';
$lng['crondesc']['cron_letsencrypt'] = 'aktualisiert Let\'s Encrypt Zertifikate';
$lng['serversettings']['letsencryptca']['title'] = "Let's Encrypt Umgebung";
-$lng['serversettings']['letsencryptca']['description'] = "Let's Encrypt - Umgebung, welche genutzt wird um Zertifikate zu bestellen.
ATTENTION:Let's Encrypt befindet sich noch im Test";
-$lng['serversettings']['letsencryptcountrycode']['title'] = "Let's Encrypt Ländercode";
-$lng['serversettings']['letsencryptcountrycode']['description'] = "2 - stelliger Ländercode, welcher benutzt wird um Let's Encrypt - Zertifikate zu bestellen.
ATTENTION:Let's Encrypt befindet sich noch im Test";
+$lng['serversettings']['letsencryptca']['description'] = "Let's Encrypt - Umgebung, welche genutzt wird um Zertifikate zu bestellen.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
+$lng['serversettings']['letsencryptcountrycode']['title'] = "Let's Encrypt Ländercode";
+$lng['serversettings']['letsencryptcountrycode']['description'] = "2 - stelliger Ländercode, welcher benutzt wird um Let's Encrypt - Zertifikate zu bestellen.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
$lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt Bundesland";
-$lng['serversettings']['letsencryptstate']['description'] = "Bundesland, welches benutzt wird um Let's Encrypt - Zertifikate zu bestellen.
ATTENTION:Let's Encrypt befindet sich noch im Test";
-$lng['domains']['ssl_redirect_temporarilydisabled'] = "
Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
+$lng['serversettings']['letsencryptstate']['description'] = "Bundesland, welches benutzt wird um Let's Encrypt - Zertifikate zu bestellen.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
+$lng['serversettings']['letsencryptchallengepath']['title'] = "Verzeichnis für Let's Encrypt challenges";
+$lng['serversettings']['letsencryptchallengepath']['description'] = "Let's Encrypt challenges werden aus diesem Verzeichnis über einen globalen Alias ausgeliefert.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
+$lng['serversettings']['letsencryptkeysize']['title'] = "Schlüsselgröße für neue Let's Encrypt Zertifikate";
+$lng['serversettings']['letsencryptkeysize']['description'] = "Größe des Schlüssels in Bit für neue Let's Encrypt Zertifikate.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
+$lng['serversettings']['letsencryptreuseold']['title'] = "Let's Encrypt Schlüssel / CSR wiederverwenden";
+$lng['serversettings']['letsencryptreuseold']['description'] = "Wenn dies aktiviet ist, werden der alte Schlüssel und CSR bei jeder Verlängerung verwendet, andernfalls wird ein neues Paar generiert.
ACHTUNG:Let's Encrypt befindet sich noch im Test";
+$lng['domains']['ssl_redirect_temporarilydisabled'] = "
Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
// Added for Termination-date
$lng['domains']['termination_date'] = 'Kündigungsdatum';
diff --git a/scripts/jobs/cron_letsencrypt.php b/scripts/jobs/cron_letsencrypt.php
index 7ac89a98..dd3f8ffe 100644
--- a/scripts/jobs/cron_letsencrypt.php
+++ b/scripts/jobs/cron_letsencrypt.php
@@ -21,14 +21,14 @@
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificates");
$certificates_stmt = Database::query("
- SELECT domssl.`id`, domssl.`domainid`, domssl.expirationdate, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`,
+ SELECT domssl.`id`, domssl.`domainid`, domssl.expirationdate, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, domssl.`ssl_csr_file`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`,
dom.`documentroot`, dom.`id` as 'domainid', dom.`ssl_redirect`, cust.`leprivatekey`, cust.`lepublickey`, cust.customerid
FROM `".TABLE_PANEL_CUSTOMERS."` as cust, `".TABLE_PANEL_DOMAINS."` dom LEFT JOIN `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` domssl ON (dom.id = domssl.domainid)
WHERE dom.customerid = cust.customerid AND dom.letsencrypt = 1 AND (domssl.expirationdate < DATE_ADD(NOW(), INTERVAL 30 DAY) OR domssl.expirationdate IS NULL)
");
$updcert_stmt = Database::prepare("
- REPLACE INTO `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` SET `id` = :id, `domainid` = :domainid, `ssl_cert_file` = :crt, `ssl_key_file` = :key, `ssl_ca_file` = :ca, `ssl_cert_chainfile` = :fullchain, expirationdate = :expirationdate
+ REPLACE INTO `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` SET `id` = :id, `domainid` = :domainid, `ssl_cert_file` = :crt, `ssl_key_file` = :key, `ssl_ca_file` = :ca, `ssl_cert_chainfile` = :fullchain, `ssl_csr_file` = :csr, expirationdate = :expirationdate
");
$upddom_stmt = Database::prepare("
@@ -71,7 +71,7 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
$le->initAccount($certrow);
// Request the new certificate (old key may be used)
- $return = $le->signDomains($domains, $certrow['ssl_key_file']);
+ $return = $le->signDomains($domains, $certrow['ssl_key_file'], $certrow['ssl_csr_file']);
// We are interessted in the expirationdate
$newcert = openssl_x509_parse($return['crt']);
@@ -84,6 +84,7 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
'key' => $return['key'],
'ca' => $return['chain'],
'fullchain' => $return['fullchain'],
+ 'csr' => $return['csr'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
)
);
diff --git a/scripts/jobs/cron_tasks.inc.http.10.apache.php b/scripts/jobs/cron_tasks.inc.http.10.apache.php
index 4891f5b8..ca6fe141 100644
--- a/scripts/jobs/cron_tasks.inc.http.10.apache.php
+++ b/scripts/jobs/cron_tasks.inc.http.10.apache.php
@@ -811,6 +811,19 @@ class apache extends HttpConfigBase {
if ($domain['ssl_cert_chainfile'] != '') {
$vhost_content .= ' SSLCertificateChainFile ' . makeCorrectFile($domain['ssl_cert_chainfile']) . "\n";
}
+
+ if ($domain['hsts'] > 0) {
+ $vhost_content .= ' ' . "\n";
+ $vhost_content .= ' Header always set Strict-Transport-Security "max-age=' . $domain['hsts'];
+ if ($domain['hsts_sub'] == 1) {
+ $vhost_content .= '; includeSubdomains';
+ }
+ if ($domain['hsts_preload'] == 1) {
+ $vhost_content .= '; preload';
+ }
+ $vhost_content .= '"' . "\n";
+ $vhost_content .= ' ' . "\n";
+ }
}
else
{
diff --git a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php
index 0b3ec71d..121f1c26 100644
--- a/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php
+++ b/scripts/jobs/cron_tasks.inc.http.20.lighttpd.php
@@ -518,6 +518,18 @@ class lighttpd extends HttpConfigBase {
if ($domain['ssl_ca_file'] != '') {
$ssl_settings.= 'ssl.ca-file = "' . makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n";
}
+
+ if ($domain['hsts'] > 0) {
+
+ $vhost_content .= '$HTTP["scheme"] == "https" { setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=' . $domain['hsts'];
+ if ($domain['hsts_sub'] == 1) {
+ $vhost_content .= '; includeSubdomains';
+ }
+ if ($domain['hsts_preload'] == 1) {
+ $vhost_content .= '; preload';
+ }
+ $vhost_content .= '") }' . "\n";
+ }
}
}
return $ssl_settings;
diff --git a/scripts/jobs/cron_tasks.inc.http.30.nginx.php b/scripts/jobs/cron_tasks.inc.http.30.nginx.php
index 82f77b61..4bff60a1 100644
--- a/scripts/jobs/cron_tasks.inc.http.30.nginx.php
+++ b/scripts/jobs/cron_tasks.inc.http.30.nginx.php
@@ -591,6 +591,18 @@ class nginx extends HttpConfigBase {
$sslsettings.= "\t" . 'ssl_client_certificate ' . makeCorrectFile($domain_or_ip['ssl_ca_file']) . ';' . "\n";
}
}
+
+ if ($domain['hsts'] > 0) {
+
+ $vhost_content .= 'add_header Strict-Transport-Security "max-age=' . $domain['hsts'];
+ if ($domain['hsts_sub'] == 1) {
+ $vhost_content .= '; includeSubdomains';
+ }
+ if ($domain['hsts_preload'] == 1) {
+ $vhost_content .= '; preload';
+ }
+ $vhost_content .= '";' . "\n";
+ }
}
}