Changed comments to // to match the rest of Froxlor and made small improvements to the accountKey

Signed-off-by: Florian Aders <eleras@froxlor.org>
This commit is contained in:
Florian Aders
2016-01-30 10:56:08 +01:00
parent ed2837f1db
commit 2e7dd6f212
2 changed files with 50 additions and 51 deletions

View File

@@ -1,34 +1,34 @@
<?php <?php
# Copyright (c) 2015, Stanislav Humplik <sh@analogic.cz> // Copyright (c) 2015, Stanislav Humplik <sh@analogic.cz>
# All rights reserved. // All rights reserved.
# //
# Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met: // modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright // * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer. // notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright // * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the // notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution. // documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the // * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products // names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission. // derived from this software without specific prior written permission.
# //
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY // DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# This file is copied from https://github.com/analogic/lescript // This file is copied from https://github.com/analogic/lescript
# and modified to work without files and integrate in Froxlor // and modified to work without files and integrate in Froxlor
class lescript class lescript
{ {
#public $ca = 'https://acme-v01.api.letsencrypt.org'; //public $ca = 'https://acme-v01.api.letsencrypt.org';
public $ca = 'https://acme-staging.api.letsencrypt.org'; // testing public $ca = 'https://acme-staging.api.letsencrypt.org'; // testing
public $license = 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf'; public $license = 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf';
public $countryCode = 'DE'; public $countryCode = 'DE';
@@ -38,7 +38,7 @@ class lescript
private $debugHandler; private $debugHandler;
private $client; private $client;
private $accountKeyPath; private $accountKey;
public function __construct($webRootDir, $debugHandler) public function __construct($webRootDir, $debugHandler)
{ {
@@ -49,9 +49,9 @@ class lescript
public function initAccount() public function initAccount()
{ {
// Let's see if we have the private accountkey
$private = Settings::Get('system.leprivatekey'); $this->accountKey = Settings::Get('system.leprivatekey');
if (!$private || $private == 'unset') { if (!$this->accountKey || $this->accountKey == 'unset') {
// generate and save new private key for account // generate and save new private key for account
// --------------------------------------------- // ---------------------------------------------
@@ -60,6 +60,7 @@ class lescript
$keys = $this->generateKey(); $keys = $this->generateKey();
Settings::Set('system.leprivatekey', $keys['private']); Settings::Set('system.leprivatekey', $keys['private']);
Settings::Set('system.lepublickey', $keys['public']); Settings::Set('system.lepublickey', $keys['public']);
$this->accountKey = $keys['private'];
$this->postNewReg(); $this->postNewReg();
$this->log('New account certificate registered'); $this->log('New account certificate registered');
@@ -74,7 +75,7 @@ class lescript
{ {
$this->log('Starting certificate generation process for domains'); $this->log('Starting certificate generation process for domains');
$privateAccountKey = openssl_pkey_get_private(Settings::Get('system.leprivatekey')); $privateAccountKey = openssl_pkey_get_private($this->accountKey);
$accountKeyDetails = openssl_pkey_get_details($privateAccountKey); $accountKeyDetails = openssl_pkey_get_details($privateAccountKey);
// start domains authentication // start domains authentication
@@ -148,6 +149,8 @@ class lescript
); );
// waiting loop // waiting loop
// we wait for a maximum of 30 seconds to avoid endless loops
$count = 0;
do { do {
if(empty($result['status']) || $result['status'] == "invalid") { if(empty($result['status']) || $result['status'] == "invalid") {
throw new \RuntimeException("Verification ended with error: ".json_encode($result)); throw new \RuntimeException("Verification ended with error: ".json_encode($result));
@@ -157,11 +160,12 @@ class lescript
if(!$ended) { if(!$ended) {
$this->log("Verification pending, sleeping 1s"); $this->log("Verification pending, sleeping 1s");
sleep(1); sleep(1);
$count++;
} }
$result = $this->client->get($location); $result = $this->client->get($location);
} while (!$ended); } while (!$ended && $count < 30);
$this->log("Verification ended with status: ${result['status']}"); $this->log("Verification ended with status: ${result['status']}");
@unlink($tokenPath); @unlink($tokenPath);
@@ -225,16 +229,11 @@ class lescript
if(empty($certificates)) throw new \RuntimeException('No certificates generated'); if(empty($certificates)) throw new \RuntimeException('No certificates generated');
$this->log("Saving fullchain.pem");
$fullchain = implode("\n", $certificates); $fullchain = implode("\n", $certificates);
$this->log("Saving cert.pem");
$crt = array_shift($certificates); $crt = array_shift($certificates);
$this->log("Saving chain.pem");
$chain = implode("\n", $certificates); $chain = implode("\n", $certificates);
$this->log("Done !!§§!"); $this->log("Done, returning new certificates and key");
return array('fullchain' => $fullchain, 'crt' => $crt, 'chain' => $chain, 'key' => $privateDomainKey); return array('fullchain' => $fullchain, 'crt' => $crt, 'chain' => $chain, 'key' => $privateDomainKey);
} }
@@ -320,7 +319,7 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
private function signedRequest($uri, array $payload) private function signedRequest($uri, array $payload)
{ {
$privateKey = openssl_pkey_get_private(Settings::Get('system.leprivatekey')); $privateKey = openssl_pkey_get_private($this->accountKey);
$details = openssl_pkey_get_details($privateKey); $details = openssl_pkey_get_details($privateKey);
$header = array( $header = array(

View File

@@ -31,16 +31,16 @@ $upd_stmt = Database::prepare("
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'])
) { ) {
fwrite($debugHandler, "updating " . $certrow['domain'] . "\n"); fwrite($debugHandler, "updating " . $certrow['domain'] . "\n");
# Parse the old certificate // Parse the old certificate
$x509data = openssl_x509_parse($certrow['ssl_cert_file']); $x509data = openssl_x509_parse($certrow['ssl_cert_file']);
# We are interessted in the old SAN - data // We are interessted in the old SAN - data
$san = explode(', ', $x509data['extensions']['subjectAltName']); $san = explode(', ', $x509data['extensions']['subjectAltName']);
$domains = array(); $domains = array();
foreach($san as $dnsname) { foreach($san as $dnsname) {
@@ -48,19 +48,19 @@ 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'], $debugHandler);
# Initialize Lescript // Initialize Lescript
$le->initAccount(); $le->initAccount();
# Request the new certificate (old key may be used) // 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']);
# We are interessted in the expirationdate // We are interessted in the expirationdate
$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($upd_stmt, array(
'crt' => $return['crt'], 'crt' => $return['crt'],
'key' => $return['key'], 'key' => $return['key'],
@@ -69,9 +69,9 @@ while ($certrow = $certificates_stmt->fetch(PDO::FETCH_ASSOC)) {
'id' => $certrow['id']) 'id' => $certrow['id'])
); );
} catch (\Exception $e) { } catch (\Exception $e) {
fwrite($debugHandler, 'letsencrypt exception: ' . $e->getMessage()); fwrite($debugHandler, 'letsencrypt exception: ' . $e->getMessage() . "\n");
} }
} else { } else {
fwrite($debugHandler, 'documentroot ' . $certrow['documentroot'] . ' does not exist' . "\n"); fwrite($debugHandler, 'letsencrypt skipped because documentroot ' . $certrow['documentroot'] . ' does not exist' . "\n");
} }
} }