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:
@@ -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(
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user