diff options
Diffstat (limited to 'modules-available')
9 files changed, 42 insertions, 95 deletions
diff --git a/modules-available/webinterface/api.inc.php b/modules-available/webinterface/api.inc.php index 0b4fabdb..271ccc60 100644 --- a/modules-available/webinterface/api.inc.php +++ b/modules-available/webinterface/api.inc.php @@ -21,7 +21,7 @@ if (empty($newCert)) { // Import will try to validate the certificate too $task = WebInterface::tmImportCustomCert($newKey, $newCert, 'api', - 'New HTTPS certificate uploaded via API from ' . $_SERVER['REMOTE_ADDR']); + 'Applying new HTTPS certificate uploaded via API from ' . $_SERVER['REMOTE_ADDR']); $task = Taskmanager::waitComplete($task, 10000); if (!Taskmanager::isTask($task)) { http_send_status(500); diff --git a/modules-available/webinterface/inc/acme.inc.php b/modules-available/webinterface/inc/acme.inc.php index f12ceb2e..446c0e45 100644 --- a/modules-available/webinterface/inc/acme.inc.php +++ b/modules-available/webinterface/inc/acme.inc.php @@ -96,7 +96,7 @@ class Acme return; if (Taskmanager::isFailed($task)) { if (($args['user'] ?? null) === null) { - EventLog::warning('Automatic ACME renewal of HTTPS certificate failed', json_encode($task, JSON_PRETTY_PRINT)); + EventLog::warning('Automatic ACME renewal of HTTPS certificate failed', print_r($task, true)); } Property::set(self::PROP_ERROR, $task['data']['error'] ?? 'Unknown error'); } else { diff --git a/modules-available/webinterface/inc/webinterface.inc.php b/modules-available/webinterface/inc/webinterface.inc.php index 035b94e6..d50acd50 100644 --- a/modules-available/webinterface/inc/webinterface.inc.php +++ b/modules-available/webinterface/inc/webinterface.inc.php @@ -88,7 +88,7 @@ class WebInterface return; } if (Taskmanager::isFailed($task)) { - EventLog::failure($data['message'], json_encode($task, JSON_PRETTY_PRINT)); + EventLog::failure('TASK FAILED: ' . $data['message'], print_r($task, true)); return; } EventLog::info($data['message']); @@ -97,19 +97,10 @@ class WebInterface public static function tmDisableHttps(): ?string { - Property::set(WebInterface::PROP_HSTS, 'off'); - $task = Taskmanager::submit('LighttpdHttps', []); - self::registerCallback($task, 'off', 'HTTPS disabled'); - return $task['id'] ?? null; - } - - public static function tmGenerateRandomCert(): ?string - { $task = Taskmanager::submit('LighttpdHttps', [ - 'proxyip' => Property::getServerIp(), 'redirect' => self::isHttpsRedirectEnabled(), ]); - self::registerCallback($task, 'generated', 'Self-signed HTTPS certificate generated'); + self::registerCallback($task, 'off', 'Disabling HTTPS, switching to self-signed certificate'); return $task['id'] ?? null; } @@ -117,7 +108,6 @@ class WebInterface { $key = preg_replace('/[\r\n]+/', "\n", $key); $cert = preg_replace('/[\r\n]+/', "\n", $cert); - Property::set(WebInterface::PROP_TYPE, $type); $task = Taskmanager::submit('LighttpdHttps', [ 'importcert' => $cert, 'importkey' => $key, @@ -129,8 +119,6 @@ class WebInterface public static function tmSetHttpRedirectMode(): ?string { - if (Property::get(WebInterface::PROP_TYPE) === 'off') - return null; $task = Taskmanager::submit('LighttpdHttps', array( 'redirectOnly' => true, 'redirect' => self::isHttpsRedirectEnabled(), diff --git a/modules-available/webinterface/lang/de/messages.json b/modules-available/webinterface/lang/de/messages.json index 3f1d5ba4..f1d0d6af 100644 --- a/modules-available/webinterface/lang/de/messages.json +++ b/modules-available/webinterface/lang/de/messages.json @@ -4,8 +4,6 @@ "acme-no-mail": "Keine administrative Mailadresse angegeben", "acme-no-provider": "Kein ACME-Anbieter ausgew\u00e4hlt", "https-on-cert-missing": "HTTPS ist aktiviert, das Zertifikat ist jedoch nicht vorhanden. Bitte nehmen Sie die HTTPS-Konfiguration erneut vor.", - "https-used-without-cert": "HTTPS wird gerade verwendet, obwohl kein Zertifikat installiert ist. Falls Sie die Webserver-Konfiguration manuell angepasst haben, um HTTPS zu aktivieren beachten Sie bitte, dass die Konfiguration bei einem zuk\u00fcnftigen Server-Update ohne Nachfrage \u00fcberschrieben werden k\u00f6nnte.", - "https-want-off-is-used": "HTTPS wird gerade verwendet, obwohl es laut Einstellungen deaktiviert ist. Merkw\u00fcrdig.", "https-want-redirect-is-plain": "Weiterleitung von HTTP auf HTTPS ist aktiviert, trotzdem scheint die Verbindung Ihres Browsers mit dem Server unverschl\u00fcsselt zu sein. Nehmen Sie die Konfiguration erneut vor und wenden Sie sich an den Support, wenn das Problem weiterhin besteht.", "invalid-domain": "Ung\u00fcltige Domain: {{0}}", "mw-acme-errors": "Fehler beim erneuern\/abrufen des Zertifikats via ACME" diff --git a/modules-available/webinterface/lang/de/template-tags.json b/modules-available/webinterface/lang/de/template-tags.json index 05cd88b0..ed7e9f00 100644 --- a/modules-available/webinterface/lang/de/template-tags.json +++ b/modules-available/webinterface/lang/de/template-tags.json @@ -9,6 +9,7 @@ "lang_acmeSelected": "Das aktuelle Zertifikat wurde via ACME erstellt.", "lang_acmeWipeAll": "Alle hinterlegten Daten l\u00f6schen und Account etc. von neuem anfordern", "lang_acmeWipeAllHint": "W\u00e4hlen Sie diese Option aus, wenn das Zertifikat nicht verl\u00e4ndert werden kann, oder es Probleme beim \u00c4ndern und Speichern der Daten gibt. Beachten Sie, dass einige Anbieter ein Ratelimit haben, Sie also nicht zu oft\/schnell hintereinander ein neues Zertifikat anfordern sollten.", + "lang_apiSelected": "Das aktuelle Zertifikat wurde mittels API-Zugriff eingespielt.", "lang_applyingSettings": "Anwenden der Einstellungen", "lang_caChain": "Optional k\u00f6nnen Sie hier die zum Zertifikat geh\u00f6rende Zertifikatkette (CA-Chain) einf\u00fcgen. Dies wird ben\u00f6tigt, wenn das Zertifikat nicht direkt von einer der in Browsern mitgeliferten CAs signiert wurde. Die Datei enth\u00e4lt ein oder meherere Zertifikatsbl\u00f6cke, im gleichen Format wie das oben gezeigte Zertifikat.", "lang_certExpireTime": "Zertifikat l\u00e4uft ab", @@ -27,25 +28,23 @@ "lang_httpsApiKeyDescription": "Hier k\u00f6nnen Sie ein API-Token generieren, mit dem Sie das Zertifikat von einem anderen Rechner aus aktualisieren k\u00f6nnen. Um die Funktion zu deaktivieren, l\u00f6schen Sie das Token wieder.", "lang_httpsApiKeyRegenerateConfirm": "Aktuelles Token verwerfen und neu generieren?", "lang_httpsApiPostExample": "Ein Beispiel mittels curl", - "lang_httpsApiPostMaybeInsecure": "Es ist ggf. sinnvoll, zum \u00fcbermitteln die Zertifikatsverifikation abzuschalten, wenn z.B. zu erwarten ist, dass das Zertifikat des Satellitenservers bereits abgelaufen ist, oder selbstsigniert. Bei curl geht das unter Verwendung des Paramters -k", + "lang_httpsApiPostMaybeInsecure": "Es ist ggf. sinnvoll, zum \u00fcbermitteln die Zertifikatsverifikation abzuschalten, wenn z.B. zu erwarten ist, dass das Zertifikat des Satellitenservers bereits abgelaufen ist, oder selbst signiert. Bei curl geht das unter Verwendung des Paramters -k", "lang_httpsApiPostText": "Um ein neues Zertifikat einzuspielen, senden Sie einen POST-Request an die folgende URL, mit den POST-Feldern \"token\" (obiges Token), sowie \"privkey\" (privater Schl\u00fcssel des Zertifikats) und \"cert\" (Zertifikat, ggf. mit angeh\u00e4ngten Intermediates, aka fullchain), beides im PEM-Format.", "lang_httpsCurrentApiKey": "Aktuelles Token", "lang_httpsDescription": "Hier k\u00f6nnen Sie festlegen, ob das Web-Interface auch per HTTPS erreichbar sein soll, und welches Zertifikat daf\u00fcr verwendet werden soll.", "lang_httpsOptionNoChange": "Nichts \u00e4ndern", - "lang_httpsRedirect": "Anfragen per HTTP immer auf HTTPS umleiten (sofern aktiviert)", + "lang_httpsRedirect": "Anfragen per HTTP immer auf HTTPS umleiten", "lang_httpsSettings": "HTTPS-Konfiguration", "lang_installAndRestart": "Zertifikat installieren und Webserver neustarten", "lang_logoBackground": "Hintergrundfarbe des Logos", "lang_moduleHeading": "Web-Schnittstelle", "lang_msgAcmeFailed": "ACME-Abruf fehlgeschlagen", - "lang_noHttps": "HTTPS wieder deaktivieren, aktuelles Zertifikat l\u00f6schen", - "lang_offSelected": "HTTPS ist derzeit deaktiviert.", + "lang_noHttps": "Aktuelles Zertifikat l\u00f6schen, nur internes, selbst signiertes Zertifikat nutzen", "lang_optionAcme": "ACMEv2", "lang_pageTitlePrefix": "Pr\u00e4fix f\u00fcr den Seitentitel", "lang_passwordFields": "Passwortfelder", "lang_passwordsDescription": "Legen Sie fest, ob Passwortfelder in der Web-Schnittstelle maskiert werden, oder ob Ihr Inhalt sichtbar sein soll. Wenn Sie die Schnittstelle in einer sicheren Umgebung nutzen (keine neugierigen Augen), kann dies den Komfort erh\u00f6hen. Das Passwortfeld der Anmeldemaske ist von dieser Einstellung ausgenommen.", "lang_privateKey": "Bitte f\u00fcgen Sie hier den privaten Schl\u00fcssel ein, der zum obigen Zertifikat geh\u00f6rt. Er muss ebenfalls im \"pem\"-Format vorliegen, und sieht wie folgt aus:", - "lang_randomCert": "Neues selbstsigniertes Zertifikat generieren", "lang_redirectDomain": "Bei Browserzugriff \u00fcber eine andere Domain oder per IP auf die Prim\u00e4rdomain des Zertifikats umleiten", "lang_regenerate": "(Re)generieren", "lang_showPasswords": "Passw\u00f6rter anzeigen", diff --git a/modules-available/webinterface/lang/en/messages.json b/modules-available/webinterface/lang/en/messages.json index edccbd47..f938552a 100644 --- a/modules-available/webinterface/lang/en/messages.json +++ b/modules-available/webinterface/lang/en/messages.json @@ -4,8 +4,6 @@ "acme-no-mail": "No technical mail contact specified", "acme-no-provider": "No ACME provider selected", "https-on-cert-missing": "HTTPS is enabled, but the certificate is missing. Please redo the configuration steps.", - "https-used-without-cert": "HTTPS is currently used, but there is no certificate installed. If you tweaked the web server's configuration manually to enable HTTPS bear in mind that a future server update might overwrite your modified configuration without asking.", - "https-want-off-is-used": "HTTPS is currently in use although it is disabled in the settings. Very weird indeed.", "https-want-redirect-is-plain": "HTTP to HTTPS redirects are enabled, but the connection from your browser appears to be unencrypted. Please redo the HTTPS configuration and contact support if the problem persists.", "invalid-domain": "Invalid domain: {{0}}", "mw-acme-errors": "Error renewing\/requesting certificate via ACME" diff --git a/modules-available/webinterface/lang/en/template-tags.json b/modules-available/webinterface/lang/en/template-tags.json index 9c290083..b3afb43f 100644 --- a/modules-available/webinterface/lang/en/template-tags.json +++ b/modules-available/webinterface/lang/en/template-tags.json @@ -9,6 +9,7 @@ "lang_acmeSelected": "Current certificate was generated via ACME.", "lang_acmeWipeAll": "Wipe all existing data and request everything anew", "lang_acmeWipeAllHint": "Select this option if you experience trouble renewing an existing certificate, or if a previous registration attempt left stale data. Please be aware that rate limits apply with some providers, so you shouldn't issue too many requests over a short period of time.", + "lang_apiSelected": "Current certificate was supplied via API access.", "lang_applyingSettings": "Applying settings", "lang_caChain": "Here you can paste an optional certificate chain. It should only be required if you have a certificate that was not directly signed by a certificate authority known by the browsers. It should contain one or more certificate blocks, looking just like the certificate above.", "lang_certExpireTime": "Certificate expires", @@ -32,20 +33,18 @@ "lang_httpsCurrentApiKey": "Current token", "lang_httpsDescription": "Here you can set whether the web interface should be accessible via https. You can choose if you want to use a random self signed certificate, or supply your own.", "lang_httpsOptionNoChange": "Don't change", - "lang_httpsRedirect": "Redirect incoming HTTP requests to HTTPS (if enabled).", + "lang_httpsRedirect": "Redirect incoming HTTP requests to HTTPS", "lang_httpsSettings": "HTTPS settings", "lang_installAndRestart": "Installing certificate and restarting web server", "lang_logoBackground": "Logo background color", "lang_moduleHeading": "Web Interface", "lang_msgAcmeFailed": "ACME failed", - "lang_noHttps": "Disable HTTPS, delete current certificate", - "lang_offSelected": "HTTPS is currently disabled.", + "lang_noHttps": "Delete current certificate, only use internal self-signed certificate", "lang_optionAcme": "ACMEv2", "lang_pageTitlePrefix": "Page title prefix", "lang_passwordFields": "Password fields", "lang_passwordsDescription": "Set whether password fields should be masked or not. The password field of the login page to the web interface is always masked.", "lang_privateKey": "Please paste the private key belonging to the certificate here. It has to be in \"pem\" format too, which should look like this:", - "lang_randomCert": "Generate new self-signed certificate", "lang_redirectDomain": "Redirect browser to certificate's primary domain if accessed via unknown domain name or IP address", "lang_regenerate": "(Re)generate", "lang_showPasswords": "Show passwords", diff --git a/modules-available/webinterface/page.inc.php b/modules-available/webinterface/page.inc.php index a2123ac5..fb982616 100644 --- a/modules-available/webinterface/page.inc.php +++ b/modules-available/webinterface/page.inc.php @@ -45,12 +45,10 @@ class Page_WebInterface extends Page $this->setRedirectFromPost(); $mode = Request::post('mode'); switch ($mode) { + case 'random': case 'off': $taskId = $this->setHttpsOff(); break; - case 'random': - $taskId = $this->setHttpsRandomCert(); - break; case 'custom': $taskId = $this->setHttpsCustomCert(); break; @@ -67,7 +65,7 @@ class Page_WebInterface extends Page } if ($taskId !== null) { Session::set('https-id', $taskId, 1); - Util::redirect('?do=WebInterface&show=httpsupdate'); + Util::redirect('?do=WebInterface&show=httpsupdate&mode=' . $mode); } Util::redirect('?do=WebInterface'); } @@ -96,9 +94,17 @@ class Page_WebInterface extends Page // HTTPS // if (Request::get('show') === 'httpsupdate') { - Render::addTemplate('httpd-restart', array('taskid' => Session::get('https-id'))); + Render::addTemplate('httpd-restart', [ + 'taskid' => Session::get('https-id'), + 'mode' => Request::get('mode', '', 'string'), + ]); } $type = Property::get(WebInterface::PROP_TYPE); + if ($type === 'off') { + // Not really possible anymore to disable HTTPS since we use it for client communication + $type = 'generated'; + Property::set(WebInterface::PROP_TYPE, $type); + } $force = Property::get(WebInterface::PROP_REDIRECT) === 'True'; $hsts = Property::get(WebInterface::PROP_HSTS) === 'True'; $redirdomain = WebInterface::getDomainRedirect(); @@ -117,36 +123,19 @@ class Page_WebInterface extends Page Render::addTemplate('acme-error', ['error' => $err]); } } - if ($type === 'off') { - if ($exists) { - // HTTPS is set to off, but a certificate exists - if ($https) { - // User is using https, just warn to prevent lockout - Message::addWarning('https-want-off-is-used'); - } else { - // User is not using https, try to delete stray certificate - $this->setHttpsOff(); - } - } elseif ($https) { - // Set to off, no cert found, but still using HTTPS apparently - // Admin might have modified web server config in another way - Message::addWarning('https-used-without-cert'); - } - } elseif ($type === 'generated' || $type === 'supplied' || $type === 'acme' || $type === 'api') { - $data['httpsEnabled'] = true; + if ($type === 'generated' || $type === 'supplied' || $type === 'acme' || $type === 'api') { if ($force && !$https) { Message::addWarning('https-want-redirect-is-plain'); } - if (!$exists) { + if ($type !== 'generated' && !$exists) { Message::addWarning('https-on-cert-missing'); } } else { // Unknown config - maybe upgraded old install that doesn't keep track if ($exists || $https) { $type = 'unknown'; // Legacy fallback - $data['httpsEnabled'] = true; } else { - $type = 'off'; + $type = 'generated'; } } $domains = implode("\n", Acme::getDomains()); @@ -171,23 +160,21 @@ class Page_WebInterface extends Page // $type might have changed in above block $data[$type . 'Selected'] = true; // Show cert info if possible - if ($type !== 'off') { - $data['certDomains'] = []; - $exp = 0; - $iss = ''; - if (WebInterface::extractCurrentCertData($data['certDomains'], $exp, $iss)) { - $data['certExpire'] = Util::prettyTime($exp); - $data['certIssuer'] = $iss; - $diff = $exp - time(); - $class = []; - if ($diff < 86400 * 3) { - $class[] = 'text-danger'; - } - if ($diff < 86400 * 10) { - $class[] = 'slx-bold'; - } - $data['certExpireClass'] = implode(' ', $class); + $data['certDomains'] = []; + $exp = 0; + $iss = ''; + if (WebInterface::extractCurrentCertData($data['certDomains'], $exp, $iss)) { + $data['certExpire'] = Util::prettyTime($exp); + $data['certIssuer'] = $iss; + $diff = $exp - time(); + $class = []; + if ($diff < 86400 * 3) { + $class[] = 'text-danger'; + } + if ($diff < 86400 * 10) { + $class[] = 'slx-bold'; } + $data['certExpireClass'] = implode(' ', $class); } $data['httpsApiKeyPostUrl'] = ($https ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/slx-admin/api.php?do=webinterface'; Permission::addGlobalTags($data['perms'], null, ['edit.https']); @@ -238,16 +225,9 @@ class Page_WebInterface extends Page private function setHttpsOff(): ?string { - Header('Strict-Transport-Security: max-age=0', true); - Session::deleteCookie(); return WebInterface::tmDisableHttps(); } - private function setHttpsRandomCert(): ?string - { - return WebInterface::tmGenerateRandomCert(); - } - private function setHttpsCustomCert(): ?string { $cert = trim(Request::post('certificate', Request::REQUIRED, 'string')); @@ -257,7 +237,7 @@ class Page_WebInterface extends Page $cert .= "\n" . $chain; } return WebInterface::tmImportCustomCert($key . "\n", $cert . "\n", 'supplied', - 'New certificate uploaded by ' . User::getLogin()); + 'Applying uploaded HTTPS certificate'); } private function setAcmeMode(): ?string diff --git a/modules-available/webinterface/templates/https.html b/modules-available/webinterface/templates/https.html index b109fa9d..a93b8fb8 100644 --- a/modules-available/webinterface/templates/https.html +++ b/modules-available/webinterface/templates/https.html @@ -9,9 +9,6 @@ <p>{{lang_youreUsingHttps}}</p> {{/httpsUsed}} <div class="text-info slx-bold"> - {{#offSelected}} - <p>{{lang_offSelected}}</p> - {{/offSelected}} {{#unknownSelected}} <p>{{lang_unknownSelected}}</p> {{/unknownSelected}} @@ -111,7 +108,7 @@ </span> </div> - {{#httpsEnabled}} + {{^generatedSelected}} <div class="input-group row-select"> <span class="input-group-addon"> <span class="radio"> @@ -123,19 +120,7 @@ {{lang_noHttps}} </span> </div> - {{/httpsEnabled}} - - <div class="input-group row-select"> - <span class="input-group-addon"> - <span class="radio"> - <input id="mrandom" type="radio" name="mode" value="random" {{perms.edit.https.disabled}}> - <label></label> - </span> - </span> - <span class="form-control"> - {{lang_randomCert}} - </span> - </div> + {{/generatedSelected}} <div class="input-group row-select"> <span class="input-group-addon"> |