68 lines
3.0 KiB
PHP
68 lines
3.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Sicherung des System-Updates.
|
|
*
|
|
* Ein Update ersetzt Programmcode. Würde das Konto beim Update-Server übernommen, könnten sonst Schadcode-Updates an
|
|
* alle Installationen gehen. Deshalb prüft DeskHub bei hinterlegtem Herausgeber-Schlüssel (includes/catalog_defaults.php)
|
|
* eine Signatur: Der Herausgeber signiert jedes Release-Paket mit seinem privaten Schlüssel (tools/release-sign.php),
|
|
* ohne passende Signatur wird nichts installiert. Der Schlüssel ist derselbe wie bei Plugins und Themes.
|
|
*
|
|
* Release-Dateien (Anhänge des Releases): deskhub-<Version>.zip und deskhub-<Version>.zip.sig
|
|
*/
|
|
|
|
/** Wird für Updates eine Herausgeber-Signatur verlangt? Ja, sobald ein Herausgeber-Schlüssel eingebaut ist. */
|
|
function update_signature_required(): bool
|
|
{
|
|
return function_exists('plugin_publisher_key') && plugin_publisher_key() !== '';
|
|
}
|
|
|
|
/** Zu signierende Nachricht: bindet Signatur an Version und Dateiinhalt. */
|
|
function update_signature_message(string $tag, string $sha256): string
|
|
{
|
|
return "deskhub-update\n" . ltrim(trim($tag), 'vV') . "\n" . strtolower($sha256);
|
|
}
|
|
|
|
/** Prüft die Signatur eines heruntergeladenen Pakets. Gibt null bei Erfolg zurück, sonst eine Fehlermeldung. */
|
|
function update_verify_package(string $tag, string $zipPath, string $signature): ?string
|
|
{
|
|
$signature = trim($signature);
|
|
if ($signature === '') return 'Dem Release fehlt die Signatur des Herausgebers.';
|
|
$key = plugin_publisher_key();
|
|
if ($key === '') return 'Es ist kein Herausgeber-Schlüssel hinterlegt, die Signatur kann nicht geprüft werden.';
|
|
$sha = hash_file('sha256', $zipPath);
|
|
if ($sha === false) return 'Das Paket konnte nicht gelesen werden.';
|
|
if (!plugin_verify_signature(update_signature_message($tag, $sha), $signature, $key)) {
|
|
return 'Die Signatur ist ungültig. Das Paket wurde verändert oder stammt nicht vom Herausgeber. Es wird nicht installiert.';
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Sucht in den Anhängen eines Releases (Gitea-API) das Paket und die Signatur.
|
|
*
|
|
* @return array{zip: ?string, sig: ?string} Download-Adressen oder null
|
|
*/
|
|
function update_find_assets(array $release, string $tag): array
|
|
{
|
|
$version = ltrim(trim($tag), 'vV');
|
|
$names = ['zip' => "deskhub-{$version}.zip", 'sig' => "deskhub-{$version}.zip.sig"];
|
|
$out = ['zip' => null, 'sig' => null];
|
|
foreach ((array) ($release['assets'] ?? []) as $asset) {
|
|
$name = (string) ($asset['name'] ?? '');
|
|
$url = (string) ($asset['browser_download_url'] ?? '');
|
|
foreach ($names as $kind => $expected) {
|
|
if ($name === $expected && str_starts_with($url, 'https://')) $out[$kind] = $url;
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
/** Kopfzeilen für Abrufe beim Update-Server; ein Zugangstoken ist nur nötig, wenn das Repository nicht öffentlich ist. */
|
|
function update_http_headers(): array
|
|
{
|
|
$token = (string) (config()['update']['token'] ?? '');
|
|
return $token !== '' ? ['Authorization: token ' . $token] : [];
|
|
}
|