Version 2.8.14: Diagnose in der Bildschirmsitzung, Vorauswahl ohne Passwort

This commit is contained in:
alientim committed 2026-09-13 11:31:42 +02:00
1 parent 0c47e1d645
commit f551ce0ee6
3 files changed
+79 -3

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "tesm-core" name = "tesm-core"
version = "2.8.5" version = "2.8.6"
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver" description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
@@ -11,6 +11,25 @@
import RFB from "../vendor/novnc/core/rfb.js"; import RFB from "../vendor/novnc/core/rfb.js";
// Sicherheitsverfahren, die ohne Zugangsdaten auskommen. Bietet der Server
// eines davon an und haben wir keine, nehmen wir es -- auch wenn der Server
// ein anderes zuerst nennt.
//
// Warum das noetig ist: noVNC waehlt "das erste, das ich kann, in der
// Reihenfolge des Servers". Ein RealVNC Server nennt RA2ne vor "ohne
// Authentifizierung"; der Browser liefe also in eine Passwortabfrage, obwohl
// daneben ein Weg offensteht, den auch der RealVNC Viewer nimmt. Wer ein
// Passwort hinterlegt hat, behaelt die Reihenfolge des Servers -- dann ist
// der angemeldete Weg der bessere.
const OHNE_ZUGANGSDATEN = new Set([1]);
// Der Eingriff sitzt in einer privaten Methode der mitgelieferten Bibliothek.
// Das ist bewusst hier und nicht in der Bibliothek selbst: eine neue Fassung
// von noVNC laesst sich dann austauschen, ohne eine Aenderung nachzupflegen --
// faellt die Methode weg, greift die Vorauswahl nicht mehr, und die Sitzung
// laeuft wieder wie ohne sie. Kein stiller Bruch.
const istUnterstuetzt = RFB.prototype._isSupportedSecurityType;
const wurzel = document.getElementById("screen"); const wurzel = document.getElementById("screen");
if (wurzel) { if (wurzel) {
starten(wurzel); starten(wurzel);
@@ -35,14 +54,58 @@ function starten(wurzel) {
); );
let rfb = null; let rfb = null;
let letzterFehler = "";
function melden(text, art = "") { function melden(text, art = "") {
zeile.textContent = text; zeile.textContent = text;
zeile.className = `screen__status${art ? " screen__status--" + art : ""}`; zeile.className = `screen__status${art ? " screen__status--" + art : ""}`;
} }
// noVNC meldet den *Grund* eines Fehlschlags ausschliesslich ins Protokoll
// der Entwicklerkonsole -- das Ereignis "disconnect" trägt ihn nicht. Ohne
// diesen Griff bliebe der Seite nur "Verbindung abgebrochen", und damit
// steht der Anwender genau dort, wo er ohne die ganze Anzeige auch stuende.
// Darum wird die Fehlerausgabe waehrend der Sitzung mitgelesen -- und
// hinterher wieder losgelassen.
const echteAusgabe = console.error.bind(console);
console.error = (...teile) => {
letzterFehler = teile.map((teil) => String(teil)).join(" ");
echteAusgabe(...teile);
};
window.addEventListener("beforeunload", () => {
console.error = echteAusgabe;
});
function grund() {
const teile = [];
if (letzterFehler) {
teile.push(letzterFehler.replace(/^Failed (when|while) \w+: /, ""));
}
if (rfb && rfb._rfbAuthScheme > 0) {
teile.push(`gewähltes Verfahren: ${rfb._rfbAuthScheme}`);
}
return teile.join(" · ");
}
function verbinden(zugang) { function verbinden(zugang) {
melden("Verbindung wird aufgebaut …"); melden("Verbindung wird aufgebaut …");
letzterFehler = "";
// Vorauswahl nur, wenn wir nichts anzubieten haben: dann zaehlt der Weg,
// der ohne Zugangsdaten auskommt -- sofern der Server ihn anbietet.
const hatZugangsdaten = Boolean(zugang && (zugang.password || zugang.username));
const angeboten = (wurzel.dataset.verfahren || "")
.split(",")
.map((wert) => parseInt(wert, 10))
.filter((wert) => !Number.isNaN(wert));
const ohnePasswortMoeglich = angeboten.some((wert) => OHNE_ZUGANGSDATEN.has(wert));
RFB.prototype._isSupportedSecurityType = function (typ) {
if (!hatZugangsdaten && ohnePasswortMoeglich) {
return OHNE_ZUGANGSDATEN.has(typ);
}
return istUnterstuetzt.call(this, typ);
};
rfb = new RFB(leinwand, adresse, { rfb = new RFB(leinwand, adresse, {
credentials: zugang, credentials: zugang,
// Eine Bildschirmsitzung soll nicht nebenbei die Zwischenablage des // Eine Bildschirmsitzung soll nicht nebenbei die Zwischenablage des
@@ -69,9 +132,12 @@ function starten(wurzel) {
if (ereignis.detail && ereignis.detail.clean) { if (ereignis.detail && ereignis.detail.clean) {
melden("Sitzung beendet."); melden("Sitzung beendet.");
} else { } else {
const erklaerung = grund();
melden( melden(
"Verbindung abgebrochen. Antwortet der VNC-Server noch, und lässt der " + erklaerung
"Arbeitsplatz die Verbindung zu?", ? `Verbindung abgebrochen – ${erklaerung}`
: "Verbindung abgebrochen, ohne dass der Client einen Grund nennt. " +
"Antwortet der VNC-Server noch?",
"fehler", "fehler",
); );
} }
@@ -20,6 +20,16 @@ der einen Bildschirm fernsteuert.
Datei -- mit Grund und Fundstelle, damit ein Wechsel auf eine neuere Fassung Datei -- mit Grund und Fundstelle, damit ein Wechsel auf eine neuere Fassung
nicht stillschweigend darueberlaeuft. nicht stillschweigend darueberlaeuft.
**Was TESM von aussen umbiegt** (also *nicht* in diesen Dateien steht, sondern
in `js/screen.js`): `RFB.prototype._isSupportedSecurityType` wird ueberschrieben,
solange keine Zugangsdaten vorliegen und der Server ein Verfahren ohne
Anmeldung anbietet. Grund: noVNC nimmt "das erste, das ich kann, in der
Reihenfolge des Servers"; ein RealVNC Server nennt RA2ne vor "ohne
Authentifizierung", und der Browser liefe in eine Passwortabfrage, obwohl
daneben der Weg offensteht, den auch der RealVNC Viewer nimmt. Faellt die
Methode in einer neueren Fassung weg, greift die Vorauswahl nicht mehr -- die
Sitzung laeuft dann wie ohne sie, es bricht nichts.
**Was noVNC an Sicherheitsverfahren spricht** (`core/rfb.js`, **Was noVNC an Sicherheitsverfahren spricht** (`core/rfb.js`,
`_isSupportedSecurityType`): `1` None, `2` VNC-Passwort, `6` RA2ne (RSA-AES `_isSupportedSecurityType`): `1` None, `2` VNC-Passwort, `6` RA2ne (RSA-AES
ohne Streckenverschluesselung), `16` Tight, `19` VeNCrypt, `22` xvp, `30` ARD, ohne Streckenverschluesselung), `16` Tight, `19` VeNCrypt, `22` xvp, `30` ARD,