
Die weborientierte Skriptsprache PHP - ein rekursives Akronym namens PHP: Hypertext Preprocessor - erlaubt die Entwicklung von komfortablen Frontends zum Zugriff auf LDAP-Server. Das macht auf die Bedürfnisse von Endbenutzern zugeschnittene Anwendungen möglich, ohne dass die sich durch eine Kommandozeile quälen oder mit trägen und allgemein gehaltenen Administrationsanwendungen herumärgern müssen.
Ein Webfrontend, in dem der Benutzer Zugriff auf seine persönlichen Daten erhält, die er unter seiner Verwaltung hat (Passwort, Urlaubsnachrichten, Signatur ...), erleichtert dem Administrator das tägliche Leben. Im Zusammenhang mit Webfrontends eignet sich besonders PHP, da es ein Leichtes ist, sichere und flexible Seiten zu entwickeln. Dieser Artikel demonstriert die LDAP-API von PHP an einem Beispiel, das die Grundfunktionen zum Ändern der Passwörter mit LDAP bereitstellt. Der Zugriff auf andere Attribute erfolgt analog und lässt sich leicht ergänzen.
Ein Zugriff auf einen LDAP-Baum folgt immer dem folgenden Schema:
Auf den ersten Blick erscheint das etwas umständlich. Bei näherer Betrachtung ist es jedoch der einzig praktikable Weg: Um sich gegenüber dem LDAP-Server zu authentifizieren, benötigt man einen DN und ein Passwort. Letzteres ist dabei in dem Objekt enthalten, das durch den DN eindeutig bezeichnet wird. Da einem Benutzer nicht zuzumuten ist, sich den oftmals langen und aus vielen Komponenten bestehenden DN seines Eintrags im LDAP zu merken, verwendet man ein eindeutiges Attribut, das im dazugehörigen Objekt gespeichert ist. Prinzipiell kann jedes Attribut dazu dienen, aber in der Praxis verwendet man meist den Usernamen.
Mit Hilfe des ersten, anonymen Bind lässt sich dieses Attribut im LDAP suchen. Mit dem auf diese Weise ermittelten Benutzer-DN kann man den eigentlichen Anmeldeprozess durchführen. Danach stehen für die weiteren Aktionen die Rechte des Users bereit. Ein korrekt konfigurierter Server wird nach einem anonymen Bind (hoffentlich) nicht mehr als diese eine Suchoperation erlauben.
Die LDAP-API von PHP baut direkt auf der API von C auf, die verschiedene Hersteller (Netscape, Sun, OpenLDAP) bereitgestellt haben. Daher ist es recht einfach, vorhandenen C-Code nach PHP zu portieren. Um überhaupt mit LDAP arbeiten zu können, muss man eine Verbindung aufbauen und sich authentifizieren. Dazu dienen die Funktionen ldap_connect und ldap_bind, zu denen es ein entsprechendes Gegenstück gibt, um die Verbindung wieder abzubauen (ldap_close, ldap_unbind). ldap_close und ldap_unbind rufen dabei intern dieselbe Funktion auf, wobei ldap_unbind bevorzugt verwendet werden sollte, da diese Funktion der C-API folgt und damit der Code zwischen den beiden Sprachen portabler bleibt.
Wie erwähnt, benötigt man für ein ldap_bind den DN des Benutzers, mit dem er sich gegenüber dem LDAP-Server authentifizieren soll. Deswegen gilt es zuerst, eine Verbindung zwischen dem vom Frontend übergebenen Usernamen und dem DN des dazugehörigen Eintrags im LDAP zu finden. Schließlich können Anwender sich ihren kompletten DN kaum merken: cn=Jan Kneschke, ou=People, dc=Company, dc=Incremental, dc=Internet. Ein Username wie jk oder Jan Kneschke ist entschieden anwenderfreundlicher.
Dazu muss zunächst ein anonymous bind gegen den LDAP-Server gemacht werden, und dann beginnt mit Hilfe des passenden Usernamens die Suche nach dem DN. Dafür stehen drei Funktionen zur Verfügung, die die drei verschiedenen Suchvarianten der LDAP-API abdecken.
Um die Suche einzugrenzen, übergibt man den Suchfunktionen einen Filter und (optional) die gewünschten Attribute. Zum Auffinden des Benutzer-DN muss der gesamte Baum nach einem Objekt durchsucht werden, das als Attribut uid den angegebenen Usernamen hat.
ldap_search($link, $root_dn, "uid=$uid");
Da ein Username eindeutig sein sollte, erwartet man, dass maximal ein Eintrag gefunden wird. Dazu dient die Funktion ldap_count_entries, die die Anzahl der gefundenen Einträge zurückliefert.
Um nun endgültig den korrekten DN zu ermitteln, muss das gefundene Objekt eingelesen werden. Das erledigen die Funktionen ldap_first_entry und ldap_next_entry. ldap_first_entry holt das erste Objekt vom Server. Alle weiteren liest ldap_next_entry in einer Schleife. Nach dem Laden des LDAP-Objekts kann man endlich mit ldap_get_dn den DN erfahren, der für die richtige Authentifizierung des Users gegenüber dem LDAP-Server nötig ist.
Nach erfolgreicher Ermittlung des korrekten DN kann die eigentliche Authentifizierung gegenüber dem LDAP-Server erfolgen. Gelingt die, stehen ab diesem Zeitpunkt dem Benutzer alle Rechte zur Verfügung, die er gegenüber dem LDAP-Server hat. Er darf zum Beispiel sein Passwort ändern und erhält Einsicht in Attribute, die einem anonymen Benutzer verborgen bleiben.
Die erworbenen Rechte werden im Folgenden zum Ändern des Attributes userpassword verwendet. Zum Ändern von LDAP-Attributen dient die Funktion ldap_modify, die Attribute anlegen, löschen und ihnen neue Werte zuweisen kann. Dabei ist zu beachten, dass man nur erlaubte Attribute verwendet. Welche erlaubt sind, ist durch die Objektklassen festgelegt, die dem durch einen DN bezeichneten Objekt zugeordnet sind.
Ein Attribut wird gelöscht, indem ldap_modify ein leeres Array übergeben wird. Wenn ein Attribut keinen Wert hat, wird es automatisch aus dem Objekt gelöscht, andernfalls wird es auf die angegebenen Werte gesetzt. Die Funktion verlangt ein Array als Parameter, um der LDAP-Eigenart Rechnung zu tragen, dass Attribute mehrere Werte annehmen können, falls dies in der Objektdefinition nicht anders verlangt wird. Auch ldap_modify hat Eigenarten: So kann man nicht einfach nur einen einzelnen Attributwert ändern, sondern muss immer alle Attribute vollständig neu schreiben - will man dies nicht, stehen die Funktionen ldap_mod_add, ldap_mod_del, ldap_mod_replace zur Verfügung, die gezielt Modifikationen vornehmen.
Nach dem erfolgreichen Abschluss der Änderungen baut ldap_unbind die Verbindung zum LDAP-Server ab. Obwohl die Verbindung am Ende des Skriptes von alleine geschlossen wird, sollte man dennoch selbst die Verbindung abbauen, da besonders das NDS von Novell allergisch auf offene Netzwerkverbindungen reagiert.
LDAP ist in Unternehmen recht erfolgreich, da seine offene und flexible Schnittstelle einen einfachen und doch sicheren Zugriff auf die Daten erlaubt. Die MTAs Sendmail, Qmail und SIMS können ihr Mailrouting über LDAP steuern, Microsoft ersetzt sein Domänenkonzept durch ActiveDirectory, das ebenfalls über eine LDAP-Schnittstelle verfügt, und das in der Zugriffskontrolle eingesetzte PAM hat natürlich auch ein pam_ldap-Modul, das sich zur Authentifizierung in Bezug auf Webserver verwenden lässt.
Die mit den meisten LDAP-Servern mitgelieferten Verwaltungswerkzeuge sind jedoch für viele Einsatzzwecke zu generisch und nicht auf spezifische Situationen anpassbar - in einem Callcenter, an einem Helpdesk oder in einer Anwendung zur Selbstpflege der eigenen Daten durch den Benutzer können sie nicht eingesetzt werden. PHP bietet mit seiner LDAP-Schnittstelle jedoch die Mittel, schnell und zuverlässig für spezifische Einsatzzwecke angepasste Webinterfaces entwickeln zu können.
Jan Kneschke
ist Student and der FH Kiel, entwickelt Webanwendungen bei der NetUSE AG und pflegt verschiedene Open-Source-Projekte (ModLogAn, pxTools).
Kristian Köhntopp
ist Entwickler für Webanwendungen bei NetUSE AG, Kiel, an der Entwicklung von PHPLib sowie PHP beteiligt und betreut die deutsche FAQ der Newsgroup [news:de.comp.lang.php de.comp.lang.php]
Dieser Text ist der Zeitschriften-Ausgabe 02/2001 von iX entnommen.
Parallelprogrammierung - die Kunst der Multi-Core-Nutzung
Agile ALM - agile Praktiken im Application Lifecycle Management
Webentwicklung - Applikationen für mobile Clients