From 1b4231e1a93588c0d6255b77fa2c064da1962fca Mon Sep 17 00:00:00 2001 From: Nicolas Roman Date: Tue, 9 Jul 2019 18:07:47 +0200 Subject: [PATCH] make-csr function and confirmation button when warning is displayed --- inc/webadmin-letsencrypt.php | 23 ++++++--- lib/letsencrypt.php | 89 +++++++++++++++++--------------- scripts/web-add.sh | 36 +++++++++++-- tpl/webadmin-letsencrypt.tpl.php | 18 +++++-- 4 files changed, 110 insertions(+), 56 deletions(-) diff --git a/inc/webadmin-letsencrypt.php b/inc/webadmin-letsencrypt.php index 2859aab..ff85b37 100644 --- a/inc/webadmin-letsencrypt.php +++ b/inc/webadmin-letsencrypt.php @@ -52,6 +52,7 @@ if (isset($_POST['submit'])) { $domainsIncluded = array(); foreach ($_SESSION['letsencrypt-domains'] as $domain) { $existingSSLCertificate = $letsencrypt->getCertificate($domain); + // if no certificate is present (false returned) for this domain, go to the next domain if (is_bool($existingSSLCertificate)) { continue; } @@ -73,7 +74,7 @@ if (isset($_POST['submit'])) { // check wether the certificate is valid or expired $isCertValid = $letsencrypt->isCertValid($parsedCertificate["validUntil"]); - if (!$îsCertValid) { + if (!$îsCertValid && !isset($_POST['force_renew'])) { $warningMessage = "Attention : le certificat existant n'est plus valide. Souhaitez-vous le renouveller ?"; break 2; @@ -81,7 +82,7 @@ if (isset($_POST['submit'])) { } // contains all the domains included in the existing certificate - if (!empty($domainsIncluded)) { + if (!empty($domainsIncluded) && !isset($_POST['force_renew'])) { $domainsNotIncluded = array_diff($_SESSION['letsencrypt-domains'], $domainsIncluded); if (empty($domainsNotIncluded)) { @@ -96,11 +97,11 @@ if (isset($_POST['submit'])) { } // check HTTP - $checked_domains = $letsencrypt->checkRemoteResourceAvailability($_SESSION['letsencrypt-domains']); - $failed_domains = array_diff($_SESSION['letsencrypt-domains'], $checked_domains); - if (!empty($failed_domains)) { - $errorMessage = "Erreur : Le challenge HTTP a échoué pour le(s) domaine(s) ci-dessous. - Merci de vérifier que le dossier /.well-known/ est accessible."; + $isRemoteResourceAvailable = $letsencrypt->checkRemoteResourceAvailability($_SESSION['letsencrypt-domains'][0]); + + if (!$isRemoteResourceAvailable) { + $errorMessage = "Erreur : Le challenge HTTP a échoué.
+ Merci de vérifier que le dossier /.well-known/evoacme-challenge/ est accessible."; break; } @@ -115,6 +116,14 @@ if (isset($_POST['submit'])) { break; } + + // make csr + $isCsrGenerated = $letsencrypt->makeCsr($params[1], $_SESSION['letsencrypt-domains']); + + // evoacme TEST ou DRY RUN + // evoacme + // modifier configuration vhosts + // reload service web } include_once EVOADMIN_BASE . '../tpl/webadmin-letsencrypt.tpl.php'; diff --git a/lib/letsencrypt.php b/lib/letsencrypt.php index cd0ca65..b355505 100644 --- a/lib/letsencrypt.php +++ b/lib/letsencrypt.php @@ -7,7 +7,7 @@ namespace lib; class LetsEncrypt { const HTTP_OK = 200; - const HTTP_CHALLENGE_URL = '/.well-known/acme-challenge'; + const HTTP_CHALLENGE_URL = '/.well-known/acme-challenge/testfile'; /** * create the file used to test the HTTP challenge @@ -28,56 +28,63 @@ class LetsEncrypt } /** - * perform a cURL call on the remote resource - * the cURL call follows redirections and pushes the last valid URL to an array - * @param Array $domains list of domains - * @return Array $checked_domains list of checked domains + * generate a CSR + * @param string $vhost + * @param Array $domains + * @return boolean */ - public function checkRemoteResourceAvailability($domains) + public function makeCsr($vhost, $domains) + { + $domains = implode(' ', $domains); + $cmd = 'web-add.sh generate-csr ' . $vhost . ' ' . "$domains"; + + sudoexec($cmd ,$data_output, $exec_return); + + if ($exec_return == 0) { + return true; + } + + return false; + } + + /** + * perform a cURL call on the remote resource + * the cURL call follows redirections + * @param Array $domains list of domains + * @return boolean + */ + public function checkRemoteResourceAvailability($domain) { $this->createFileHttpChallenge(); - $curl_multi = curl_multi_init(); - $curl_handles = array(); - $checked_domains = array(); + $curl_handler = curl_init(); - foreach ($domains as $key => $domain) { - $curl_handles[$key] = curl_init($domain . self::HTTP_CHALLENGE_URL); + // setting cURL options + curl_setopt($curl_handler, CURLOPT_URL, $domain . self::HTTP_CHALLENGE_URL); + curl_setopt($curl_handler, CURLOPT_TIMEOUT, 3); + curl_setopt($curl_handler, CURLOPT_HEADER, true); + curl_setopt($curl_handler, CURLOPT_NOBODY, true); + curl_setopt($curl_handler, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl_handler, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl_handler, CURLOPT_MAXREDIRS, 3); + curl_setopt($curl_handler, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($curl_handler, CURLOPT_RETURNTRANSFER, true); - // setting cURL options - curl_setopt($curl_handles[$key], CURLOPT_TIMEOUT, 3); - curl_setopt($curl_handles[$key], CURLOPT_HEADER, true); - curl_setopt($curl_handles[$key], CURLOPT_NOBODY, true); - curl_setopt($curl_handles[$key], CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($curl_handles[$key], CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl_handles[$key], CURLOPT_MAXREDIRS, 3); - curl_setopt($curl_handles[$key], CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); - curl_setopt($curl_handles[$key], CURLOPT_RETURNTRANSFER, true); + curl_exec($curl_handler); - curl_multi_add_handle($curl_multi, $curl_handles[$key]); - } - - do { - curl_multi_exec($curl_multi, $active); - } while ($active); - - foreach ($curl_handles as $curl_handle) { - $returned_http_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE); - $returned_http_url = curl_getinfo($curl_handle, CURLINFO_EFFECTIVE_URL); - - if ($returned_http_code === self::HTTP_OK && strpos($returned_http_url, self::HTTP_CHALLENGE_URL)) { - $returned_http_url = str_replace(self::HTTP_CHALLENGE_URL, '', $returned_http_url); - $returned_http_url = preg_replace('#^https?://#', '', $returned_http_url); - - array_push($checked_domains, $returned_http_url); - } - curl_multi_remove_handle($curl_multi, $curl_handle); - } - curl_multi_close($curl_multi); + $returned_http_code = curl_getinfo($curl_handler, CURLINFO_HTTP_CODE); + $returned_http_url = curl_getinfo($curl_handler, CURLINFO_EFFECTIVE_URL); $this->deleteFileHttpChallenge(); - return $checked_domains; + if ($returned_http_code === self::HTTP_OK && strpos($returned_http_url, self::HTTP_CHALLENGE_URL)) { + $returned_http_url = str_replace(self::HTTP_CHALLENGE_URL, '', $returned_http_url); + $returned_http_url = preg_replace('#^https?://#', '', $returned_http_url); + + return true; + } + + return false; } /** diff --git a/scripts/web-add.sh b/scripts/web-add.sh index 05fdada..bd4571b 100755 --- a/scripts/web-add.sh +++ b/scripts/web-add.sh @@ -853,6 +853,9 @@ arg_processing() { manage-http-challenge-file) op_managehttpchallengefile "$@" ;; + generate-csr) + op_makecsr "$@" + ;; *) usage ;; @@ -860,16 +863,41 @@ arg_processing() { fi } +op_makecsr() { + if [ $# -gt 1 ]; then + vhost="$1" + domains="" + + # remove the first argument to keep only the domains + shift 1 + + for domain in "$@"; do + domains="${domains:+${domains} }${domain}" + done + + # pipe the domains to make-csr because we don't have STDIN + echo "$domains" | make-csr "$vhost" + else usage + fi +} + op_managehttpchallengefile() { if [ $# -eq 1 ]; then - file="/var/lib/letsencrypt/.well-known/acme-challenge" + folder="/var/lib/letsencrypt/.well-known/acme-challenge" + file="testfile" + action=${1}; if [ "$action" = "create" ]; then - touch "$file" - chmod 755 "$file" + if [ ! -d "$folder" ]; then + mkdir "$folder" + fi + if [ ! -f "$folder/$file" ]; then + touch "$folder/$file" + fi + chmod -R 755 "$folder" elif [ "$action" = "delete" ]; then - rm "$file" + rm -r "$folder" else usage fi else usage diff --git a/tpl/webadmin-letsencrypt.tpl.php b/tpl/webadmin-letsencrypt.tpl.php index d95698e..9d7c881 100644 --- a/tpl/webadmin-letsencrypt.tpl.php +++ b/tpl/webadmin-letsencrypt.tpl.php @@ -2,8 +2,8 @@ ' . $error_message . ''; + if (!empty($errorMessage)) { + echo '' . $errorMessage . ''; if (count($failed_domains) > 0) { echo '

'; @@ -12,8 +12,18 @@ if (isset($_POST['submit'])) { } echo '

'; } + } elseif (!empty($warningMessage)) { + echo '' . $warningMessage . ''; ?> +
+

+ + +

+
+ Les domaines suivants seront intégrés au certificat :

"; @@ -24,7 +34,7 @@ if (isset($_POST['submit'])) { } echo '

'; ?> -
+