68 lines
4.9 KiB
PHP
68 lines
4.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Prüft, wie die Anmeldung der Apps aus den Anfrage-Kopfzeilen gelesen wird. Viele Hoster (Apache mit PHP-FPM, z. B. Plesk)
|
|
* reichen "Authorization" nicht an PHP weiter: Dann muss der Ersatz-Header "X-DeskHub-Authorization" genügen.
|
|
*/
|
|
|
|
putenv('DESKHUB_SQLITE_PATH=:memory:');
|
|
require_once dirname(__DIR__) . '/api/staff/v1/common.php';
|
|
|
|
$failures = [];
|
|
$check = function (bool $ok, string $what) use (&$failures): void {
|
|
if (!$ok) $failures[] = $what;
|
|
};
|
|
$token = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
|
|
$other = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
|
|
$reset = function (array $server): void {
|
|
foreach (['HTTP_AUTHORIZATION', 'REDIRECT_HTTP_AUTHORIZATION', 'HTTP_X_DESKHUB_AUTHORIZATION'] as $k) unset($_SERVER[$k]);
|
|
foreach ($server as $k => $v) $_SERVER[$k] = $v;
|
|
};
|
|
|
|
$reset(['HTTP_AUTHORIZATION' => "Bearer {$token}"]);
|
|
$check(api_bearer_token() === $token, 'normaler Authorization-Header wird gelesen');
|
|
$reset(['REDIRECT_HTTP_AUTHORIZATION' => "Bearer {$token}"]);
|
|
$check(api_bearer_token() === $token, 'Authorization über REDIRECT_HTTP_AUTHORIZATION (Apache-Umleitung) wird gelesen');
|
|
$reset(['HTTP_X_DESKHUB_AUTHORIZATION' => "Bearer {$token}"]);
|
|
$check(api_bearer_token() === $token, 'Ersatz-Header X-DeskHub-Authorization genügt, wenn Authorization fehlt (Plesk/FPM)');
|
|
$reset(['HTTP_AUTHORIZATION' => "Bearer {$token}", 'HTTP_X_DESKHUB_AUTHORIZATION' => "Bearer {$other}"]);
|
|
$check(api_bearer_token() === $token, 'ist beides vorhanden, gilt Authorization');
|
|
$reset(['HTTP_AUTHORIZATION' => '', 'HTTP_X_DESKHUB_AUTHORIZATION' => "Bearer {$token}"]);
|
|
$check(api_bearer_token() === $token, 'leerer Authorization-Header fällt auf den Ersatz-Header zurück');
|
|
$reset([]);
|
|
$check(api_bearer_token() === null && api_authorization_header() === '', 'ohne Header: kein Token');
|
|
$reset(['HTTP_X_DESKHUB_AUTHORIZATION' => 'Basic abc']);
|
|
$check(api_bearer_token() === null, 'kein Bearer-Schema: abgelehnt');
|
|
$reset(['HTTP_X_DESKHUB_AUTHORIZATION' => 'Bearer kurz']);
|
|
$check(api_bearer_token() === null, 'zu kurzes Token: abgelehnt');
|
|
$reset(['HTTP_X_DESKHUB_AUTHORIZATION' => "Bearer {$token}\r\nX-Evil: 1"]);
|
|
$check(api_bearer_token() === null, 'eingeschleuste Zeilenumbrüche: abgelehnt');
|
|
|
|
// Klartext aus HTML (Signaturen und Nachrichten in den Apps): Blöcke bleiben getrennt
|
|
$check(api_plain_text('<p>Liebe Grüße<br>Lukas</p><div>Inhaber Windelweb</div><div>Zweite Zeile</div>') === "Liebe Grüße\nLukas\n\nInhaber Windelweb\nZweite Zeile", 'Klartext: Absätze und div-Blöcke bleiben getrennt: ' . json_encode(api_plain_text('<p>Liebe Grüße<br>Lukas</p><div>Inhaber Windelweb</div><div>Zweite Zeile</div>')));
|
|
$check(api_plain_text('<ul><li>Eins</li><li>Zwei</li></ul>') === "• Eins\n• Zwei", 'Klartext: Listenpunkte');
|
|
$check(api_plain_text("<p>A</p><p></p><p></p><p>B</p>") === "A\n\nB", 'Klartext: höchstens eine Leerzeile');
|
|
$check(api_plain_text('<p>Text & mehr <b></p>') === 'Text & mehr <b>', 'Klartext: Entities werden aufgelöst');
|
|
$check(api_plain_text(null) === '' && api_plain_text('') === '', 'Klartext: leer');
|
|
// Klartext aus HTML (Signaturen und Nachrichten in den Apps): Blöcke bleiben getrennt
|
|
$check(api_plain_text('<p>Liebe Grüße<br>Lukas</p><div>Inhaber Windelweb</div><div>Zweite Zeile</div>') === "Liebe Grüße\nLukas\n\nInhaber Windelweb\nZweite Zeile", 'Klartext: Absätze und div-Blöcke bleiben getrennt: ' . json_encode(api_plain_text('<p>Liebe Grüße<br>Lukas</p><div>Inhaber Windelweb</div><div>Zweite Zeile</div>')));
|
|
$check(api_plain_text('<ul><li>Eins</li><li>Zwei</li></ul>') === "• Eins\n• Zwei", 'Klartext: Listenpunkte');
|
|
$check(api_plain_text("<p>A</p><p></p><p></p><p>B</p>") === "A\n\nB", 'Klartext: höchstens eine Leerzeile');
|
|
$check(api_plain_text('<p>Text & mehr <b></p>') === 'Text & mehr <b>', 'Klartext: Entities werden aufgelöst');
|
|
$check(api_plain_text(null) === '' && api_plain_text('') === '', 'Klartext: leer');
|
|
// Anwendungs-Code der Apps sendet den Ersatz-Header
|
|
$desktop = (string) @file_get_contents(dirname(__DIR__, 2) . '/desktop/src/main.js');
|
|
if ($desktop !== '') $check(str_contains($desktop, "X-DeskHub-Authorization"), 'Windows-App sendet den Ersatz-Header');
|
|
$android = (string) @file_get_contents(dirname(__DIR__, 2) . '/mobile/src/main/java/de/deskhub/staff/data/remote/DeskHubApi.kt');
|
|
if ($android !== '') $check(substr_count($android, 'X-DeskHub-Authorization') >= 2, 'Android-App sendet den Ersatz-Header (Anfragen und Bild-Upload)');
|
|
// Apache-Regeln
|
|
$htaccess = (string) file_get_contents(dirname(__DIR__) . '/.htaccess');
|
|
$check(str_contains($htaccess, 'E=HTTP_AUTHORIZATION:%{HTTP:Authorization}') && str_contains($htaccess, 'CGIPassAuth On'), '.htaccess reicht den Authorization-Header an PHP weiter');
|
|
|
|
if ($failures) {
|
|
fwrite(STDERR, "FEHLER:\n- " . implode("\n- ", $failures) . "\n");
|
|
exit(1);
|
|
}
|
|
echo "API auth header checks passed.\n";
|