Wenn Programmieren keinen Spass macht - A specific logon session does not exist - It may already have been terminated - 0x80070520

26.05.2018 23:55:50, Jürgen Auer, keine Kommentare
Hier wird angezeigt, daß der private Schlüssel existiert und zugeordnet ist. Beim Versuch, zu exportieren, steht aber: "Der dazugehörige private Schlüssel wurde nicht gefunden."

Ab und zu hatte ich schon mit Kunden das Phänomen, daß diese fragten, wann etwas soweit fertig sei. Und ich meinte, ich könne das nicht so richtig einschätzen. Woraufhin sich manche dies "überhaupt nicht vorstellen" konnten.

Nun gibt es - wieder einmal - ein treffend-schön-schauriges Beispiel dafür.

Im Januar hatte Letsencrypt die Version 2 des ACME-Protokolls auf dem dortigen Testsystem zur Nutzung freigegeben. Damit kann man kostenlos und automatisiert SSL-Zertifikate anfordern, bestätigen (per Dateihinterlegung auf der Website) und sich schließlich ein signiertes Zertifikat herunterladen.

Das installiert man lokal, bis man nach spätestens 90 Tagen ein neues braucht. Das sollte also automatisiert funktionieren. Sonst wird das bald sehr aufwendig.

Im Februar hatte ich mir das im wesentlichen angesehen, einen größtenteils funktionierenden Client geschrieben. Da klappte auch der letzte Schritt: Das Zertifikat so im MachineKeyStore ablegen, daß man das Zertifikat manuell der Website zuweisen kann.

Dann folgten andere eigene Arbeiten. Ende März aktivierte das Letsencrypt auch auf dem dortigen Produktivsystem.

Nun wollte ich das für die erste Kundensubdomain einbauen. Die läuft eigentlich auch über die Infrastruktur von Server-Daten. Aber die - nur lesende - Ausgabe war eben bis jetzt unverschlüsselt.

Was passierte? Der Code lief komplett durch. Das Zertifikat wurde scheinbar korrekt importiert. Aber beim Versuch, das Zertifikat manuell der Website zuzuweisen, gab es eine "berüchtigte Fehlermeldung":

> A specific logon session does not exist. It may already have been terminated - HRESULT 0x80070520

Der Fehler ist bei dem Thema SSL-Bindung berüchtigt. Allerdings: Der Code hatte im Februar noch problemlos funktioniert. Irgendwelche neuen Bugs müssen da wieder reingekommen sein. Das Problem trat sowohl auf meinem lokalen Arbeits-PC (Windows 10) als auch auf dem Webserver auf (Server 2012), wobei die Kommunikation mit Letsencrypt vom lokalen PC her lief und ich das Zertifikat hochkopierte. Es ging nur um den letzten Schritt: Die Zertifikatsantwort und den privaten Schlüssel zusammenfügen und das in Webhosting importieren.

Das Problem: Wenn man programmatisch ein SSL-Zertifikat beantragen möchte, benötigt man zunächst ein RSACryptoServiceProvider - Objekt, also eine Kombination aus privatem und öffentlichem Schlüssel. Das übergibt man dem CertificateRequest-Objekt, das nutzt den öffentlichen Schlüssel, um den eigentlichen CertificateRequest zu erstellen.

Bekommt man das Zertifikat von Letsencrypt zurück, packt man das in ein X509Certificate2 und koppelt über die X509Certificate2.PrivateKey-Eigenschaft den privaten Schlüssel des RSACryptoServiceProvider - Objekts wieder an das Zertifikat.

Dann - so die Theorie - kann man das in den Webhosting - CertificateStore packen und vom Webserver her verwenden. Das endete in der obigen Fehlermeldung.

Üblicher Kandidat: Der private Schlüssel fehlt. Den hatte ich aber - siehe das Bildschirmphoto. Warum funktionierte das trotzdem nicht?

Nach diversem Herumprobieren fiel auf: Versucht man, das Zertifikat in eine Datei zu speichern, gibt es nicht die Option, den privaten Schlüssel zu speichern. Denn:

> Der dazugehörige private Schlüssel wurde nicht gefunden.

Das eine Formular zeigt also an, daß es den privaten Schlüssel gibt. Das andere Formular kann den nicht finden. Na super. Daß dann auch der IIS nicht mit diesem "irgendwie beschädigten" Zertifikat klarkommt, ist nachvollziehbar. Für ein Webserver-Zertifikat wird natürlich der private Schlüssel benötigt.

Nach vielem Herumgesuche schließlich:

Certutil -repairstore Webhosting Zertifikatsfingerabdruck

Das führte dazu, daß nun beim Versuch, das Zertifikat zu exportieren, auch der private Schlüssel exportiert werden konnte. Sprich: "Irgendwie" waren Zertifikat und privater Schlüssel voneinander getrennt. Das Phänomen trat auf zwei verschiedenen Windows-Systemen auf, die "Quelle" für das Zertifikat war verschieden. Aber damit ließ sich das immerhin reparieren.

Allerdings: Die Bindung an den IIS funktionierte weiterhin nicht.

Es funktionierte nun aber:

1. Das reparierte Zertifikat mit dem privaten Schlüssel und allen erweiterten Eigenschaften exportieren.
2. Das Zertifikat im Webhosting-Zertifikatsspeicher löschen.
3. Das Zertifikat erneut importieren, dabei den privaten Schlüssel explizit als exportierbar anhaken.

Letzteres fand sich als Hinweis von 2012:

Error HRESULT: 0x80070520 when adding SSL binding in IIS

https://blogs.msdn.microsoft.com/kaushal/2012/10/07/error-hresult-0x80070520-when-adding-ssl-binding-in-iis/

Da gab es auch den Hinweis, daß man im System-Eventlog den zusätzlichen Fehler 0x8009030D findet.

> Schwerwiegender Fehler beim Zugriff auf den privaten Schlüssel der Server-Anmeldeinformationen für TLS. Der vom kryptografischen Modul zurückgegebene Fehlercode lautet 0x8009030D. Der interne Fehlerstatus ist 10001.

Sprich: Geplante Zeit für dieses Problem: 20 Sekunden, im Februar hatte das ohne Probleme funktioniert.

Tatsächlicher Zeitaufwand: Vielleicht so etwa 4 - 5 Stunden. Der Code vom Februar (Zertifikatsantwort und Schlüsselpaar zusammenfügen, in Datei speichern, die in Webhosting importieren) crashte. Die "Lösung" ist eigentlich absurd: Erst wird das importiert. Dann repariert. Dann exportiert und gelöscht. Dann wieder importiert - dann funktioniert alles. Nur weiß ich aktuell noch überhaupt nicht, ob sich das auch per Code machen läßt. Oder ob nicht das Problem nach dem nächsten Patchday wieder verschwindet.

Aber so lange will ich das eigentlich nicht liegen lassen.

Sprich: Praktisch habe ich das zwar nun "irgendwie" gelöst. Aber das erfordert erst recht manuellen Aufwand, so daß man womöglich noch einmal etwas Zeit benötigt, um das nun wirklich auf den Stand vom Februar bringen zu können.

Aber das ist eben das, was es beim Programmieren auch immer wieder gibt: Daß Konstellationen auftauchen, die sich "widersprechen", die eigentlich gar nicht gemeinsam auftreten können. Und daß man dann plötzlich einen Arbeitsaufwand von mehr als einem Tag hat. Mit dem Ergebnis einer Lösung, die nicht so wirklich zufriedenstellend ist.

*
* (wird nicht angezeigt)
Die Erläuterungen zum Datenschutz habe ich gelesen und stimme diesen zu.