From b1f0c209804d3b627ab62fcba53e32df289ec8b6 Mon Sep 17 00:00:00 2001 From: Hj Ahmad Rasyid Hj Ismail <ahrasis@gmail.com> Date: Wed, 6 Jan 2021 07:32:57 +0100 Subject: [PATCH] Update installer_base.lib.php to overwrite self-signed certificate with LE SSL certs when possible. A temporary backup is made to be restored if LE SSL certs failed to be issued. It will be made permanent if LE SSL certs are successfully issued. To resolve raised issue https://git.ispconfig.org/ispconfig/ispconfig3/-/issues/5919 --- install/lib/installer_base.lib.php | 74 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 7bb75d8c37..6996198e7a 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -2871,8 +2871,13 @@ class installer_base { $ip_address_match = true; } + // Get subject and issuer of ispserver.crt to check if it is self-signed cert + if (file_exists($ssl_crt_file)) { + $crt_subject = exec("openssl x509 -in ".escapeshellarg($ssl_crt_file)." -inform PEM -noout -subject"); + $crt_issuer = exec("openssl x509 -in ".escapeshellarg($ssl_crt_file)." -inform PEM -noout -issuer"); + } - if ((!@is_dir($acme_cert_dir) || !@file_exists($check_acme_file) || !@file_exists($ssl_crt_file) || md5_file($check_acme_file) != md5_file($ssl_crt_file)) && $ip_address_match == true) { + if ((@file_exists($ssl_crt_file) && ($crt_subject == $crt_issuer)) || (!@is_dir($acme_cert_dir) || !@file_exists($check_acme_file) || !@file_exists($ssl_crt_file) || md5_file($check_acme_file) != md5_file($ssl_crt_file)) && $ip_address_match == true) { // This script is needed earlier to check and open http port 80 or standalone might fail // Make executable and temporary symlink latest letsencrypt pre, post and renew hook script before install @@ -2942,6 +2947,14 @@ class installer_base { $issued_successfully = false; + // Backup existing ispserver ssl files + if(file_exists($ssl_crt_file) || is_link($ssl_crt_file)) + rename($ssl_crt_file, $ssl_crt_file.'-temporary.bak'); + if(file_exists($ssl_key_file) || is_link($ssl_key_file)) + rename($ssl_key_file, $ssl_key_file.'-temporary.bak'); + if(file_exists($ssl_pem_file) || is_link($ssl_pem_file)) + rename($ssl_pem_file, $ssl_pem_file.'-temporary.bak'); + // Attempt to use Neilpang acme.sh first, as it is now the preferred LE client if (is_executable($acme)) { @@ -2958,18 +2971,6 @@ class installer_base { if($ret == 0 || ($ret == 2 && file_exists($check_acme_file))) { // acme.sh returns with 2 on issue for already existing certificate - - // Backup existing ispserver ssl files - if(file_exists($ssl_crt_file) || is_link($ssl_crt_file)) { - rename($ssl_crt_file, $ssl_crt_file . '-' . $date->format('YmdHis') . '.bak'); - } - if(file_exists($ssl_key_file) || is_link($ssl_key_file)) { - rename($ssl_key_file, $ssl_key_file . '-' . $date->format('YmdHis') . '.bak'); - } - if(file_exists($ssl_pem_file) || is_link($ssl_pem_file)) { - rename($ssl_pem_file, $ssl_pem_file . '-' . $date->format('YmdHis') . '.bak'); - } - $check_acme_file = $ssl_crt_file; // Define LE certs name and path, then install them @@ -2978,8 +2979,26 @@ class installer_base { $acme_chain = "--fullchain-file " . escapeshellarg($ssl_crt_file); exec("$acme --install-cert -d " . escapeshellarg($hostname) . " $acme_key $acme_chain"); $issued_successfully = true; + + // Make temporary backup of self-signed certs permanent + if(file_exists($ssl_crt_file.'-temporary.bak') || is_link($ssl_crt_file.'-temporary.bak')) + rename($ssl_crt_file.'-temporary.bak', $ssl_crt_file.'-'.$date->format('YmdHis').'.bak'); + if(file_exists($ssl_key_file.'-temporary.bak') || is_link($ssl_key_file.'-temporary.bak')) + rename($ssl_key_file.'-temporary.bak', $ssl_key_file.'-'.$date->format('YmdHis').'.bak'); + if(file_exists($ssl_pem_file.'-temporary.bak') || is_link($ssl_pem_file.'-temporary.bak')) + rename($ssl_pem_file.'-temporary.bak', $ssl_pem_file.'-'.$date->format('YmdHis').'.bak'); + } else { swriteln('Issuing certificate via acme.sh failed. Please check that your hostname can be verified by letsencrypt'); + + // Restore temporary backup of self-signed certs + if(file_exists($ssl_crt_file.'-temporary.bak') || is_link($ssl_crt_file.'-temporary.bak')) + rename($ssl_crt_file.'-temporary.bak', $ssl_crt_file); + if(file_exists($ssl_key_file.'-temporary.bak') || is_link($ssl_key_file.'-temporary.bak')) + rename($ssl_key_file.'-temporary.bak', $ssl_key_file); + if(file_exists($ssl_pem_file.'-temporary.bak') || is_link($ssl_pem_file.'-temporary.bak')) + rename($ssl_pem_file.'-temporary.bak', $ssl_pem_file); + } // Else, we attempt to use the official LE certbot client certbot } else { @@ -3011,24 +3030,31 @@ class installer_base { if($ret == 0) { // certbot returns with 0 on issue for already existing certificate - // Backup existing ispserver ssl files - if(file_exists($ssl_crt_file) || is_link($ssl_crt_file)) { - rename($ssl_crt_file, $ssl_crt_file . '-' . $date->format('YmdHis') . '.bak'); - } - if(file_exists($ssl_key_file) || is_link($ssl_key_file)) { - rename($ssl_key_file, $ssl_key_file . '-' . $date->format('YmdHis') . '.bak'); - } - if(file_exists($ssl_pem_file) || is_link($ssl_pem_file)) { - rename($ssl_pem_file, $ssl_pem_file . '-' . $date->format('YmdHis') . '.bak'); - } - $acme_cert_dir = '/etc/letsencrypt/live/' . $hostname; symlink($acme_cert_dir . '/fullchain.pem', $ssl_crt_file); symlink($acme_cert_dir . '/privkey.pem', $ssl_key_file); $issued_successfully = true; + + // Make temporary backup of self-signed certs permanent + if(file_exists($ssl_crt_file.'-temporary.bak') || is_link($ssl_crt_file.'-temporary.bak')) + rename($ssl_crt_file.'-temporary.bak', $ssl_crt_file.'-'.$date->format('YmdHis').'.bak'); + if(file_exists($ssl_key_file.'-temporary.bak') || is_link($ssl_key_file.'-temporary.bak')) + rename($ssl_key_file.'-temporary.bak', $ssl_key_file.'-'.$date->format('YmdHis').'.bak'); + if(file_exists($ssl_pem_file.'-temporary.bak') || is_link($ssl_pem_file.'-temporary.bak')) + rename($ssl_pem_file.'-temporary.bak', $ssl_pem_file.'-'.$date->format('YmdHis').'.bak'); + } else { swriteln('Issuing certificate via certbot failed. Please check log files and make sure that your hostname can be verified by letsencrypt'); + + // Restore temporary backup of self-signed certs + if(file_exists($ssl_crt_file.'-temporary.bak') || is_link($ssl_crt_file.'-temporary.bak')) + rename($ssl_crt_file.'-temporary.bak', $ssl_crt_file); + if(file_exists($ssl_key_file.'-temporary.bak') || is_link($ssl_key_file.'-temporary.bak')) + rename($ssl_key_file.'-temporary.bak', $ssl_key_file); + if(file_exists($ssl_pem_file.'-temporary.bak') || is_link($ssl_pem_file.'-temporary.bak')) + rename($ssl_pem_file.'-temporary.bak', $ssl_pem_file); + } } else { swriteln('Did not find any valid acme client (acme.sh or certbot)'); -- GitLab