Version 2.8.14: Diagnose in der Bildschirmsitzung, Vorauswahl ohne Passwort
This commit is contained in:
1 parent
436b080deb
commit
f3b312046f
10 files changed
+116
-6
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
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"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -11,6 +11,25 @@
|
||||
|
||||
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");
|
||||
if (wurzel) {
|
||||
starten(wurzel);
|
||||
@@ -35,14 +54,58 @@ function starten(wurzel) {
|
||||
);
|
||||
|
||||
let rfb = null;
|
||||
let letzterFehler = "";
|
||||
|
||||
function melden(text, art = "") {
|
||||
zeile.textContent = text;
|
||||
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) {
|
||||
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, {
|
||||
credentials: zugang,
|
||||
// Eine Bildschirmsitzung soll nicht nebenbei die Zwischenablage des
|
||||
@@ -69,9 +132,12 @@ function starten(wurzel) {
|
||||
if (ereignis.detail && ereignis.detail.clean) {
|
||||
melden("Sitzung beendet.");
|
||||
} else {
|
||||
const erklaerung = grund();
|
||||
melden(
|
||||
"Verbindung abgebrochen. Antwortet der VNC-Server noch, und lässt der " +
|
||||
"Arbeitsplatz die Verbindung zu?",
|
||||
erklaerung
|
||||
? `Verbindung abgebrochen – ${erklaerung}`
|
||||
: "Verbindung abgebrochen, ohne dass der Client einen Grund nennt. " +
|
||||
"Antwortet der VNC-Server noch?",
|
||||
"fehler",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,16 @@ der einen Bildschirm fernsteuert.
|
||||
Datei -- mit Grund und Fundstelle, damit ein Wechsel auf eine neuere Fassung
|
||||
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`,
|
||||
`_isSupportedSecurityType`): `1` None, `2` VNC-Passwort, `6` RA2ne (RSA-AES
|
||||
ohne Streckenverschluesselung), `16` Tight, `19` VeNCrypt, `22` xvp, `30` ARD,
|
||||
|
||||
Reference in new issue
Block a user