#!/usr/bin/env python3 """ Zwei Funktionen fuer den JViewer-Start mit IcedTea-Web: 1) JNLP-Strukturpatch (Standardaufruf): patch_jviewer.py - / bleiben UNVERAENDERT: die Jars werden signiert (s.u.), signierter+vertrauter Code mit dieser Anforderung bekommt regulaer AllPermission - kein Grund mehr, das zu entfernen. - wird trotzdem zu umbenannt: das ist laut Fehlermeldung "nativelib kann nicht angegeben werden sofern vertrauenswuerdige Umgebung angefordert wird" mit inkompatibel, unabhaengig davon ob signiert oder nicht. - bleibt UNVERAENDERT (zeigt weiter auf die echte BMC). Das ist wichtig: IcedTea-Web erlaubt unsignierten/nicht vertrauten Apps im Sandbox-Modus nur Netzwerkzugriff zurueck zu Host+Port der Codebase. Der KVM-Redirection-Socket (Port 7578) geht an dieselbe IP wie die BMC/ Codebase, aber einen anderen Port - wuerde man die Codebase auf einen lokalen Proxy umbiegen, wuerde der Zugriff verboten (getestet, "access denied SocketPermission"). 2) Manifest-Patch fuer ein bereits von IcedTea-Web heruntergeladenes, gecachtes Jar (wird NACH einem ersten, absichtlich fehlschlagenden javaws-Lauf aufgerufen, der nur zum Befuellen des Caches dient): patch_jviewer.py --strip-manifest [ ...] Frueherer Ansatz: entfernte "Permissions: all-permissions" aus dem Manifest, um IcedTea-Webs hartcodierte Forced-Sandbox fuer UNSIGNIERTEN Code mit dieser Deklaration zu umgehen. Wird seit Einfuehrung der Selbstsignierung NICHT MEHR aufgerufen (das Attribut wird fuer signierten, vertrauten Code wieder gebraucht) - Funktion bleibt nur als Fallback im Code, falls Signierung aus irgendeinem Grund nicht moeglich ist. """ import os import re import sys import zipfile def localname(t): """Tag-Namen ohne Namespace-Praefix, egal ob die JNLP ein xmlns deklariert oder nicht (manche AMI-Firmwarestaende tun es, manche nicht).""" return t.split("}", 1)[-1] if "}" in t else t def is_tag(el, name): return localname(el.tag) == name def strip_all_permissions_from_manifest(jar_path): with zipfile.ZipFile(jar_path, "r") as zin: manifest_name = "META-INF/MANIFEST.MF" try: manifest = zin.read(manifest_name).decode("utf-8", "replace") except KeyError: print(f"(kein Manifest in {jar_path}, nichts zu tun)") return # Manifest-Continuation-Zeilen (beginnen mit einem Leerzeichen) an die # vorherige Zeile anhaengen, damit "Permissions: all-permissions" # sicher als eine logische Zeile erkannt wird. lines = manifest.splitlines() logical = [] for line in lines: if line.startswith(" ") and logical: logical[-1] += line[1:] else: logical.append(line) filtered = [l for l in logical if not re.match(r"(?i)^permissions\s*:", l)] if filtered == logical: print(f"(Permissions-Attribut in {jar_path} nicht vorhanden, nichts zu tun)") return new_manifest = "\n".join(filtered) + "\n" entries = {} for item in zin.infolist(): entries[item] = zin.read(item.filename) tmp_path = jar_path + ".tmp" with zipfile.ZipFile(tmp_path, "w", zipfile.ZIP_DEFLATED) as zout: for item, data in entries.items(): if item.filename == manifest_name: data = new_manifest.encode("utf-8") zout.writestr(item, data) os.replace(tmp_path, jar_path) print(f"Manifest gepatcht (Permissions: all-permissions entfernt): {jar_path}") def patch_jnlp(src, dst): import xml.etree.ElementTree as ET tree = ET.parse(src) root = tree.getroot() # Falls die JNLP ein xmlns deklariert (z.B. xmlns="http://www.w3.org/1999/xhtml"), # dieselbe Namespace-URI beim Schreiben wieder als Default-Namespace nutzen, # damit ET keine ns0:-Praefixe einfuegt. root_ns = localname(root.tag) if root.tag != root_ns: ns_uri = root.tag[1:root.tag.index("}")] ET.register_namespace("", ns_uri) # / bleiben unangetastet (s. Docstring oben) - # nur zu umbenennen (Namespace-Praefix des Originaltags beibehalten) for el in root.iter(): if is_tag(el, "nativelib"): prefix = el.tag[: el.tag.index("}") + 1] if "}" in el.tag else "" el.tag = f"{prefix}jar" tree.write(dst, encoding="UTF-8", xml_declaration=True) print(f"Gepatchte JNLP geschrieben: {dst}") def main(): args = sys.argv[1:] if args and args[0] == "--strip-manifest": jar_paths = args[1:] if not jar_paths: print("Benutzung: patch_jviewer.py --strip-manifest [ ...]") sys.exit(1) for jar_path in jar_paths: strip_all_permissions_from_manifest(jar_path) return if len(args) != 2: print("Benutzung: patch_jviewer.py ") print(" oder: patch_jviewer.py --strip-manifest [ ...]") sys.exit(1) patch_jnlp(args[0], args[1]) if __name__ == "__main__": main()