* @author Froxlor team (2016-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Cron * * @since 0.9.35 * */ $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`, 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 "); $upddom_stmt = Database::prepare(" UPDATE `".TABLE_PANEL_DOMAINS."` SET `ssl_redirect` = '1' WHERE `id` = :domainid "); $changedetected = 0; while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) { // Only renew let's encrypt certificate for domains where a documentroot // already exists if ($certrow['ssl_redirect'] != 2) { $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Updating " . $certrow['domain']); if ($certrow['ssl_cert_file']) { $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt using old key / SAN for " . $certrow['domain']); // 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 { $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt generating new key / SAN for " . $certrow['domain']); $domains = array($certrow['domain']); // Add www. for SAN if ($certrow['wwwserveralias'] == 1) { $domains[] = 'www.' . $certrow['domain']; } } try { // Initialize Lescript with documentroot $le = new lescript($cronlog); // Initialize Lescript $le->initAccount($certrow); // Request the new certificate (old key may be used) $return = $le->signDomains($domains, $certrow['ssl_key_file']); // We are interessted in the expirationdate $newcert = openssl_x509_parse($return['crt']); // Store the new data Database::pexecute($updcert_stmt, array( 'id' => $certrow['id'], 'domainid' => $certrow['domainid'], 'crt' => $return['crt'], 'key' => $return['key'], 'ca' => $return['chain'], 'fullchain' => $return['fullchain'], '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']); $changedetected = 1; } catch (Exception $e) { $cronlog->logAction(CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ": " . $e->getMessage()); } } else { $cronlog->logAction(CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); } } // If we have a change in a certificate, we need to update the webserver - configs // This is easiest done by just creating a new task ;) if ($changedetected) { inserttask(1); }