diff --git a/customer_domains.php b/customer_domains.php index 01311329..b32f7b48 100644 --- a/customer_domains.php +++ b/customer_domains.php @@ -36,7 +36,7 @@ if ($page == 'overview') { 'd.domain' => $lng['domains']['domainname'] ); $paging = new paging($userinfo, TABLE_PANEL_DOMAINS, $fields); - $domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d` + $domains_stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` WHERE `d`.`customerid`= :customerid @@ -71,7 +71,7 @@ if ($page == 'overview') { $ssl_stmt = Database::prepare("SELECT * FROM `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` WHERE `domainid` = :domainid"); Database::pexecute($ssl_stmt, array("domainid" => $row['id'])); $ssl_result = $ssl_stmt->fetch(PDO::FETCH_ASSOC); - if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '') { + if (is_array($ssl_result) && isset($ssl_result['ssl_cert_file']) && $ssl_result['ssl_cert_file'] != '' && $row['letsencrypt'] == 0) { // own certificate (ssl_customer_green) $row['domain_hascert'] = 1; } else { @@ -303,7 +303,7 @@ if ($page == 'overview') { $ssl_redirect = '0'; if (isset($_POST['ssl_redirect']) && $_POST['ssl_redirect'] == '1') { - // a ssl-redirect only works of there actually is a + // a ssl-redirect only works if there actually is a // ssl ip/port assigned to the domain if (domainHasSslIpPort($domain_check['id']) == true) { $ssl_redirect = '1'; @@ -313,6 +313,17 @@ if ($page == 'overview') { } } + $letsencrypt = '0'; + if (isset($_POST['letsencrypt']) && $_POST['letsencrypt'] == '1') { + // let's encrypt only works if there actually is a + // ssl ip/port assigned to the domain + if (domainHasSslIpPort($domain_check['id']) == true) { + $letsencrypt = '1'; + } else { + standard_error('letsencryptonlypossiblewithsslipport'); + } + } + if ($path == '') { standard_error('patherror'); } elseif ($subdomain == '') { @@ -354,7 +365,8 @@ if ($page == 'overview') { `speciallogfile` = :speciallogfile, `specialsettings` = :specialsettings, `ssl_redirect` = :ssl_redirect, - `phpsettingid` = :phpsettingid" + `phpsettingid` = :phpsettingid, + `letsencrypt` = :letsencrypt" ); $params = array( "customerid" => $userinfo['customerid'], @@ -370,7 +382,8 @@ if ($page == 'overview') { "speciallogfile" => $domain_check['speciallogfile'], "specialsettings" => $domain_check['specialsettings'], "ssl_redirect" => $ssl_redirect, - "phpsettingid" => $phpsid_result['phpsettingid'] + "phpsettingid" => $phpsid_result['phpsettingid'], + "letsencrypt" => $letsencrypt ); Database::pexecute($stmt, $params); @@ -403,7 +416,7 @@ if ($page == 'overview') { redirectTo($filename, array('page' => $page, 's' => $s)); } } else { - $stmt = Database::prepare("SELECT `id`, `domain`, `documentroot`, `ssl_redirect`,`isemaildomain` FROM `" . TABLE_PANEL_DOMAINS . "` + $stmt = Database::prepare("SELECT `id`, `domain`, `documentroot`, `ssl_redirect`,`isemaildomain`,`letsencrypt` FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `customerid` = :customerid AND `parentdomainid` = '0' AND `email_only` = '0' @@ -465,7 +478,7 @@ if ($page == 'overview') { } elseif ($action == 'edit' && $id != 0) { $stmt = Database::prepare("SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isemaildomain`, `d`.`wwwserveralias`, `d`.`iswildcarddomain`, - `d`.`parentdomainid`, `d`.`ssl_redirect`, `d`.`aliasdomain`, `d`.`openbasedir`, `d`.`openbasedir_path`, `pd`.`subcanemaildomain` + `d`.`parentdomainid`, `d`.`ssl_redirect`, `d`.`aliasdomain`, `d`.`openbasedir`, `d`.`openbasedir_path`, `d`.`letsencrypt`, `pd`.`subcanemaildomain` FROM `" . TABLE_PANEL_DOMAINS . "` `d`, `" . TABLE_PANEL_DOMAINS . "` `pd` WHERE `d`.`customerid` = :customerid AND `d`.`id` = :id @@ -545,7 +558,7 @@ if ($page == 'overview') { } if (isset($_POST['ssl_redirect']) && $_POST['ssl_redirect'] == '1') { - // a ssl-redirect only works of there actually is a + // a ssl-redirect only works if there actually is a // ssl ip/port assigned to the domain if (domainHasSslIpPort($id) == true) { $ssl_redirect = '1'; @@ -557,6 +570,18 @@ if ($page == 'overview') { $ssl_redirect = '0'; } + if (isset($_POST['letsencrypt']) && $_POST['letsencrypt'] == '1') { + // let's encrypt only works if there actually is a + // ssl ip/port assigned to the domain + if (domainHasSslIpPort($id) == true) { + $letsencrypt = '1'; + } else { + standard_error('letsencryptonlypossiblewithsslipport'); + } + } else { + $letsencrypt = '0'; + } + if ($path == '') { standard_error('patherror'); } else { @@ -580,7 +605,8 @@ if ($page == 'overview') { || $iswildcarddomain != $result['iswildcarddomain'] || $aliasdomain != $result['aliasdomain'] || $openbasedir_path != $result['openbasedir_path'] - || $ssl_redirect != $result['ssl_redirect']) { + || $ssl_redirect != $result['ssl_redirect'] + || $letsencrypt != $result['letsencrypt']) { $log->logAction(USR_ACTION, LOG_INFO, "edited domain '" . $idna_convert->decode($result['domain']) . "'"); $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET @@ -590,7 +616,8 @@ if ($page == 'overview') { `iswildcarddomain`= :iswildcarddomain, `aliasdomain`= :aliasdomain, `openbasedir_path`= :openbasedir_path, - `ssl_redirect`= :ssl_redirect + `ssl_redirect`= :ssl_redirect, + `letsencrypt`= :letsencrypt WHERE `customerid`= :customerid AND `id`= :id" ); @@ -602,6 +629,7 @@ if ($page == 'overview') { "aliasdomain" => ($aliasdomain != 0 && $alias_check == 0) ? $aliasdomain : null, "openbasedir_path" => $openbasedir_path, "ssl_redirect" => $ssl_redirect, + "letsencrypt" => $letsencrypt, "customerid" => $userinfo['customerid'], "id" => $id ); 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 e7b94e4c..e80708ba 100644 --- a/install/updates/froxlor/0.9/update_0.9.inc.php +++ b/install/updates/froxlor/0.9/update_0.9.inc.php @@ -3030,6 +3030,7 @@ if (isFroxlorVersion('0.9.34.2')) { Database::query("ALTER TABLE `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` ADD `expirationdate` DATETIME NULL AFTER `letsencrypt`;"); Database::query("ALTER TABLE `".TABLE_PANEL_CUSTOMERS."` ADD `lepublickey` TEXT DEFAULT NULL AFTER `custom_notes_show`"); Database::query("ALTER TABLE `".TABLE_PANEL_CUSTOMERS."` ADD `leprivatekey` TEXT DEFAULT NULL AFTER `lepublickey`;"); + Database::query("ALTER TABLE `".TABLE_PANEL_DOMAINS."` ADD `letsencrypt` INT NOT NULL DEFAULT '0' AFTER `ismainbutsubto`;"); Settings::AddNew("system.leprivatekey", 'unset'); Settings::AddNew("system.lepublickey", 'unset'); lastStepStatus(0); diff --git a/lib/classes/ssl/class.lescript.php b/lib/classes/ssl/class.lescript.php index ca2d320d..b043992b 100644 --- a/lib/classes/ssl/class.lescript.php +++ b/lib/classes/ssl/class.lescript.php @@ -75,6 +75,11 @@ class lescript public function signDomains(array $domains, $domainkey = null) { + + if (!$this->accountKey) { + throw new \RuntimeException("Account not initiated"); + } + $this->log('Starting certificate generation process for domains'); $privateAccountKey = openssl_pkey_get_private($this->accountKey); diff --git a/lib/formfields/customer/domains/formfield.domains_add.php b/lib/formfields/customer/domains/formfield.domains_add.php index 55a1a67c..5d8fd271 100644 --- a/lib/formfields/customer/domains/formfield.domains_add.php +++ b/lib/formfields/customer/domains/formfield.domains_add.php @@ -70,6 +70,16 @@ return array( ), 'value' => array() ), + 'useletsencrypt' => array( + 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? true : false) : false), + 'label' => $lng['domains']['letsencrypt']['title'], + 'desc' => $lng['domains']['letsencrypt']['description'], + 'type' => 'checkbox', + 'values' => array( + array ('label' => $lng['panel']['yes'], 'value' => '1') + ), + 'value' => array() + ), 'openbasedir_path' => array( 'label' => $lng['domain']['openbasedirpath'], 'type' => 'select', diff --git a/lib/formfields/customer/domains/formfield.domains_edit.php b/lib/formfields/customer/domains/formfield.domains_edit.php index 7d809532..005d0b4c 100644 --- a/lib/formfields/customer/domains/formfield.domains_edit.php +++ b/lib/formfields/customer/domains/formfield.domains_edit.php @@ -86,6 +86,16 @@ return array( ), 'value' => array($result['ssl_redirect']) ), + 'useletsencrypt' => array( + 'visible' => (Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports != '' ? (domainHasSslIpPort($result['id']) ? true : false) : false) : false), + 'label' => $lng['domains']['letsencrypt']['title'], + 'desc' => $lng['domains']['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'], diff --git a/lng/english.lng.php b/lng/english.lng.php index d369cb3b..4d8c78b3 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1924,3 +1924,9 @@ $lng['opcacheinfo']['blacklist'] = 'Blacklist'; $lng['opcacheinfo']['novalue'] = 'no value'; $lng['opcacheinfo']['true'] = 'true'; $lng['opcacheinfo']['false'] = 'false'; + +// Added for let's encrypt +$lng['domains']['letsencrypt']['title'] = 'Use Let\'s Encrypt'; +$lng['domains']['letsencrypt']['description'] = 'Get a free certificate from Let\'s Encrypt. This certificate will be created and renewed automatically'; +$lng['error']['sslredirectonlypossiblewithsslipport'] = 'Using Let\'s Encrypt is only possible when the domain has at least one ssl-enabled IP/port combination assigned.'; +$lng['panel']['letsencrypt'] = 'Using Let\'s encrypt'; \ No newline at end of file diff --git a/scripts/jobs/cron_letsencrypt.php b/scripts/jobs/cron_letsencrypt.php index 4f93bfdc..64772ffa 100644 --- a/scripts/jobs/cron_letsencrypt.php +++ b/scripts/jobs/cron_letsencrypt.php @@ -21,10 +21,10 @@ fwrite($debugHandler, "updating let's encrypt certificates\n"); $certificates_stmt = Database::query(" - SELECT domssl.`id`, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`, dom.`documentroot`, - cust.`leprivatekey`, cust.`lepublickey`, cust.customerid - FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` as domssl, `" . TABLE_PANEL_DOMAINS . "` as dom, `" . TABLE_PANEL_CUSTOMERS . "` as cust - WHERE domssl.domainid = dom.id AND dom.customerid = cust.customerid AND domssl.letsencrypt = 1 + SELECT domssl.`id`, domssl.expirationdate, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`, + dom.`documentroot`, 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) "); $upd_stmt = Database::prepare(" @@ -39,14 +39,25 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) { && is_dir($certrow['documentroot']) ) { fwrite($debugHandler, "updating " . $certrow['domain'] . "\n"); - // Parse the old certificate - $x509data = openssl_x509_parse($certrow['ssl_cert_file']); - // We are interessted in the old SAN - data - $san = explode(', ', $x509data['extensions']['subjectAltName']); - $domains = array(); - foreach($san as $dnsname) { - $domains[] = substr($dnsname, 4); + if ($certrow['ssl_cert_file']) { + fwrite($debugHandler, "letsencrypt using old key / SAN for " . $certrow['domain'] . "\n"); + // Parse the old certificate + $x509data = openssl_x509_parse($certrow['ssl_cert_file']); + + // We are interessted in the old SAN - data + $san = explode(', ', $x509data['extensions']['subjectAltName']); + $domains = array(); + foreach($san as $dnsname) { + $domains[] = substr($dnsname, 4); + } + } else { + fwrite($debugHandler, "letsencrypt generating new key / SAN for " . $certrow['domain'] . "\n"); + $domains = array($certrow['domain']); + // Add www. for SAN + if ($certrow['wwwserveralias'] == 1) { + $domains[] = 'www.' . $certrow['domain']; + } } try { diff --git a/templates/Sparkle/customer/domains/domains_domain.tpl b/templates/Sparkle/customer/domains/domains_domain.tpl index 681e1487..4e63a9d9 100644 --- a/templates/Sparkle/customer/domains/domains_domain.tpl +++ b/templates/Sparkle/customer/domains/domains_domain.tpl @@ -20,6 +20,9 @@ {$lng['panel']['ssleditor']}   + + {$lng['panel']['letsencrypt']} + ({$lng['domains']['isassigneddomain']})