summaryrefslogtreecommitdiffstats
path: root/modules-available/webinterface/page.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/webinterface/page.inc.php')
-rw-r--r--modules-available/webinterface/page.inc.php184
1 files changed, 139 insertions, 45 deletions
diff --git a/modules-available/webinterface/page.inc.php b/modules-available/webinterface/page.inc.php
index ca52c2ab..35f21b38 100644
--- a/modules-available/webinterface/page.inc.php
+++ b/modules-available/webinterface/page.inc.php
@@ -3,10 +3,6 @@
class Page_WebInterface extends Page
{
- const PROP_REDIRECT = 'webinterface.https-redirect';
- const PROP_TYPE = 'webinterface.https-type';
- const PROP_HSTS = 'webinterface.https-hsts';
-
protected function doPreprocess()
{
User::load();
@@ -27,6 +23,7 @@ class Page_WebInterface extends Page
User::assertPermission("edit.design");
$this->actionCustomization();
break;
+ default:
}
if (Request::isPost()) {
Util::redirect('?do=webinterface');
@@ -38,24 +35,28 @@ class Page_WebInterface extends Page
{
$mode = Request::post('mode');
switch ($mode) {
- case 'off':
- $task = $this->setHttpsOff();
- break;
- case 'random':
- $task = $this->setHttpsRandomCert();
- break;
- case 'custom':
- $task = $this->setHttpsCustomCert();
- break;
- default:
- $task = $this->setRedirectMode();
- break;
+ case 'off':
+ $taskId = $this->setHttpsOff();
+ break;
+ case 'random':
+ $taskId = $this->setHttpsRandomCert();
+ break;
+ case 'custom':
+ $taskId = $this->setHttpsCustomCert();
+ break;
+ case 'acme':
+ $taskId = $this->setAcmeMode();
+ break;
+ default:
+ $taskId = $this->setRedirectMode();
+ break;
}
if ($mode !== 'off') {
- Property::set(self::PROP_HSTS, Request::post('usehsts', false, 'string') === 'on' ? 'True' : 'False');
+ Property::set(WebInterface::PROP_HSTS, Request::post('usehsts', false, 'string') === 'on' ? 'True' : 'False');
+ WebInterface::setDomainRedirect(Request::post('redirdomain', false, 'string') === 'on');
}
- if (isset($task['id'])) {
- Session::set('https-id', $task['id']);
+ if ($taskId !== null) {
+ Session::set('https-id', $taskId, 1);
Util::redirect('?do=WebInterface&show=httpsupdate');
}
Util::redirect('?do=WebInterface');
@@ -70,7 +71,7 @@ class Page_WebInterface extends Page
private function actionCustomization()
{
$prefix = Request::post('prefix', '', 'string');
- if (!empty($prefix) && !preg_match('/[\]\)\}\-_\s\&\$\!\/\+\*\^\>]$/', $prefix)) {
+ if (!empty($prefix) && !preg_match('/[)}\]\-_\s&$!\/+*^>]$/', $prefix)) {
$prefix .= ' ';
}
Property::set('page-title-prefix', $prefix);
@@ -87,17 +88,25 @@ class Page_WebInterface extends Page
if (Request::get('show') === 'httpsupdate') {
Render::addTemplate('httpd-restart', array('taskid' => Session::get('https-id')));
}
- $type = Property::get(self::PROP_TYPE);
- $force = Property::get(self::PROP_REDIRECT) === 'True';
- $hsts = Property::get(self::PROP_HSTS) === 'True';
+ $type = Property::get(WebInterface::PROP_TYPE);
+ $force = Property::get(WebInterface::PROP_REDIRECT) === 'True';
+ $hsts = Property::get(WebInterface::PROP_HSTS) === 'True';
+ $redirdomain = WebInterface::getDomainRedirect();
$https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
$exists = file_exists('/etc/lighttpd/server.pem');
$data = array(
'httpsUsed' => $https,
'redirect_checked' => ($force ? 'checked' : ''),
- 'hsts_checked' => ($hsts ? 'checked' : '')
+ 'hsts_checked' => ($hsts ? 'checked' : ''),
+ 'redirdomain_checked' => ($redirdomain ? 'checked' : ''),
);
- // Type should be 'off', 'generated', 'supplied'
+ // Type should be 'off', 'generated', 'supplied' or 'acme'
+ if ($type === 'acme') {
+ $err = Acme::getLastError();
+ if (!empty($err)) {
+ Render::addTemplate('acme-error', ['error' => $err]);
+ }
+ }
if ($type === 'off') {
if ($exists) {
// HTTPS is set to off, but a certificate exists
@@ -113,7 +122,7 @@ class Page_WebInterface extends Page
// Admin might have modified web server config in another way
Message::addWarning('https-used-without-cert');
}
- } elseif ($type === 'generated' || $type === 'supplied') {
+ } elseif ($type === 'generated' || $type === 'supplied' || $type === 'acme') {
$data['httpsEnabled'] = true;
if ($force && !$https) {
Message::addWarning('https-want-redirect-is-plain');
@@ -125,21 +134,59 @@ class Page_WebInterface extends Page
// Unknown config - maybe upgraded old install that doesn't keep track
if ($exists || $https) {
$type = 'unknown'; // Legacy fallback
+ $data['httpsEnabled'] = true;
} else {
$type = 'off';
}
}
+ $domains = implode("\n", Acme::getDomains());
+ if (empty($domains)) {
+ $domains = $_SERVER['HTTP_HOST'];
+ }
+ $data['acmeProviders'] = [];
+ foreach (Acme::getProviders() as $id => $name) {
+ $data['acmeProviders'][] = [
+ 'id' => $id,
+ 'name' => $name,
+ 'selected' => $id === Acme::getProvider() ? 'selected' : '',
+ ];
+ }
+ $data['acmeMail'] = Acme::getMail();
+ $data['acmeDomains'] = $domains;
+ $data['acmeKeyId'] = Acme::getKeyId();
+ $data['acmeHmacKey'] = Acme::getHmacKey();
+ // $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);
+ }
+ }
Permission::addGlobalTags($data['perms'], null, ['edit.https']);
Render::addTemplate('https', $data);
//
// Password fields
//
$data = array();
- if (Property::getPasswordFieldType() === 'text')
+ if (Property::getPasswordFieldType() === 'text') {
$data['selected_show'] = 'checked';
- else
+ } else {
$data['selected_hide'] = 'checked';
+ }
Permission::addGlobalTags($data['perms'], null, ['edit.password']);
Render::addTemplate('passwords', $data);
//
@@ -164,52 +211,99 @@ class Page_WebInterface extends Page
Render::addTemplate('customization', $data);
}
- private function setHttpsOff()
+ private function setHttpsOff(): ?string
{
- Property::set(self::PROP_TYPE, 'off');
- Property::set(self::PROP_HSTS, 'off');
+ Property::set(WebInterface::PROP_TYPE, 'off');
+ Property::set(WebInterface::PROP_HSTS, 'off');
Header('Strict-Transport-Security: max-age=0', true);
Session::deleteCookie();
- return Taskmanager::submit('LighttpdHttps', array());
+ $task = Taskmanager::submit('LighttpdHttps', array());
+ return $task['id'] ?? null;
}
- private function setHttpsRandomCert()
+ private function setHttpsRandomCert(): ?string
{
$force = Request::post('httpsredirect', false, 'string') === 'on';
- Property::set(self::PROP_TYPE, 'generated');
- Property::set(self::PROP_REDIRECT, $force ? 'True' : 'False');
- return Taskmanager::submit('LighttpdHttps', array(
+ Property::set(WebInterface::PROP_TYPE, 'generated');
+ Property::set(WebInterface::PROP_REDIRECT, $force ? 'True' : 'False');
+ $task = Taskmanager::submit('LighttpdHttps', array(
'proxyip' => Property::getServerIp(),
'redirect' => $force,
));
+ return $task['id'] ?? null;
}
- private function setHttpsCustomCert()
+ private function setHttpsCustomCert(): ?string
{
$force = Request::post('httpsredirect', false, 'string') === 'on';
- Property::set(self::PROP_TYPE, 'supplied');
- Property::set(self::PROP_REDIRECT, $force ? 'True' : 'False');
- return Taskmanager::submit('LighttpdHttps', array(
+ Property::set(WebInterface::PROP_TYPE, 'supplied');
+ Property::set(WebInterface::PROP_REDIRECT, $force ? 'True' : 'False');
+ $task = Taskmanager::submit('LighttpdHttps', array(
'importcert' => Request::post('certificate', 'bla'),
'importkey' => Request::post('privatekey', 'bla'),
'importchain' => Request::post('cachain', ''),
'redirect' => $force,
));
+ return $task['id'] ?? null;
+ }
+
+ private function setAcmeMode(): ?string
+ {
+ $force = Request::post('httpsredirect', false, 'string') === 'on';
+ Property::set(WebInterface::PROP_TYPE, 'acme');
+ Property::set(WebInterface::PROP_REDIRECT, $force ? 'True' : 'False');
+ $wipeAll = Request::post('acme-wipe-all', false, 'bool');
+ // Get params
+ $provider = Request::post('acme-provider', Request::REQUIRED, 'string');
+ $mail = Request::post('acme-mail', Request::REQUIRED, 'string');
+ $domains = Request::post('acme-domains', Request::REQUIRED, 'string');
+ $kid = Request::post('acme-kid', null, 'string');
+ $hmac = Request::post('acme-hmac-key', null, 'string');
+ // Check domains
+ $domains = preg_split('/[\r\n\s]+/', strtolower($domains), 0, PREG_SPLIT_NO_EMPTY);
+ $err = false;
+ foreach ($domains as $domain) {
+ if (!preg_match('/^[a-z0-9_.-]+$/', $domain)) {
+ Message::addError('invalid-domain', $domain);
+ $err = true;
+ }
+ }
+ unset($domain);
+ if ($err)
+ return null;
+ // First, try to revive existing config/certs if parameters didn't change
+ if (!$wipeAll
+ && $provider === Acme::getProvider()
+ && $mail === Acme::getMail()
+ && $kid === Acme::getKeyId()
+ && $hmac === Acme::getHmacKey()
+ && count($domains) === count(Acme::getDomains())
+ && empty(array_diff($domains, Acme::getDomains()))) {
+ if (Acme::tryEnable())
+ return null; // Nothing to do, old setup works
+ error_log('FUUUU');
+ return Acme::renew(); // Hope for the best, otherwise user needs to check "force reissue"
+ }
+ if (!Acme::setConfig($provider, $mail, $kid, $hmac))
+ return null; // Will generate error messages in this case
+ Acme::setDomains($domains);
+ return Acme::issueNewCertificate($wipeAll);
}
- private function setRedirectMode()
+ private function setRedirectMode(): ?string
{
$force = Request::post('httpsredirect', false, 'string') === 'on';
- Property::set(self::PROP_REDIRECT, $force ? 'True' : 'False');
- if (Property::get(self::PROP_TYPE) === 'off') {
+ Property::set(WebInterface::PROP_REDIRECT, $force ? 'True' : 'False');
+ if (Property::get(WebInterface::PROP_TYPE) === 'off') {
// Don't bother running the task if https isn't enabled - just
// update the state in DB
- return false;
+ return null;
}
- return Taskmanager::submit('LighttpdHttps', array(
+ $task = Taskmanager::submit('LighttpdHttps', array(
'redirectOnly' => true,
'redirect' => $force,
));
+ return $task['id'] ?? null;
}
}