Temporarily deactivate ssl_redirect if a new Let's Encrypt certificate needs to be generated

Signed-off-by: Florian Aders <eleras@froxlor.org>
This commit is contained in:
Florian Aders
2016-02-16 14:31:07 +01:00
parent f65af0067d
commit ddaadf81d6
9 changed files with 69 additions and 20 deletions

View File

@@ -589,6 +589,11 @@ if ($page == 'domains'
standard_error('nowildcardwithletsencrypt'); standard_error('nowildcardwithletsencrypt');
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2;
}
if (!preg_match('/^https?\:\/\//', $documentroot)) { if (!preg_match('/^https?\:\/\//', $documentroot)) {
if (strstr($documentroot, ":") !== false) { if (strstr($documentroot, ":") !== false) {
standard_error('pathmaynotcontaincolon'); standard_error('pathmaynotcontaincolon');
@@ -1176,8 +1181,8 @@ if ($page == 'domains'
$caneditdomain = isset($_POST['caneditdomain']) ? intval($_POST['caneditdomain']) : 0; $caneditdomain = isset($_POST['caneditdomain']) ? intval($_POST['caneditdomain']) : 0;
$registration_date = trim($_POST['registration_date']); $registration_date = trim($_POST['registration_date']);
$registration_date = validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array('0000-00-00', '0', '')); $registration_date = validate($registration_date, 'registration_date', '/^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$/', '', array('0000-00-00', '0', ''));
$termination_date = trim($_POST['termination_date']); $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', '')); $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', ''));
$isemaildomain = 0; $isemaildomain = 0;
if (isset($_POST['isemaildomain'])) { if (isset($_POST['isemaildomain'])) {
@@ -1376,6 +1381,11 @@ if ($page == 'domains'
standard_error('nowildcardwithletsencrypt'); standard_error('nowildcardwithletsencrypt');
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
$ssl_redirect = 2;
}
if (!preg_match('/^https?\:\/\//', $documentroot)) { if (!preg_match('/^https?\:\/\//', $documentroot)) {
$documentroot = makeCorrectDir($documentroot); $documentroot = makeCorrectDir($documentroot);
} }
@@ -1490,7 +1500,8 @@ if ($page == 'domains'
'mod_fcgid_maxrequests' => $mod_fcgid_maxrequests, 'mod_fcgid_maxrequests' => $mod_fcgid_maxrequests,
'specialsettings' => $specialsettings, 'specialsettings' => $specialsettings,
'registration_date' => $registration_date, 'registration_date' => $registration_date,
'termination_date' => $termination_date, 'issubof' => $issubof, 'termination_date' => $termination_date,
'issubof' => $issubof,
'speciallogfile' => $speciallogfile, 'speciallogfile' => $speciallogfile,
'speciallogverified' => $speciallogverified, 'speciallogverified' => $speciallogverified,
'ipandport' => serialize($ipandports), 'ipandport' => serialize($ipandports),
@@ -1665,7 +1676,7 @@ if ($page == 'domains'
$update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests; $update_data['mod_fcgid_maxrequests'] = $mod_fcgid_maxrequests;
$update_data['specialsettings'] = $specialsettings; $update_data['specialsettings'] = $specialsettings;
$update_data['registration_date'] = $registration_date; $update_data['registration_date'] = $registration_date;
$update_data['termination_date'] = $termination_date; $update_data['termination_date'] = $termination_date;
$update_data['ismainbutsubto'] = $issubof; $update_data['ismainbutsubto'] = $issubof;
$update_data['letsencrypt'] = $letsencrypt; $update_data['letsencrypt'] = $letsencrypt;
$update_data['id'] = $id; $update_data['id'] = $id;
@@ -1693,7 +1704,7 @@ if ($page == 'domains'
`mod_fcgid_maxrequests` = :mod_fcgid_maxrequests, `mod_fcgid_maxrequests` = :mod_fcgid_maxrequests,
`specialsettings` = :specialsettings, `specialsettings` = :specialsettings,
`registration_date` = :registration_date, `registration_date` = :registration_date,
`termination_date` = :termination_date, `termination_date` = :termination_date,
`ismainbutsubto` = :ismainbutsubto, `ismainbutsubto` = :ismainbutsubto,
`letsencrypt` = :letsencrypt `letsencrypt` = :letsencrypt
WHERE `id` = :id WHERE `id` = :id
@@ -1929,6 +1940,11 @@ if ($page == 'domains'
} elseif ($result['wwwserveralias'] == '1') { } elseif ($result['wwwserveralias'] == '1') {
$_value = '1'; $_value = '1';
} }
// Fudge the result for ssl_redirect to hide the Let's Encrypt steps
$result['temporary_ssl_redirect'] = $result['ssl_redirect'];
$result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1);
$serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_wildcard'], '0', $_value, true, true); $serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_wildcard'], '0', $_value, true, true);
$serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_www'], '1', $_value, true, true); $serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_www'], '1', $_value, true, true);
$serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_none'], '2', $_value, true, true); $serveraliasoptions .= makeoption($lng['domains']['serveraliasoption_none'], '2', $_value, true, true);

View File

@@ -340,6 +340,11 @@ if ($page == 'overview') {
} }
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2;
}
if ($path == '') { if ($path == '') {
standard_error('patherror'); standard_error('patherror');
} elseif ($subdomain == '') { } elseif ($subdomain == '') {
@@ -598,6 +603,11 @@ if ($page == 'overview') {
$letsencrypt = '0'; $letsencrypt = '0';
} }
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1 && $result['letsencrypt'] != $letsencrypt) {
$ssl_redirect = 2;
}
if ($path == '') { if ($path == '') {
standard_error('patherror'); standard_error('patherror');
} else { } else {
@@ -715,6 +725,10 @@ if ($page == 'overview') {
$ssl_ipsandports = 'notempty'; $ssl_ipsandports = 'notempty';
} }
// Fudge the result for ssl_redirect to hide the Let's Encrypt steps
$result['temporary_ssl_redirect'] = $result['ssl_redirect'];
$result['ssl_redirect'] = ($result['ssl_redirect'] == 0 ? 0 : 1);
$openbasedir = makeoption($lng['domain']['docroot'], 0, $result['openbasedir_path'], true) . makeoption($lng['domain']['homedir'], 1, $result['openbasedir_path'], true); $openbasedir = makeoption($lng['domain']['docroot'], 0, $result['openbasedir_path'], true) . makeoption($lng['domain']['homedir'], 1, $result['openbasedir_path'], true);
// create serveralias options // create serveralias options

View File

@@ -46,6 +46,7 @@ class lescript
$ca = 'https://acme-staging.api.letsencrypt.org'; $ca = 'https://acme-staging.api.letsencrypt.org';
} }
$this->client = new Client($ca); $this->client = new Client($ca);
$this->log("Using '$ca' to generate certificate");
} }
public function initAccount($certrow) public function initAccount($certrow)
@@ -368,7 +369,7 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
protected function log($message) protected function log($message)
{ {
fwrite($this->debugHandler, 'letsencrypt ' . $message . "\n"); $this->debugHandler->logAction(CRON_ACTION, LOG_INFO, "letsencrypt " . $message);
} }
} }

View File

@@ -124,7 +124,7 @@ return array(
'ssl_redirect' => array( 'ssl_redirect' => array(
'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false),
'label' => $lng['domains']['ssl_redirect']['title'], 'label' => $lng['domains']['ssl_redirect']['title'],
'desc' => $lng['domains']['ssl_redirect']['description'], 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''),
'type' => 'checkbox', 'type' => 'checkbox',
'values' => array( 'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1') array ('label' => $lng['panel']['yes'], 'value' => '1')

View File

@@ -79,7 +79,7 @@ return array(
'ssl_redirect' => array( 'ssl_redirect' => array(
'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false), 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false),
'label' => $lng['domains']['ssl_redirect']['title'], 'label' => $lng['domains']['ssl_redirect']['title'],
'desc' => $lng['domains']['ssl_redirect']['description'], 'desc' => $lng['domains']['ssl_redirect']['description'] . ($result['temporary_ssl_redirect'] > 1 ? $lng['domains']['ssl_redirect_temporarilydisabled'] : ''),
'type' => 'checkbox', 'type' => 'checkbox',
'values' => array( 'values' => array(
array ('label' => $lng['panel']['yes'], 'value' => '1') array ('label' => $lng['panel']['yes'], 'value' => '1')

View File

@@ -1941,6 +1941,7 @@ $lng['serversettings']['letsencryptcountrycode']['title'] = "Let's Encrypt count
$lng['serversettings']['letsencryptcountrycode']['description'] = "2 letter country code used to generate Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt is still in beta</strong>"; $lng['serversettings']['letsencryptcountrycode']['description'] = "2 letter country code used to generate Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt is still in beta</strong>";
$lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt state"; $lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt state";
$lng['serversettings']['letsencryptstate']['description'] = "State used to generate Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt is still in beta</strong>"; $lng['serversettings']['letsencryptstate']['description'] = "State used to generate Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt is still in beta</strong>";
$lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>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 // Autoupdate
$lng['admin']['autoupdate'] = 'Auto-Update'; $lng['admin']['autoupdate'] = 'Auto-Update';
@@ -1959,4 +1960,4 @@ $lng['admin']['server_php'] = 'PHP';
// Added for Termination-date // Added for Termination-date
$lng['domains']['termination_date'] = 'Date of termination'; $lng['domains']['termination_date'] = 'Date of termination';
$lng['domains']['termination_date_overview'] = 'canceled until '; $lng['domains']['termination_date_overview'] = 'canceled until ';

View File

@@ -1596,6 +1596,7 @@ $lng['serversettings']['letsencryptcountrycode']['title'] = "Let's Encrypt L&aum
$lng['serversettings']['letsencryptcountrycode']['description'] = "2 - stelliger L&auml;ndercode, welcher benutzt wird um Let's Encrypt - Zertifikate zu bestellen.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt befindet sich noch im Test</strong>"; $lng['serversettings']['letsencryptcountrycode']['description'] = "2 - stelliger L&auml;ndercode, welcher benutzt wird um Let's Encrypt - Zertifikate zu bestellen.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt befindet sich noch im Test</strong>";
$lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt Bundesland"; $lng['serversettings']['letsencryptstate']['title'] = "Let's Encrypt Bundesland";
$lng['serversettings']['letsencryptstate']['description'] = "Bundesland, welches benutzt wird um Let's Encrypt - Zertifikate zu bestellen.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt befindet sich noch im Test</strong>"; $lng['serversettings']['letsencryptstate']['description'] = "Bundesland, welches benutzt wird um Let's Encrypt - Zertifikate zu bestellen.<br><strong class=\"red\">ATTENTION:</strong>Let's Encrypt befindet sich noch im Test</strong>";
$lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>Die SSL-Umleitung ist, w&auml;hrend ein neues Let's Encrypt - Zertifikat erstellt wird, tempor&auml;r deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
// Added for Termination-date // Added for Termination-date
$lng['domains']['termination_date'] = 'K&uuml;ndigungsdatum'; $lng['domains']['termination_date'] = 'K&uuml;ndigungsdatum';

View File

@@ -18,31 +18,36 @@
* *
*/ */
fwrite($debugHandler, "updating let's encrypt certificates\n"); $cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificates");
$certificates_stmt = Database::query(" $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`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`,
dom.`documentroot`, dom.`id` as 'domainid', cust.`leprivatekey`, cust.`lepublickey`, cust.customerid 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) 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) WHERE dom.customerid = cust.customerid AND dom.letsencrypt = 1 AND (domssl.expirationdate < DATE_ADD(NOW(), INTERVAL 30 DAY) OR domssl.expirationdate IS NULL)
"); ");
$upd_stmt = Database::prepare(" $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, expirationdate = :expirationdate
"); ");
$upddom_stmt = Database::prepare("
UPDATE `".TABLE_PANEL_DOMAINS."` SET `ssl_redirect` = '1' WHERE `id` = :domainid
");
$changedetected = 0; $changedetected = 0;
while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) { while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
// Only renew let's encrypt certificate for domains where a documentroot // Only renew let's encrypt certificate for domains where a documentroot
// already exists // already exists
if (file_exists($certrow['documentroot']) if (file_exists($certrow['documentroot'])
&& is_dir($certrow['documentroot']) && is_dir($certrow['documentroot']
&& $certrow['ssl_redirect'] != 2)
) { ) {
fwrite($debugHandler, "updating " . $certrow['domain'] . "\n"); $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Updating " . $certrow['domain']);
if ($certrow['ssl_cert_file']) { if ($certrow['ssl_cert_file']) {
fwrite($debugHandler, "letsencrypt using old key / SAN for " . $certrow['domain'] . "\n"); $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt using old key / SAN for " . $certrow['domain']);
// Parse the old certificate // Parse the old certificate
$x509data = openssl_x509_parse($certrow['ssl_cert_file']); $x509data = openssl_x509_parse($certrow['ssl_cert_file']);
@@ -53,7 +58,7 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
$domains[] = substr($dnsname, 4); $domains[] = substr($dnsname, 4);
} }
} else { } else {
fwrite($debugHandler, "letsencrypt generating new key / SAN for " . $certrow['domain'] . "\n"); $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt generating new key / SAN for " . $certrow['domain']);
$domains = array($certrow['domain']); $domains = array($certrow['domain']);
// Add www.<domain> for SAN // Add www.<domain> for SAN
if ($certrow['wwwserveralias'] == 1) { if ($certrow['wwwserveralias'] == 1) {
@@ -63,7 +68,7 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
try { try {
// Initialize Lescript with documentroot // Initialize Lescript with documentroot
$le = new lescript($certrow['documentroot'], $debugHandler); $le = new lescript($certrow['documentroot'], $cronlog);
// Initialize Lescript // Initialize Lescript
$le->initAccount($certrow); $le->initAccount($certrow);
@@ -75,7 +80,7 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
$newcert = openssl_x509_parse($return['crt']); $newcert = openssl_x509_parse($return['crt']);
// Store the new data // Store the new data
Database::pexecute($upd_stmt, array( Database::pexecute($updcert_stmt, array(
'id' => $certrow['id'], 'id' => $certrow['id'],
'domainid' => $certrow['domainid'], 'domainid' => $certrow['domainid'],
'crt' => $return['crt'], 'crt' => $return['crt'],
@@ -85,6 +90,13 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t']) 'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
) )
); );
if ($certrow['ssl_redirect'] == 3) {
Database::pexecute($upddom_stmt, array(
'domainid' => $certrow['domainid']
)
);
}
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']); $cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
@@ -92,10 +104,11 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
} catch (Exception $e) { } catch (Exception $e) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ": " . $e->getMessage()); $cronlog->logAction(CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ": " . $e->getMessage());
fwrite($debugHandler, 'letsencrypt exception: ' . $e->getMessage() . "\n");
} }
} elseif ($certrow['ssl_redirect'] == '2') {
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['ssl_redirect'] . " due to an enabled ssl_redirect");
} else { } else {
fwrite($debugHandler, 'letsencrypt skipped because documentroot ' . $certrow['documentroot'] . ' does not exist' . "\n"); $cronlog->logAction(CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['ssl_redirect'] . " due to a missing documentroot");
} }
} }

View File

@@ -106,6 +106,9 @@ while ($row = $result_tasks_stmt->fetch(PDO::FETCH_ASSOC)) {
} }
} }
// Tell the Let's Encrypt cron it's okay to generate the certificate and enable the redirect afterwards
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `ssl_redirect` = '3' WHERE `ssl_redirect` = '2'");
Database::pexecute($upd_stmt);
} }
/** /**