Hibiscus wechselt nach Sperrfehler (zwei Instanzen gleichzeitig gestartet) dauerhaft die DB-Verschlüsselung von XTEA auf AES und blockiert sich damit selbst

ReRo

Betreff:

Hibiscus wechselt nach Sperrfehler (zwei Instanzen gleichzeitig gestartet) dauerhaft die DB-Verschlüsselung von XTEA auf AES und blockiert sich damit selbst

 ·  Gepostet: Gestern um 21:36 Uhr  ·  #187849
Hallo zusammen,

ich hatte einen Fall, bei dem Hibiscus nach einem Sperrfehler (vermutlich durch zwei gleichzeitig gestartete Instanzen) dauerhaft nicht mehr startete mit „Verschlüsselungsfehler in Datei ... [90049-199]". Ich konnte die Ursache anhand der Logs und des öffentlichen Quellcodes recht genau eingrenzen und wollte das hier dokumentieren, falls es noch nicht bekannt ist bzw. für andere Betroffene.

Umgebung
  • Hibiscus 2.12.4 (Update von 2.12.2), Jameica 2.12.0
  • H2-Datenbank 1.4.199, Verschlüsselung ursprünglich XTEA
  • Windows 11 Pro


Auslöser
Am 29.05. wurde offenbar eine zweite Hibiscus-Instanz gestartet, während die erste noch lief und die hibiscus.h2.db offen hielt.
Beobachtung im Log (jameica.log, anonymisiert):
Code
[...] determine current database version
  [...] jdbc url: jdbc:h2:...\hibiscus/h2db/hibiscus;CIPHER=XTEA
  [...] WARN unable to determine database version - database probably empty, recreating
  [...] WARN detected error: ... CIPHER=XTEA failed; nested exception is:
        org.h2.jdbc.JdbcSQLNonTransientException: Eingabe/Ausgabe: "java.io.IOException:
        Der Prozess kann nicht auf die Datei zugreifen, da ein anderer Prozess
        einen Teil der Datei gesperrt hat"; [...] [90031-199]
  [...] INFO Installiere Hibiscus
  [...] jdbc url: jdbc:h2:...\hibiscus/h2db/hibiscus;CIPHER=AES
  [...] WARN detected error: ... CIPHER=AES failed ... [90031-199] (derselbe Sperrfehler)
  [...] ERROR unable to recreate database


Ab diesem Zeitpunkt stand in cfg\de.willuhn.jameica.hbci.rmi.HBCIDBService.properties dauerhaft database.driver.h2.encryption.algorithm=AES, obwohl die Datenbankdatei selbst nach wie vor XTEA-verschlüsselt und völlig intakt war. Jeder weitere Start scheiterte seitdem mit dem „Verschlüsselungsfehler [90049-199]", weil mit dem falschen Algorithmus geöffnet wurde.

Ursache im Quellcode (HBCIDBServiceImpl.java, GitHub master):

Code
 public void checkConsistency() {
    ...
    catch (RemoteException re) {
      Throwable cause = re.getCause();
      if (!(cause instanceof SQLException)) throw re;
      Logger.warn("unable to determine database version - database probably empty, recreating");
      this.fallback = true;
      this.install();
      ...
    }
  }

  public void install() {
    // Bei Neu-Installationen verwenden wir jetzt AES statt XTEA
    // "fallback" heisst: Die normale Verbindung schlug fehl. Wir haben eine
    // existierende Installation, aber vermutlich mit einer leeren Datenbank
    if (!this.fallback) {
      ...
      HBCIDBService.SETTINGS.setAttribute("database.driver.h2.encryption.algorithm","AES");
    }
    ...
  }


Zwei Probleme sehe ich hier:

  • checkConsistency() behandelt jede SQLException beim Versionsabruf als „Datenbank ist wahrscheinlich leer". Ein transienter Sperrfehler durch eine zweite laufende Instanz (IOException, gewrappt als JdbcSQLNonTransientException) fällt darunter, obwohl die Datenbank offensichtlich weder leer noch beschädigt ist.
  • Das fallback-Flag soll laut Kommentar genau verhindern, dass in diesem Fall die Verschlüsselung überschrieben wird – in meinem Log wurde die AES-Property aber trotzdem geschrieben, bevor der Neuanlage-Versuch selbst am gleichen Sperrfehler scheiterte. Da Jameica beim Start parallel u.a. den BackupService aus einem eigenen Thread-Pool auf denselben Service zugreifen lässt und fallback ein einfaches, nicht synchronisiertes Instanzfeld ist, vermute ich hier eine Race Condition zwischen mehreren Threads.


Unabhängig vom genauen Mechanismus: Ein reiner Verbindungs-/Sperrfehler sollte niemals dazu führen, dass dauerhaft eine Konfigurationsänderung an einer intakten, nicht-leeren Datenbank persistiert wird – erst recht nicht, wenn der Neuanlage-Versuch selbst fehlschlägt und gar nichts „repariert" wurde.

Workaround/Lösung, falls jemand vor demselben Problem steht: Jameica beenden, in cfg\de.willuhn.jameica.hbci.rmi.HBCIDBService.properties die Zeile
Code
  database.driver.h2.encryption.algorithm=AES

zurück auf
Code
  database.driver.h2.encryption.algorithm=XTEA

ändern (vorher Backup der Datei anlegen), danach ließ sich bei mir alles wieder öffnen, keine Daten verloren.

Ich habe im Forum nach ähnlichen Fällen gesucht: Der Sperrfehler bei zwei gleichzeitigen Instanzen ist bekannt (z. B. "Datenbank kann nicht initialisiert werden ... Locked by another process"), ebenso der generische Verschlüsselungsfehler nach einem Update. Die konkrete Verbindung – dass ein Sperrfehler die Verschlüsselung dauerhaft umschaltet – konnte ich aber in keinem bestehenden Thread finden. Vielleicht hilft das ja bei einer dauerhaften Behebung.

Danke & Grüße
René