„Wer bist du?“ – Authentifizierung ist ein wichtiger Bestandteil der meisten Anwendungen im Internet und die unverzichtbare Vorstufe zur Authorisierung („was darf ich“). Die klassische Authentifizierung im Webbereich setzt auf eine Username/Passwort Kombination entweder direkt über HTTP Authentifizierung („.htaccess“) oder über ein zwischengeschaltetes Token (ein Authentifizierungs-Cookie).
Zusätzlich oder auch alternativ dazu gibt es die Möglichkeit, User anhand von SSL Zertifikaten zu authentifzieren. Dabei muss keine geheime Information, nämlich das Passwort, auf dem Server gespeichert werden. Das Zertifikat kann der Benutzer daher problemlos zur Anmeldung an vielen verschiedenen Servern nutzen und es bietet auch zusätzliche Sicherheit, da ein Angreifer sowohl das Zertifikat als auch das zugehörige Passwort besitzen muss. Da es sich bei den verwendeten Zertifikaten um Public-Key Informationen handelt, muss in keinem Fall (abgesehen von der Generierung) der geheime Teil des Zertifikats den Rechner des Users verlassen.
Die Infrastruktur auf dem Server bereitzustellen, um Webmastern zu erlauben, ihren Usern die Option einer Authentifizierung per SSL Zertifikat anzubieten, ist Thema dieses Howtos.
Zunächst benötigt der User natürlich ein Zertifikat, dass er in seinen Browser importiert. Dieses Zertifikat muss von einer Zertifizierungsstelle signiert sein, die vom Apache als vertrauenswürdig eingestuft wird. Entweder, weil sie sich sowieso in seiner Liste der vertrauenswürdigen Zertifizierungsstellen befindet (was recht unwahrscheinlich ist), oder indem sie manuell eingepflegt wird. Den zweiten Fall wollen wir hier durchspielen. Als Beispiel nutzen wir die Zertifikate von Globalsign (www.globalsign.com). Es können auch selbst signierte Zertifikate benutzt werden, dies liegt aber außerhalb dieses Howtos.
Im Detail:
Um nun in einem bestimmten Verzeichnis eine Authentifizierung per SSL zu erzwingen wird dort eine .htaccess Datei mit folgendem Inhalt angelegt:
SSLVerifyClient require SSLVerifyDepth 10
(Die Apache Dokumentation gibt es hier: httpd.apache.org/docs/2.2/mod/mod_ssl.html)
SSLVerifyDepth muss in der Regel gesetzt werden, da wir es üblicherweise mit sogenannten Chained-Zertifikaten zu tun haben, so dass der Server, um eine Signatur zu verifizieren, gleich mehrere Zertifikate prüfen muss.
Üblicherweise möchten wir aber nicht einfach alle User mit einem gültigen Zertifikat authentifizieren, sondern nur solche, die bestimmte Kriterien erfüllen. Soll z.B. nur ein bestimmter User Zugriff erhalten, so erreichen wir das mit folgender .htaccess:
SSLVerifyClient require SSLVerifyDepth 10 SSLRequire %{SSL_CLIENT_S_DN_CN} eq "user@domain.de"
Damit werden nur User authentifiziert, deren Zertifikat als CN (CommonName) aus dem String user@domain.de besteht. Details des x509 Systems, das für SSL Zertifkate verwendet wird, und auf dessen Bestandteile wir hier zugreifen würden diesen Artikel sprengen, insoweit sei auf die Apache Dokumentation und die im Netz verfügbaren Informationen verwiesen.
Damit der Server nun die Verifizierung des Client-Zertifikates auch durchführen kann, benötigt er die sogenannten CA-Zertifikate der Zertifizierungsstelle, die die Zertifikate des Clients signiert hat. Diese lassen sich üblicherweise auf der Webseite des Zertifikatsanbieters herunterladen (in unserem Beispiel hier: https://www.globalsign.com/support/intermediate-root-install.php).
Sollten die Zertifikate noch nicht im PEM Format vorliegen, müssen sie per openssl Tool konvertiert werden, z.B.:
openssl x509 -inform der -in ca.cer -out globalsign.inter.crt
(Das resultierende PEM kodierte Zertifikat ist jetzt im File globalsign.inter.crt.)
Bei PEM handelt es sich um ein Base64-kodiertes ASCII Format, der Inhalt der resultierenden Files müsste demnach etwa so aussehen:
-----BEGIN CERTIFICATE----- MIIEFjCCAv6gAwIBAgILBAAAAAABL07hLOEwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw ... v+P+SmU5rXeeyGFzzNQtU76gCUPj7tzM0rZEmJO+EmIMkNFNnLcMncEJDytc4Z1b MMQjm6IHxNnSzfbuDjhiVzp2AqBh6U2f1EtiM0RNfw4glmWvS0Vilxis -----END CERTIFICATE-----
Die resultierenden Zertifikate werden in ein für den Webserver erreichbares Verzeichnis gelegt.
ACHTUNG: Nicht erwähnt in der Dokumentation aber absolut nötig: Das Verzeichnis muss für den Webserver-User (nobody, www-data o.ä.) erreichbar sein, sonst gibt es Fehler bei der Verifizierung. Es genügt nicht, dass der Apache beim Start die Zertifikate einlesen kann.
Danach weclselt man in dieses Verzeichnis und führt dort das c_rehash Utility aus dem openssl-Paket aus:
[root@debian /ssl.user.crt]# c_rehash . Doing . globalsign.inter.crt => 634a765f.0 globalsign.root.crt => b0f3e76e.0
Dies ist zwingend erforderlich, da der Apache die Zertifikate anhand ihrer Hashes sucht, wenn er die Zertifikats-Chain nach oben wandert. Bei dem Hash handelt es sich übrigens um eben den Hash, der das Zertifikat identifiziert:
[root@debian /ssl.user.crt]# openssl x509 -in globalsign.inter.crt -subject_hash -noout 634a765f
In der Apache Config muss sodann das Verzeichnis mit den Zertifikaten noch bekannt gemacht werden:
SSLCACertificatePath /usr/local/apache/user.ssl/ssl.user.crt
Nun muss noch der Apache einmal seine Config reloaden und dann sollte es funktionieren. Sollte dem nicht so sein, so hilft ein
LogLevel debug
Beim Finden des Fehlers. Auch das Openssl Commandline Tool kann hierbei gute Dienste leisten. Wenn das Client Zertifikat als PEM File vorliegt, so kann man per:
[root@debian /ssl.user.crt]# openssl verify -CApath /usr/local/apache/user.ssl/ssl.user.crt/ client.pem client.pem: OK
prüfen, ob die Zertifikatsverfizierung generell funktioniert.
Und für Artfiles Kunden gilt natürlich wie immer: bei Problemen hilft unser Support jederzeit gerne 🙂
Sehr schön…weiter so!