OpenSSL: Implementierung innerhalb eines Client- und Server-Programms, Teil 2

Seite 3: IPv6 und Portabilität

Inhaltsverzeichnis

Wie im ersten Teil gezeigt lässt sich der Server starten:

./wopr <host>:<port> servercert.pem private.key

Folgender Befehl startet nun das zugehörtige WOPR-Terminal:

./terminal <host>:<port> <trust-certificates.pem>

Neben dem Host und dem Port, auf dem die Verbindung erfolgen soll, benötigt man eine Trust-Zertifikatsdatei im PEM-Format. Im einfachsten Fall lässt sich einfach das vom Makefile erzeugte servercert.pem mit dem selbst signierten Server-Zertifikat angeben. Darauf meldet der Client beim Connect, dass das Server-Zertifikat gültig ist. Kommt ein CA-signiertes Server-Zertifikat zum Einsatz, muss sich das CA-Zertifikat, das das Server-Zertifikat signiert hat, in der PEM-Datei enthalten sein. Optional lässt sich als zusätzliches Argument eine Seed für den PRNG anhängen. Beispielsweise eine Datei oder ein "special device".

Sowie sich der Client mit dem Server verbunden hat, kann der Dialog zwischen den beiden beginnen. Wie am Ende des ersten Teils erläutert, lassen sich nun die Befehle aus "War Games" absetzen.

Ein paar Worte bedarf es noch zu IPv6. Obwohl das Protokoll seit geraumer Zeit Einzug in die Praxis hält, hat OpenSSL noch heute Schwierigkeiten mit ihm. Die BIO-Bibliothek, die Sockets kapselt, konnte bis Version 1.0.0 von OpenSSL überhaupt nicht mit IPv6 umgehen. Seitdem kann wenigstens BIO_new_accept() mit "Hostnamen" wie fc9e:21a7:a92c:2424::1:7777, die sich in den Host fc9e:21a7:a92c:2424::1 und den Port 7777 teilen, umgehen. Somit lassen sich wenigstens Server-Prozesse jetzt unverändert in die schöne neue IPv6-Welt befördern.

Die an sich leistungsfähige Funktion BIO_set_conn_hostname() streckt jedoch auch in Version 1.0.0 angesichts eines solchen Hostnamens die Waffen. Fehlermeldungen der Art

3147065860:error:2006A066:BIO routines:BIO_get_host_ip:
bad hostname lookup:crypto/bio/b_sock.c:149:host=fc9e

zieren den Bildschirm. Offensichtlich geschieht das Teilen in Hostname und Port beim ersten Auftreten eines Doppelpunkts.

Nun kann man für Client-Programme warten, bis eine (hoffentlich baldige) Lösung für das Problem am Horizont aufsteigt. Alternativ lassen sich Clients jedoch so umstricken, dass sie nicht mehr BIOs über BIO_new_ssl_connect() erzeugen. Stattdessen kann man Sockets vom Typ AF_INET6 mit socket() erzeugen und über connect() mit dem Server verbinden. Ein SSL-Objekt ist anschließend durch SSL_new() aus dem Context-Objekt heraus zu erzeugen. Danach lässt sich das Socket-Handle mit SSL_set_fd() dem SSL-Objekt zuweisen. Ein SSL_connect( rundet das SSL-Handshake ab. Ab dem Punkt geht es gewohnt mit SSL_get_verify_result() und den entsprechenden Schreib- und Leseoperationen weiter.

Eigentlich sollte die BIO-Library solche Ausflüge in die Welt der Socket-Programmierung verhindern. Bleibt zu hoffen, dass die nächste OpenSSL-Version IPv6 vollumfänglich unterstützt.

OpenSSL ist nicht zuletzt durch die freie Verfügbarkeit der Quelltexte inzwischen auf sehr unterschiedlichen Plattformen verfügbar. Das Beispiel WOPR zeigt, wie einfach die Portierung einer Unix-konformen Lösung ist. WOPR läuft mit unveränderten Quelltexten auf einer Vielzahl Unix-ähnlicher Systeme. Unix-Derivate, wie *BSD, AIX und Solaris, unixoide Systeme wie Linux und QNX, Windows mit Cygwin und sogar Exoten wie Syllable oder MINIX und der Dinosaurier der Systeme – z/OS mit seinen Unix System Services – werden unterstützt.

Grundsätzlich wäre die Lösung mit OpenSSL auf anderen nicht Unix-ähnlichen Betriebssystemen lauffähig – beispielsweise unter nativen Windows-Systemen ohne Unix-Nachbildungen wie Cygwin und unter OpenVMS. Allerdings bedürfte das einiger Änderungen im Programm. Sowohl Windows als auch OpenVMS implementieren zwar ein weitgehend Unix-kompatibles select(), allerdings ist das nur auf Sockets anwendbar. Ein select() auf einem Datei-Handle wie stdin unterstützen beide Plattformen nicht. Hier wären Änderungen im WOPR-Terminal unabdingbar.

Außerdem implementieren beide Plattformen kein fork(). Unter Windows wären die API-Funktionen CreateProcess() oder CreateThread(), unter OpenVMS ein Gespann aus vfork() mit decc$set_child_standard_streams() und den exec*()-Funktionen die adäquate Lösung. Die Ansätze sind jedoch mit der hinter dem Unix-fork() stehenden Philosophie nicht vereinbar.

Doch die Änderungen beziehen sich nicht auf den Einsatz der OpenSSL-Funktionen. Die Änderungen sind beschränkt auf systemspezifisches "Drumherum". Die eigentlichen SSL-spezifischen Programmteile blieben unverändert einsetzbar. Die Unabhängigkeit ist der Vorteil von OpenSSL gegenüber anderen SSL-Implementierungen. OpenSSL funktioniert systemübergreifend. Damit sind OpenSSL-Programme an sich nicht schwieriger zu portieren als beliebige andere Programme.

Deutlich zu sehen ist das bei eComStation (vormals OS/2). Mit kNIX existiert eine Unix-kompatible Ausführungsschicht aus dem Open-Source-Lager. Sowohl der WOPR-Server als auch das WOPR-Terminal lassen sich mit GNU C++ 3.x und höher problemlos kompilieren und linken. fork() ist implementiert und funktioniert einwandfrei. Der Server kann damit ohne weitere Modifikationen auf der im Kern auf dem Stand von Anfang der 2000er stehen gebliebenen Plattform seine Dienste bereitstellen.

select() arbeitet jedoch nicht einwandfrei mit Datei-Handles zusammen. Das WOPR-Terminal startet einwandfrei und verbindet sich auf den Server. Es kann aber durch die select()-Einschränkung keine Tastatureingaben erkennen. WOPR-Terminals anderer Plattformen arbeiten jedoch problemlos mit dem WOPR-Server auf eComstation beziehungsweise OS/2 Warp 4.x zusammen.

Außen vor bleiben lediglich Systeme, die für OpenSSL nicht die entsprechende Umgebung schaffen. Beispielsweise ist eine Portierung von OpenSSL auf das einst von AT&T als Unix-Nachfolger geplante Plan9 durch den eigenwilligen C-Dialekt schwierig. Selbst wenn OpenSSL auf Plan9 verfügbar wäre, würde es einen mittleren Gewaltakt bedeuten, WOPR auf Plan9 zum Laufen zu bringen. Auf dem Betriebssystem steht lediglich mit zusätzlichem Aufwand ein alter AT&T cfront als C++-Compiler zur Verfügung. Er ist aber nicht in der Lage, moderne C++-Programme zu kompilieren. Vergleichbares gilt für Forks des Plan9-Projekts wie Inferno und Plan B.

Oliver Müller
ist Geschäftsführer der OMSE Software Engineering GmbH. Er leitet die Bereiche Software Engineering, Nearshoring und IT-Sicherheit.
(ane)