#!/bin/bash set -e BASE="$(cd "$(dirname "$0")" && pwd)" echo "=== JViewer Auto Starter ===" echo "Ordner: $BASE" # Altes Log löschen, damit nie ein Log aus einem früheren Lauf verwechselt wird rm -f "$BASE/jviewer-debug.log" if [ "$1" != "-c" ] || [ -z "$2" ]; then echo "Benutzung:" echo "$0 -c datei.jnlp" exit 1 fi JNLP="$2" if [ "${JNLP:0:1}" != "/" ]; then JNLP="$BASE/$JNLP" fi if [ ! -f "$JNLP" ]; then echo "JNLP nicht gefunden:" echo "$JNLP" exit 1 fi echo "JNLP:" echo "$JNLP" # --------------------------------------------------------------------------- # Java 8 suchen / herunterladen (Temurin JDK von Adoptium - JDK statt JRE, # weil wir jarsigner/keytool brauchen um die Jars selbst zu signieren, s.u.) # --------------------------------------------------------------------------- JAVA=$(find "$BASE/java8" -type f -name java 2>/dev/null | head -1) JARSIGNER=$(find "$BASE/java8" -type f -name jarsigner 2>/dev/null | head -1) if [ -z "$JAVA" ] || [ -z "$JARSIGNER" ]; then echo "Kein vollständiges Java8-JDK gefunden (java+jarsigner) - lade neu..." rm -rf "$BASE/java8" mkdir -p "$BASE/java8" ( cd "$BASE/java8" wget -O java8.tar.gz \ "https://api.adoptium.net/v3/binary/latest/8/ga/linux/x64/jdk/hotspot/normal/eclipse" tar xf java8.tar.gz rm java8.tar.gz ) JAVA=$(find "$BASE/java8" -type f -name java | head -1) JARSIGNER=$(find "$BASE/java8" -type f -name jarsigner | head -1) fi if [ -z "$JAVA" ] || [ -z "$JARSIGNER" ]; then echo "Java8-JDK (java + jarsigner) konnte nicht bereitgestellt werden" exit 1 fi KEYTOOL="$(dirname "$JARSIGNER")/keytool" JAVA_HOME="$(dirname "$(dirname "$JAVA")")" echo echo "Java:" echo "$JAVA" "$JAVA" -version echo "jarsigner: $JARSIGNER" echo "keytool: $KEYTOOL" # --------------------------------------------------------------------------- # javaws finden (icedtea-netx). Wird NICHT lokal erwartet, sondern im System # gesucht (z.B. /usr/bin/javaws aus dem Paket "icedtea-netx"). # --------------------------------------------------------------------------- JAVAWS="" for CAND in "$BASE/javaws" "$(command -v javaws 2>/dev/null)" /usr/bin/javaws; do if [ -n "$CAND" ] && [ -x "$CAND" ]; then JAVAWS="$CAND" break fi done if [ -z "$JAVAWS" ]; then echo "javaws wurde nicht gefunden." echo "Bitte installieren: sudo apt install icedtea-netx" exit 1 fi echo echo "javaws:" echo "$JAVAWS" # --------------------------------------------------------------------------- # Eigene, isolierte Umgebung (HOME) für IcedTea-Web, damit Systemeinstellungen # nicht stören und nichts außerhalb von $BASE verändert wird. # --------------------------------------------------------------------------- export HOME="$BASE/runtime-home" # IcedTea-Web folgt zuerst XDG_CONFIG_HOME/XDG_CACHE_HOME, falls diese im # System bereits gesetzt sind - dann wird HOME ignoriert und die echte # System-Config (~/.config/icedtea-web) verwendet statt unserer eigenen. # Deshalb XDG-Variablen explizit auf unseren eigenen Bereich zwingen. export XDG_CONFIG_HOME="$HOME/.config" export XDG_CACHE_HOME="$HOME/.cache" # Cache wird bei jedem Lauf frisch geleert (Jars sollen neu von der BMC # geladen und neu gepatcht/signiert werden). Der Config-Ordner wird NICHT # mehr komplett gelöscht: falls die automatische Zertifikatsvertrauensstellung # unten nicht zuverlässig greift und stattdessen ein GUI-Dialog erscheint, in # dem man einmalig "Diesem Zertifikat immer vertrauen" klickt, soll diese # Entscheidung über Neustarts hinweg erhalten bleiben statt jedes Mal verworfen # zu werden. rm -rf "$XDG_CACHE_HOME/icedtea-web" mkdir -p "$XDG_CONFIG_HOME/icedtea-web" mkdir -p "$XDG_CACHE_HOME/icedtea-web" # JAVA_HOME/PATH auf das heruntergeladene Java8 zwingen, damit javaws nicht # irgendeine System-Java-Version verwendet. export JAVA_HOME export PATH="$JAVA_HOME/bin:$PATH" # Hinweis: deployment.javaws.jre.0.*, deployment.javaws.cache.* und # deployment.manifest.attribute.check werden von dieser IcedTea-Web-Version # nicht erkannt ("Eigenschaft ist unbekannt" im Log) und wurden deshalb # entfernt. Das heruntergeladene Java8 wird stattdessen ueber JAVA_HOME/PATH # erzwungen (s.o.) - das greift laut Log zuverlaessig ("your JRE - 1.8.0_492"). # Die Sandbox-Beschraenkung fuer unsignierten Code wird nicht per Config, # sondern durch Selbstsignierung der Jars geloest (siehe unten). cat > "$XDG_CONFIG_HOME/icedtea-web/deployment.properties" </ bleiben unverändert (Jars werden signiert, # s.u. - signierter+vertrauter Code mit dieser Anforderung bekommt regulär # AllPermission) # - zu ändern (inkompatibel mit , # unabhängig von Signierung) # - bleibt UNVERÄNDERT (zeigt weiter auf die echte BMC), damit # IcedTea-Webs Sandbox-Regel "Netzwerkzugriff nur zurück zum Codebase-Host" # den KVM-Redirection-Socket (Port 7578, selbe IP wie die BMC) erlaubt, # falls Vertrauen aus irgendeinem Grund doch nicht greift. # --------------------------------------------------------------------------- echo echo "Patch JNLP" FIXED="$BASE/fixed-$(basename "$JNLP")" rm -f "$FIXED" if [ ! -f "$BASE/patch_jviewer.py" ]; then echo "FEHLER: $BASE/patch_jviewer.py fehlt." exit 1 fi python3 "$BASE/patch_jviewer.py" "$JNLP" "$FIXED" PATCH_RC=$? if [ "$PATCH_RC" -ne 0 ]; then echo "FEHLER: patch_jviewer.py ist mit Exitcode $PATCH_RC abgebrochen." exit 1 fi if [ ! -f "$FIXED" ]; then echo "FEHLER: $FIXED wurde nicht erzeugt." exit 1 fi echo echo "Kontrolle:" if grep -q "nativelib" "$FIXED"; then echo "FEHLER: JNLP wurde NICHT gepatcht (nativelib noch vorhanden)." exit 1 fi echo "(nativelib wurde in jar umbenannt - ok)" # --------------------------------------------------------------------------- # 1. Lauf: absichtlich nur zum Befüllen des Caches. javaws lädt die Original- # jars von der echten BMC in den eigenen Cache und wird danach vermutlich mit # einem Berechtigungsfehler abbrechen (Manifest deklariert "all-permissions", # ist aber unsigniert) - das ist an dieser Stelle erwartet und kein Problem. # --------------------------------------------------------------------------- echo echo "Lauf 1/2: Cache befüllen (Abbruch danach ist normal)" cd "$BASE" set +e "$JAVAWS" -verbose "$FIXED" >"$BASE/jviewer-debug-pass1.log" 2>&1 set -e CACHED_JARS=$(find "$XDG_CACHE_HOME/icedtea-web" -type f -name '*.jar' 2>/dev/null) if [ -z "$CACHED_JARS" ]; then echo "FEHLER: Nach Lauf 1 wurden keine Jars im Cache gefunden." echo "--- jviewer-debug-pass1.log ---" cat "$BASE/jviewer-debug-pass1.log" exit 1 fi echo "Im Cache gefundene Jars:" echo "$CACHED_JARS" # --------------------------------------------------------------------------- # Jars selbst signieren (selbstsigniertes Zertifikat). Das Manifest-Attribut # "Permissions: all-permissions" bleibt dabei UNVERÄNDERT im Jar (frühere # Script-Version entfernte es, um die Forced-Sandbox für UNSIGNIERTEN Code zu # umgehen - das Attribut wird jetzt für signierten, vertrauten Code aber # gerade gebraucht, um volle Rechte statt Sandbox zu bekommen). # --------------------------------------------------------------------------- # Unsignierter Code bekommt von IcedTea-Web nur die restriktive Sandbox # (Socket-Permission ist an Host UND Port der Codebase gebunden - der # KVM-Redirection-Port 7578 unterscheidet sich vom Codebase-Port 443 und wird # deshalb verweigert, s. DEVLOG). Signierter Code mit "Permissions: # all-permissions" bekommt nach einmaligem Vertrauen des Zertifikats volle # Rechte statt Sandbox - deshalb signieren wir hier selbst und importieren # das Zertifikat in IcedTea-Webs Trusted-Certs-Store, damit kein manueller # Klick nötig ist (Best-Effort - Pfad/Format ist nicht offiziell dokumentiert # und wurde nicht auf dem Zielsystem verifiziert, siehe DEVLOG). # --------------------------------------------------------------------------- echo echo "Signiere gecachte Jars (selbstsigniertes Zertifikat)" SIGNING_DIR="$BASE/signing" KEYSTORE="$SIGNING_DIR/jviewer.jks" CERT="$SIGNING_DIR/jviewer.crt" ALIAS="jviewer" STOREPASS="jviewer-local" mkdir -p "$SIGNING_DIR" if [ ! -f "$KEYSTORE" ]; then echo "Erzeuge neues Signier-Schlüsselpaar (einmalig, wird unter $SIGNING_DIR aufbewahrt)" "$KEYTOOL" -genkeypair \ -keystore "$KEYSTORE" -storepass "$STOREPASS" -keypass "$STOREPASS" \ -alias "$ALIAS" -keyalg RSA -keysize 2048 -validity 3650 \ -dname "CN=JViewer Local, OU=jviewer, O=local, L=local, S=local, C=DE" fi "$KEYTOOL" -exportcert -rfc \ -keystore "$KEYSTORE" -storepass "$STOREPASS" -alias "$ALIAS" -file "$CERT" # shellcheck disable=SC2086 for JAR in $CACHED_JARS; do "$JARSIGNER" -keystore "$KEYSTORE" -storepass "$STOREPASS" "$JAR" "$ALIAS" done # Zertifikat in IcedTea-Webs Trusted-Certs-Store eintragen, damit kein # Vertrauens-Dialog erscheinen muss. Falls das nicht greift, fragt IcedTea-Web # beim 2. Lauf per GUI-Dialog nach - dort einmalig "immer vertrauen" wählen. TRUSTED_CERTS_DIR="$XDG_CONFIG_HOME/icedtea-web/security" TRUSTED_CERTS_STORE="$TRUSTED_CERTS_DIR/trusted.certs" TRUSTED_STOREPASS="changeit" mkdir -p "$TRUSTED_CERTS_DIR" "$KEYTOOL" -importcert -noprompt \ -keystore "$TRUSTED_CERTS_STORE" -storepass "$TRUSTED_STOREPASS" \ -alias "$ALIAS" -file "$CERT" || echo "Hinweis: Import in Trusted-Certs-Store fehlgeschlagen - ggf. manuell im GUI-Dialog bestätigen." # --------------------------------------------------------------------------- # 2. Lauf: mit -Xoffline, damit die (jetzt gepatchten und signierten) Cache- # Dateien verwendet werden, ohne dass IcedTea-Web sie erneut von der BMC # herunterlädt und damit den Patch überschreibt. # --------------------------------------------------------------------------- echo echo "Lauf 2/2: Starte JViewer (offline, aus gepatchtem Cache):" echo "$FIXED" "$JAVAWS" -Xoffline -verbose "$FIXED" 2>&1 | tee "$BASE/jviewer-debug.log" echo echo "Log:" echo "$BASE/jviewer-debug.log" read -p "ENTER zum Beenden"