Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
270ba455a8 | ||
|
|
f3b312046f |
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm"
|
name = "tesm"
|
||||||
version = "2.8.13"
|
version = "2.8.15"
|
||||||
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -424,7 +424,11 @@ def vnc_connection(device_id: int):
|
|||||||
f"Verbindungsdatei für {ziel}:{port}",
|
f"Verbindungsdatei für {ziel}:{port}",
|
||||||
)
|
)
|
||||||
return Response(
|
return Response(
|
||||||
vnc.verbindungsdatei(device, port=port),
|
vnc.verbindungsdatei(
|
||||||
|
device,
|
||||||
|
port=port,
|
||||||
|
warnung_aus=bool(extension.settings.get(conn, "vnc_warn_unencrypted_off")),
|
||||||
|
),
|
||||||
mimetype="application/octet-stream",
|
mimetype="application/octet-stream",
|
||||||
headers={
|
headers={
|
||||||
"Content-Disposition": f'attachment; filename="{vnc.dateiname(device)}"',
|
"Content-Disposition": f'attachment; filename="{vnc.dateiname(device)}"',
|
||||||
|
|||||||
@@ -138,6 +138,26 @@ def init_app(app) -> None: # type: ignore[no-untyped-def]
|
|||||||
def screen_socket(ws, device_id: int): # type: ignore[no-untyped-def]
|
def screen_socket(ws, device_id: int): # type: ignore[no-untyped-def]
|
||||||
_strecke(ws, device_id)
|
_strecke(ws, device_id)
|
||||||
|
|
||||||
|
@sock.route("/ws/probe")
|
||||||
|
def probe_socket(ws): # type: ignore[no-untyped-def]
|
||||||
|
"""Sagt "da", und mehr nicht.
|
||||||
|
|
||||||
|
Wozu: bricht eine Bildschirmsitzung ab, gibt es zwei sehr verschiedene
|
||||||
|
Ursachen -- der VNC-Server mag nicht, oder die WebSocket-Verbindung
|
||||||
|
kommt gar nicht erst durch (ein Proxy zwischen Browser und TESM, der
|
||||||
|
"Upgrade" nicht weiterreicht, ist der haeufigste Fall). Von aussen
|
||||||
|
sehen beide gleich aus: ein Abbruch ohne Grund. Diese Probe trennt
|
||||||
|
sie, ohne dass jemand ein Protokoll lesen muss.
|
||||||
|
"""
|
||||||
|
if not current_user.is_authenticated:
|
||||||
|
ws.close(1008, "Nicht angemeldet.")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
ws.send("da")
|
||||||
|
ws.receive(timeout=2)
|
||||||
|
except Exception: # noqa: BLE001 - der Browser ist weg, das ist keine Stoerung
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _strecke(ws, device_id: int) -> None: # type: ignore[no-untyped-def]
|
def _strecke(ws, device_id: int) -> None: # type: ignore[no-untyped-def]
|
||||||
"""Bytes hin, Bytes her -- und sonst nichts.
|
"""Bytes hin, Bytes her -- und sonst nichts.
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ def system():
|
|||||||
"dashboard_public",
|
"dashboard_public",
|
||||||
"vnc_enabled",
|
"vnc_enabled",
|
||||||
"vnc_port",
|
"vnc_port",
|
||||||
|
"vnc_warn_unencrypted_off",
|
||||||
"terminal_switches_enabled",
|
"terminal_switches_enabled",
|
||||||
"terminal_clients_enabled",
|
"terminal_clients_enabled",
|
||||||
"terminal_idle_timeout",
|
"terminal_idle_timeout",
|
||||||
@@ -147,6 +148,7 @@ def system_save():
|
|||||||
"dashboard_public",
|
"dashboard_public",
|
||||||
"vnc_enabled",
|
"vnc_enabled",
|
||||||
"vnc_port",
|
"vnc_port",
|
||||||
|
"vnc_warn_unencrypted_off",
|
||||||
"terminal_switches_enabled",
|
"terminal_switches_enabled",
|
||||||
"terminal_clients_enabled",
|
"terminal_clients_enabled",
|
||||||
"terminal_idle_timeout",
|
"terminal_idle_timeout",
|
||||||
|
|||||||
@@ -207,7 +207,28 @@ def sicherheitsverfahren(host: str, port: int = STANDARD_PORT) -> tuple[str, tup
|
|||||||
# Wir antworten mit 3.8 -- der Fassung, die auch der Browser
|
# Wir antworten mit 3.8 -- der Fassung, die auch der Browser
|
||||||
# spricht. Ein Server, der mehr kann, faellt darauf zurueck und
|
# spricht. Ein Server, der mehr kann, faellt darauf zurueck und
|
||||||
# nennt trotzdem seine Verfahren.
|
# nennt trotzdem seine Verfahren.
|
||||||
sock.sendall(b"RFB 003.008" + bytes([10]))
|
# Antworten wird mit *seiner* Fassung, hoechstens 3.8. Wer einem
|
||||||
|
# 3.3-Server mit 3.8 antwortet, bekommt keine Liste, sondern eine
|
||||||
|
# 32-Bit-Zahl -- und liest sie als "keine Verfahren".
|
||||||
|
eigene = "003.003" if fassung == "003.003" else "003.008"
|
||||||
|
sock.sendall(b"RFB " + eigene.encode("ascii") + bytes([10]))
|
||||||
|
|
||||||
|
if eigene == "003.003":
|
||||||
|
# RFB 3.3: der Server bestimmt allein und schickt eine
|
||||||
|
# 32-Bit-Zahl. Das ist kein Sonderfall aus der Vorzeit --
|
||||||
|
# RealVNC faellt darauf zurueck, sobald keine Anmeldung
|
||||||
|
# verlangt wird.
|
||||||
|
rohwert = b""
|
||||||
|
while len(rohwert) < 4:
|
||||||
|
stueck = sock.recv(4 - len(rohwert))
|
||||||
|
if not stueck:
|
||||||
|
break
|
||||||
|
rohwert += stueck
|
||||||
|
if len(rohwert) < 4:
|
||||||
|
return fassung, ()
|
||||||
|
bestimmt = int.from_bytes(rohwert, "big")
|
||||||
|
return fassung, () if bestimmt == 0 else (bestimmt,)
|
||||||
|
|
||||||
anzahl = sock.recv(1)
|
anzahl = sock.recv(1)
|
||||||
if not anzahl:
|
if not anzahl:
|
||||||
return fassung, ()
|
return fassung, ()
|
||||||
@@ -235,13 +256,24 @@ def zugang(device: Mapping[str, Any], *, port: int = STANDARD_PORT, pruefen: boo
|
|||||||
return Zugang(ziel=host, port=port, erreichbar=bool(fassung), verfahren=verfahren)
|
return Zugang(ziel=host, port=port, erreichbar=bool(fassung), verfahren=verfahren)
|
||||||
|
|
||||||
|
|
||||||
def verbindungsdatei(device: Mapping[str, Any], *, port: int = STANDARD_PORT) -> str:
|
def verbindungsdatei(
|
||||||
|
device: Mapping[str, Any], *, port: int = STANDARD_PORT, warnung_aus: bool = False
|
||||||
|
) -> str:
|
||||||
"""Der Inhalt der ``.vnc``-Datei -- drei Zeilen, keine vierte.
|
"""Der Inhalt der ``.vnc``-Datei -- drei Zeilen, keine vierte.
|
||||||
|
|
||||||
``ConnMethod=tcp`` ist die direkte Verbindung (nicht ueber den Cloud-Dienst
|
``ConnMethod=tcp`` ist die direkte Verbindung (nicht ueber den Cloud-Dienst
|
||||||
von RealVNC), ``FriendlyName`` der Name, den der Viewer anzeigt, ``Host``
|
von RealVNC), ``FriendlyName`` der Name, den der Viewer anzeigt, ``Host``
|
||||||
das Ziel. Ein abweichender Port gehoert in dieser Datei an den Host, mit
|
das Ziel. Ein abweichender Port gehoert in dieser Datei an den Host, mit
|
||||||
Doppelpunkt -- einen eigenen Schluessel dafuer gibt es nicht.
|
Doppelpunkt -- einen eigenen Schluessel dafuer gibt es nicht.
|
||||||
|
|
||||||
|
``warnung_aus`` haengt eine vierte Zeile an: ``WarnUnencrypted=False``. Sie
|
||||||
|
betrifft **den Viewer**, nicht den Server -- er zeigt sonst bei jeder
|
||||||
|
Verbindung zu einem Geraet ohne Streckenverschluesselung einen roten
|
||||||
|
Hinweis, den man wegklicken muss. Wer ``Encryption=AlwaysOff`` auf dem
|
||||||
|
Geraet gesetzt hat (damit der Browser ueberhaupt verbinden kann), sieht
|
||||||
|
diesen Hinweis fortan bei jedem Start. Er bleibt in der Vorgabe stehen:
|
||||||
|
eine unverschluesselte Strecke soll man einmal bewusst hinnehmen, nicht
|
||||||
|
stillschweigend. Abschaltbar unter Verwaltung -> System.
|
||||||
"""
|
"""
|
||||||
host = ziel(device)
|
host = ziel(device)
|
||||||
if port != STANDARD_PORT:
|
if port != STANDARD_PORT:
|
||||||
@@ -251,6 +283,8 @@ def verbindungsdatei(device: Mapping[str, Any], *, port: int = STANDARD_PORT) ->
|
|||||||
f"FriendlyName={str(device.get('name') or host).strip()}",
|
f"FriendlyName={str(device.get('name') or host).strip()}",
|
||||||
f"Host={host}",
|
f"Host={host}",
|
||||||
]
|
]
|
||||||
|
if warnung_aus:
|
||||||
|
zeilen.append("WarnUnencrypted=False")
|
||||||
return ZEILE.join(zeilen) + ZEILE
|
return ZEILE.join(zeilen) + ZEILE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,16 @@ TESM_SETTINGS: tuple[SettingSpec, ...] = (
|
|||||||
minimum=1,
|
minimum=1,
|
||||||
maximum=65535,
|
maximum=65535,
|
||||||
),
|
),
|
||||||
|
SettingSpec(
|
||||||
|
"vnc_warn_unencrypted_off",
|
||||||
|
False,
|
||||||
|
"bool",
|
||||||
|
"Warnung des Viewers vor unverschlüsselter Verbindung unterdrücken",
|
||||||
|
hint="Setzt WarnUnencrypted=False in die Verbindungsdatei. Betrifft nur den "
|
||||||
|
"RealVNC Viewer auf dem Arbeitsplatz, nicht die Verbindung selbst: die bleibt "
|
||||||
|
"unverschlüsselt, wenn das Gerät es so anbietet.",
|
||||||
|
section="monitoring",
|
||||||
|
),
|
||||||
# -- DHCP --------------------------------------------------------------- #
|
# -- DHCP --------------------------------------------------------------- #
|
||||||
SettingSpec("dhcp_domain", "local", "str", "Domainname", section="dhcp"),
|
SettingSpec("dhcp_domain", "local", "str", "Domainname", section="dhcp"),
|
||||||
SettingSpec(
|
SettingSpec(
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
<div id="screen" class="screen"
|
<div id="screen" class="screen"
|
||||||
data-socket="{{ websocket_path }}"
|
data-socket="{{ websocket_path }}"
|
||||||
data-ziel="{{ zugang.ziel }}:{{ zugang.port }}"
|
data-ziel="{{ zugang.ziel }}:{{ zugang.port }}"
|
||||||
|
data-verfahren="{{ zugang.verfahren | join(',') }}"
|
||||||
data-blockiert="{{ '1' if zugang.hinderungsgrund else '0' }}"
|
data-blockiert="{{ '1' if zugang.hinderungsgrund else '0' }}"
|
||||||
data-grund="{{ zugang.hinderungsgrund }}">
|
data-grund="{{ zugang.hinderungsgrund }}">
|
||||||
<div id="screen-canvas" class="screen__canvas" hidden></div>
|
<div id="screen-canvas" class="screen__canvas" hidden></div>
|
||||||
|
|||||||
@@ -53,6 +53,10 @@
|
|||||||
{{ field('vnc_port', 'VNC-Port', value=values.vnc_port, type='number',
|
{{ field('vnc_port', 'VNC-Port', value=values.vnc_port, type='number',
|
||||||
hint_text=specs['vnc_port'].hint) }}
|
hint_text=specs['vnc_port'].hint) }}
|
||||||
</div>
|
</div>
|
||||||
|
{{ checkbox('vnc_warn_unencrypted_off',
|
||||||
|
'Warnung des Viewers vor unverschlüsselter Verbindung unterdrücken',
|
||||||
|
checked=values.vnc_warn_unencrypted_off,
|
||||||
|
hint_text=specs['vnc_warn_unencrypted_off'].hint) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="card__footer"><button class="btn btn--primary" type="submit">Speichern</button></div>
|
<div class="card__footer"><button class="btn btn--primary" type="submit">Speichern</button></div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-core"
|
name = "tesm-core"
|
||||||
version = "2.8.5"
|
version = "2.8.7"
|
||||||
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,50 @@
|
|||||||
|
|
||||||
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]);
|
||||||
|
|
||||||
|
// Drei Eingriffe in private Methoden der mitgelieferten Bibliothek. Bewusst
|
||||||
|
// hier und nicht in der Bibliothek selbst: eine neue Fassung von noVNC laesst
|
||||||
|
// sich dann austauschen, ohne eine Aenderung nachzupflegen -- faellt eine
|
||||||
|
// Methode weg, greift der jeweilige Eingriff nicht mehr, und die Sitzung
|
||||||
|
// laeuft wieder wie ohne ihn. Kein stiller Bruch.
|
||||||
|
const istUnterstuetzt = RFB.prototype._isSupportedSecurityType;
|
||||||
|
|
||||||
|
// Den *Grund* eines Fehlschlags kennt nur ``_fail`` -- das Ereignis
|
||||||
|
// "disconnect" traegt ihn nicht, und der Weg ueber die Protokollausgabe
|
||||||
|
// funktioniert nicht: die Bibliothek bindet ``console.error`` beim Laden, also
|
||||||
|
// bevor eine Seite etwas daran aendern koennte. (Genau daran ist der erste
|
||||||
|
// Versuch gescheitert -- die Meldung blieb leer.)
|
||||||
|
let letzterGrund = "";
|
||||||
|
const originalFail = RFB.prototype._fail;
|
||||||
|
RFB.prototype._fail = function (details) {
|
||||||
|
letzterGrund = String(details);
|
||||||
|
return originalFail.call(this, details);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Und der Abschluss der Leitung selbst: der Schliesscode sagt, ob TESM
|
||||||
|
// abgewiesen hat (1008), ob es ein Serverfehler war (1011) -- oder ob die
|
||||||
|
// Verbindung nie zustande kam (1006).
|
||||||
|
let letzterCode = 0;
|
||||||
|
const originalSocketClose = RFB.prototype._socketClose;
|
||||||
|
RFB.prototype._socketClose = function (ereignis) {
|
||||||
|
letzterCode = (ereignis && ereignis.code) || 0;
|
||||||
|
if (ereignis && ereignis.reason) {
|
||||||
|
letzterGrund = letzterGrund || String(ereignis.reason);
|
||||||
|
}
|
||||||
|
return originalSocketClose.call(this, ereignis);
|
||||||
|
};
|
||||||
|
|
||||||
const wurzel = document.getElementById("screen");
|
const wurzel = document.getElementById("screen");
|
||||||
if (wurzel) {
|
if (wurzel) {
|
||||||
starten(wurzel);
|
starten(wurzel);
|
||||||
@@ -41,8 +85,62 @@ function starten(wurzel) {
|
|||||||
zeile.className = `screen__status${art ? " screen__status--" + art : ""}`;
|
zeile.className = `screen__status${art ? " screen__status--" + art : ""}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function grund() {
|
||||||
|
const teile = [];
|
||||||
|
if (letzterGrund) {
|
||||||
|
teile.push(letzterGrund.replace(/^Failed (when|while) \w+: /, ""));
|
||||||
|
}
|
||||||
|
if (rfb && rfb._rfbAuthScheme > 0) {
|
||||||
|
teile.push(`gewähltes Verfahren: ${rfb._rfbAuthScheme}`);
|
||||||
|
}
|
||||||
|
return teile.join(" · ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steht die WebSocket-Strecke zu TESM überhaupt? Zwei sehr verschiedene
|
||||||
|
// Ursachen sehen von aussen gleich aus: der VNC-Server mag nicht, oder die
|
||||||
|
// Verbindung kommt nie zustande, weil ein Proxy zwischen Browser und TESM
|
||||||
|
// "Upgrade" nicht durchreicht. Diese Probe trennt sie.
|
||||||
|
function streckeTesten() {
|
||||||
|
return new Promise((fertig) => {
|
||||||
|
let beantwortet = false;
|
||||||
|
const pruefling = new WebSocket(`${schema}//${window.location.host}/ws/probe`);
|
||||||
|
const schliessen = (ergebnis) => {
|
||||||
|
if (beantwortet) return;
|
||||||
|
beantwortet = true;
|
||||||
|
try {
|
||||||
|
pruefling.close();
|
||||||
|
} catch (fehler) {
|
||||||
|
/* schon zu */
|
||||||
|
}
|
||||||
|
fertig(ergebnis);
|
||||||
|
};
|
||||||
|
pruefling.onmessage = () => schliessen(true);
|
||||||
|
pruefling.onerror = () => schliessen(false);
|
||||||
|
pruefling.onclose = () => schliessen(false);
|
||||||
|
window.setTimeout(() => schliessen(false), 4000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function verbinden(zugang) {
|
function verbinden(zugang) {
|
||||||
melden("Verbindung wird aufgebaut …");
|
melden("Verbindung wird aufgebaut …");
|
||||||
|
letzterGrund = "";
|
||||||
|
letzterCode = 0;
|
||||||
|
|
||||||
|
// 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,11 +167,32 @@ 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. Wird geprüft, woran es liegt …",
|
||||||
"fehler",
|
"fehler",
|
||||||
);
|
);
|
||||||
|
// 1006 heisst: die Leitung ging zu, ohne dass die Gegenseite einen
|
||||||
|
// Grund geschickt hat -- typisch, wenn die WebSocket-Verbindung gar
|
||||||
|
// nicht erst zustande kam. Dann sagt die Probe, wer schweigt.
|
||||||
|
if (letzterCode === 1006 || !erklaerung) {
|
||||||
|
streckeTesten().then((steht) => {
|
||||||
|
melden(
|
||||||
|
steht
|
||||||
|
? `${erklaerung || "Verbindung abgebrochen"} – die WebSocket-Strecke zu ` +
|
||||||
|
"TESM selbst steht (Probe erfolgreich), der Abbruch kommt also von " +
|
||||||
|
"der VNC-Seite."
|
||||||
|
: "Die WebSocket-Verbindung zu TESM kommt nicht zustande – auch eine " +
|
||||||
|
"einfache Probe scheitert. Ein Proxy zwischen Browser und TESM muss " +
|
||||||
|
"die Kopfzeilen Upgrade und Connection durchreichen (nginx: " +
|
||||||
|
"location /ws/ mit proxy_set_header Upgrade $http_upgrade). Dasselbe " +
|
||||||
|
"gilt für die Browser-Konsole.",
|
||||||
|
"fehler",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rfb = null;
|
rfb = null;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in new issue
Block a user