LDAP-Abfragen erstellen

01.09.2006 von Holger Kattner
Das Lightweight Directory Access Protocol, kurz LDAP, bildet die Schnittstelle zum Active Directory, dem Verzeichnisdienst von Windows-Domänen, in dem auch viele Daten von Exchange abgelegt sind. Wenn Daten vom Active Directory abgefragt werden, kommt dieser Standard zur Anwendung. Es ist für Administratoren deshalb oft hilfreich, über einige Grundkenntnisse zu verfügen.

LDAP wurde als speziell an die Erfordernisse des TCP/IP-Netzwerkprotokolls angepasste Variante des X.500-Verzeichnisstandards entwickelt. Die Festlegungen von X.500, genauso wie die des damit zusammenhängenden X.400-Standards, zeichnen sich durch einige Komplexität aus. Auch die „leichtgewichtige“ Version ist ohne längeres Studium der Standarddokumente kaum durchschaubar. Glücklicherweise ist dies auch für kaum einen Anwender notwendig. Die Nutzung der vollständigen Protokolle kann in der Regel der Software-Implementation überlassen werden.

Allerdings gibt es einen Teilbereich, den es sich lohnt genauer zu betrachten. Die Formulierung von Verzeichnisabfragen, mit denen in LDAP-Verzeichnissen nach Objekten wie Benutzern und Verteilerlisten gesucht werden kann, wird von Administratoren und Entwicklern gleichermaßen benötigt. An verschiedenen Stellen von Windows und Exchange ist es hin und wieder notwendig Abfragen direkt im LDAP-Format zu formulieren.

LDAP wurde in Anbetracht der Entwicklung des Internet von dem ursprünglichen X.500-Standard abgeleitet, und die zugehörigen Standards werden deshalb auch von der Internet Standard-Gruppe IETF verwaltet, die auch die entsprechenden RFCs (Request for Comments) herausbringt. Die aktuellen Dokumente sind RFC 4510-4533, die aus einer Überarbeitung vom Anfang des Jahres 2006 stammen. Microsofts Active Directory beruht noch auf etwas älteren Varianten der Standarddokumente. Die hier besprochene Formulierung von Suchabfragen ist in den Dokumenten RFC 4515 (aktuell) beziehungsweise RFC 2254 (Active Directory) niedergelegt.

Attributbezeichner

In Suchabfragen werden in der Regel bestimmte Objekte mit bestimmten Attributwerten gesucht, also beispielsweise ein Benutzer mit einem bestimmten Nachnamen. Würde beispielsweise ein Anwender mit dem Nachnamen Meier gesucht werden, würde die Abfrage folgendermaßen aussehen:

(sn=Meier)

LDAP-Suchfilter werden immer von runden Klammern eingeschlossen. Bei direkten Suchen nach einem bekannten Attributwert (hier Meier) wird dieser einfach mit einem Gleichheitszeichen dem Attributnamen (sn) gegenübergestellt.

Gleichzeitig tritt hier schon ein Problem bei der Formulierung von Suchfiltern zutage. Es ist nicht immer einfach, den Bezeichner für das gesuchte Attribut zu finden. Der Nachname verbirgt sich beispielsweise hinter dem Code sn, was eine Abkürzung für das englische Wort Surname ist. Die Bezeichner sind Kürzel oder ganze Wörter, die, falls es sich um Standardwerte handelt, aus dem Englischen abgeleitet sind.

Insgesamt ist die Zusammensetzung der Attribute durch den amerikanischen Kulturkreis geprägt. Ein Feld für die vor allem in den USA gebräuchliche Middle Initial oder die Angabe eines Bundesstaates sind vorhanden. Im deutschen lässt sich damit aber im Zweifelsfalle einfach umgehen, indem solche Felder einfach leer gelassen werden. Angehörige anderer Kulturen werden da mit schwierigeren Problemen konfrontiert, beispielsweise wenn es darum geht, in welchem Feld der beispielsweise in Russland übliche Name des Vaters untergebracht werden soll.

Eine Aufstellung der in einem Windows-System vorhandenen Attribute lässt sich mit relativ einfachen Mitteln erzeugen. Eine Referenzaufstellung mit ausführlichen Erklärungen und Vorgaben für gültige Werte sucht man allerdings vergebens. Die zentralen Werte sind durch den LDAP-Standard selbst vorgegeben. Das Attributschema kann allerdings nach Bedarf erweitert werden. Microsoft hat dies für Active Directory und Exchange Server getan. Die wichtigsten Werte sind in den jeweiligen Produktdokumentationen zu finden.

In der Regel greifen Administratoren allerdings lieber zu pragmatischen Methoden. Mit Programmen wie ADSIEdit aus den Windows Server Support Tools lassen sich die Attribute des Active Directory einfach im Überblick anzeigen. Die Support Tools können kostenlos von Microsofts Website bezogen werden.

Auch wenn sich die vorhandenen Attribute herausfinden lassen, ist es nicht immer einfach, den Sinn eines Attributs abzuleiten. Wie schon das Beispiel sn zeigt, stimmen die Bezeichner häufig nicht mit den Texten der Dialoge in der englischsprachigen Windows-Version überein. Für Entwickler ergibt sich zudem das Problem, dass die einschlägige Windows-Programmierschnittstelle MAPI noch einmal andere Bezeichner für dieselben Attribute verwendet, da MAPI und LDAP/X.500 seinerzeit unabhängig voneinander entwickelt wurden. Hierdurch stehen sich dann in manchen Fällen drei unterschiedliche Bezeichnungen für einen semantischen Wert gegenüber.

Suchsyntax

Häufig ist der Wert des Attributs, nach dem gesucht wird, nicht exakt vorgegeben, oder es müssen mehrere Bedingungen erfüllt werden. In diesem Fall muss das oben genannte Suchbeispiel erweitert werden.

Wenn beispielsweise die Schreibweise von Meier unklar ist, könnte die Suche über den Platzhalter * durchgeführt werden: (sn=M*ier).

Der Platzhalter * ist der einzige vorgesehene Platzhalter. Weder das Fragezeichen, wie es aus der Windows-Kommandozeile bekannt ist, noch irgendeine Art von regulären Ausdrücken werden von LDAP verstanden.

Oft wird der Stern am Ende des gesuchten Werts eingesetzt. (sn=M*) würde beispielsweise alle Objekte finden, deren Nachnamen-Attribut einen Wert hat, der mit „M“ beginnt. Ob dabei nur Werte mit großem „M“ akzeptiert werden, hängt von der Art des Attributs ab. Für jeden Attributtyp im Verzeichnis kann im Active Directory festgelegt werden, ob Groß- und Kleinschreibung relevant ist. In den meisten Fällen wird sie nicht beachtet.

Auch am Anfang kann der Platzhalter gesetzt werden, beispielsweise um neben den Meiers auch die Ober- und Untermeiers zu finden. (sn=*meier). Allerdings muss hier davor gewarnt werden, dass diese Art besonders aufwendig ist und dementsprechende Laufzeiten mit sich bringt. Noch mehr rechnen muss der Server bei der Suche nach Teilstrings, beispielsweise alle Anwender mit einem „r“ im Namen (sn=*r*).

Besonders häufig wird nur nach dem Stern gesucht. In diesem Fall wird das Attribut auf Existenz überprüft. Um Speicherplatz zu sparen, werden Attribute, denen kein Wert zugeordnet ist, gar nicht angelegt. Diese Überprüfung kann im Gegensatz zur Teilstringsuche sehr effizient durchgeführt werden, muss also nicht gemieden werden. (initials=*) würde beispielsweise alle Anwender liefern, bei denen die besagte amerikanische Middle Initial eingetragen ist.

Mehrere Bedingungen

Die oben beschriebene Suche nach verschiedenen Schreibweisen von Meier hat einen Nachteil. Anstelle des Platzhalters kann eine beliebige Zeichenkette stehen. Es werden also neben Maier und Meier auch Anwender mit den Nachnamen Mrier und sogar Meinbier und Mier gefunden.

Besser ist es, explizit nach den einzelnen möglichen Schreibweisen zu suchen. Der Filter soll also nach Benutzern suchen, deren Nachname Meier oder Maier ist. Hierzu können mehrere Bedingungen über logische Operatoren verknüpft werden. Im vorliegenden Fall wird der Oder-Operator (|) benötigt. Er muss vor die einzelnen Bedingungen gestellt werden. Die einzelnen Vergleiche, die verknüpft werden sollen, müssen durch eine Klammer zusammengefasst werden.

(|(sn=Meier)(sn=Maier))

In Deutschland kommt der Name Meier ziemlich häufig vor. Um schnell den gewünschten zu finden, hilft da oft nur der Vorname. In diesem Fall müssen die Vergleiche durch ein logisches Und verknüpft werden

(&(givenName=Heinz)(sn=Meier))

Wenn nun die Schreibweise des Nachnamens unklar, aber der Vorname bekannt ist, dann wird sowohl der Und- als auch Oder-Operator benötigt:

(&(givenName=Heinz)(|(sn=Meier)(sn=Maier)))

Hier kommt eine ganze Menge von Klammern zum Einsatz, die zur Ordnung des Filters aber notwendig sind. Im Zweifelsfall sollten bei der Formulierung von LDAP lieber ein paar Klammern zu viel als zu wenig verwendet werden, um Fehlinterpretationen zu vermeiden.

Vergleiche

Neben dem Gleichheitszeichen werden von LDAP auch andere Vergleiche unterstützt. <= und >= führen jeweils lexikographische Vergleiche durch. (sn<=M*) würde alle Anwender mit Nachnamen liefern, die mit Buchstaben bis einschließlich „M“ beginnen. Diese Vergleiche sind allerdings mit Vorsicht zu genießen. Es wird definitionsgemäß ein lexikographischer Vergleich durchgeführt. Dieser bezieht sich rein auf den Zeichencode an der jeweiligen Position des Strings. Es gilt in diesem Fall zwar „021“ < „201“, aber „21“ > „201“ („2“ gleich „2“ und „1“ > „0“).

LDAP sieht zudem noch einen Operator für ungefähre Vergleiche „~=“ vor, dessen genaue Funktion aber vom Standard nicht vorgegeben wird. Microsoft unterstützt diesen Operator zwar, aber das bedeutet nur, dass dessen Angabe nicht zu einem Fehler führt. Derzeit wird er nur wie ein normales Gleichheitszeichen ausgewertet.

Zudem werden vom Active Directory zwei Operatoren zu Vergleichen mit Bitfeldern unterstützt. Sie haben die Form Attribut:ruleOID:=Wert. Attribut ist der Name eines Bitfeld-Attributs, Wert ist eine Bitmaske. Mit dieser Bitmaske wird eine bitweise Auswertung durchgeführt. Je nach roleOID wird der Vergleich als wahr bewertet, wenn alle (UND) oder wenn irgendein Bit (ODER) des Attributswerts dessen Position in der Maske auf 1 gesetzt ist, auch 1 ist. Es werden also nur die Bits des Attributs betrachtet, die in der Maske auf 1 gesetzt sind. Für diese wird überprüft, ob ihr Wert 1 ist. Die zulässigen Angaben für roleOID sind:

Ein Beispiel für die Anwendung des Bit-Vergleichs ist die Suche nach deaktivierten Konten und solchen, die ihre Kennwörter nicht ändern können. Das notwendige Attribut heißt in diesem Fall userAccountControl. Die Bitmasken sind 0x02 (Deaktiviert) und 0x0040 (Kennwort kann nicht geändert werden), also zusammen 0x0042 oder dezimal 66. Wenn nach Konten gesucht werden soll, die deaktiviert sind und ihre Kennwörter nicht ändern können, dann hilft folgender Filter weiter:

(userAccountControl:1.2.840.113556.1.4.803:=66)

Wenn Konten gesucht werden sollen, die entweder deaktiviert sind oder ihre Kennwörter nicht ändern können, muss der Filter entsprechend wie folgt lauten:

(userAccountControl:1.2.840.113556.1.4.803:=66)

Zudem unterstützt LDAP auch einen logischen Negations-Operator. Er wird dem Vergleich als Ausrufezeichen vorangestellt. Sind beispielsweise in einem Unternehmen die Anwender selbst dafür verantwortlich, Daten wie ihre Büronummer einzutragen, dann hilft der folgende Filter, all diejenigen zu finden, die dies noch nicht getan haben (!physicalDeliveryOfficeName=*). Die Negation in Verbindung mit dem Stern sucht nach leeren, also letztlich nicht existenten Attributwerten. Auch hier muss man bei den Attributbezeichnern etwas aufpassen: roomNumber entspricht nicht dem Feld Büro in der Eingabemaske von AD Benutzer und Computer.

Bild 1: ADSIEdit (hier in der Windows 2003 SP1-Version) hilft die verfügbaren Attribute anzuzeigen.

Objekttypen

Im Active Directory befinden sich befinden sich eine ganze Reihe von Objektarten. Benutzerkonten sind genauso Objekte wie Gruppen und Verteilerlisten und eine Vielzahl von Systemobjekten. Wenn nun einfach nach E-Mail-Adressen gesucht wird, würden alle Objekte, denen eine EMail zugeordnet werden kann, als Ergebnis zurückgeliefert, neben Benutzern beispielsweise auch Verteilerlisten und öffentliche Ordner, was nicht immer gewünscht ist. Wenn nach der nicht vorhandenen Raumnummer ohne Einschränkung des Objekttyps gesucht würde, würde jede Objektart ohne festgelegte Raumnummer ausgegeben werden.

Die Objekttypen lassen sich aber leicht auswählen, da sie auch als Attribut (objectClass) beim Objekt gespeichert sind. Sie lassen sich deshalb genauso als Bedingung formulieren, wie auch nach Objekten mit bestimmten Nachnamen oder Raumnummer gesucht wird. Die folgende Abfrage sucht alle Kontakt-Objekte im Verzeichnis:

(objectClass=contact)

Allerdings ist ein Active Directory einer hierarchischen Liste von Objektklassen zugeordnet, die letztendlich den Typ ausmachen. Wenn beispielsweise nach der Klasse User gesucht wird, werden auch Typen wie Computerkonten gefunden, die eventuell nicht als Ergebnis gewünscht sind. Speziell bei der Suche nach Benutzerkonten wird deshalb üblicherweise noch als Bedingung (objectClass=person) hinzugefügt, um nur menschliche Anwender zu finden. Der folgende Filter liefert beispielsweise in einer Exchange-Umgebung alle regulären Benutzerobjekte, das heißt solche, die ein Postfach und damit eine definierte E-Mail-Adresse haben.

(&(objectCategory=person)(objectClass=user)(mail=*))

Sonderzeichen

Grundsätzlich sind in LDAP innerhalb der Attributwerte alle Zeichen als Eintrag erlaubt. Da einige Zeichen wie (,),=,&,| eine besondere Bedeutung haben, können sie aber nicht in der Form in Suchabfragen verwendet werden. Sie müssen stattdessen über so genannte Escapesequenzen angegeben werden. Diese bestehen aus einem Backslash-Zeichen (\), das von dem hexadezimalen Zeichencode gefolgt wird, beispielsweise und für die runden Klammern. Der folgende Filter würde nach Objekten mit Telefonnummern in Berlin suchen, falls die Werte alle der Konvention „+49(30)Nummer“ folgen.

(telephoneNumber=+49*)

Es ist vom Standard her auch möglich, direkt binäre Daten in Verzeichnisattributen abzulegen. In diesen Attributwerten kann über den Escape-Mechanismus ebenfalls gesucht werden in dem die Bytewerte als Escape-Sequenzen angegeben werden, beispielsweise .

Weitere Elemente

Der eigentliche Suchfilter bildet je nach Kontext nur einen Teil einer LDAP-Anfrage. Meistens muss daneben noch angegeben werden, wo gesucht werden soll (Suchbasis), was als Ergebnis zurückgeliefert werden soll, und in welcher Tiefe gesucht wird. Diese vier Teile werden durch Strichpunkte getrennt aneinander gereiht.

Suchbasis;Filter;Attribute;Suchtiefe

Die Suchbasis gibt an, in welchem Verzeichnis beziehungsweise Verzeichnisbereich gesucht werden soll. Hierbei handelt es sich um den so genannten voll qualifizierten Namen (DN) der Verzeichnisbasis oder des Unterobjekts, zum Beispiel eine Organizational Unit, die durchsucht werden soll. Diese lässt sich beispielsweise mit ADSIEdit einfach herausfinden. Zudem enthält die Suchbasis die Art des Verzeichnisses, das durchsucht werden soll, ein Standard-LDAP-Verzeichnis/Active Directory (LDAP://) oder den Global Catalog eines Domänenforests (GC://). Die zugrunde liegende Windows-Schnittstelle ADSI unterstützt daneben noch einige andere Verzeichnisarten, die allerdings nicht auf LDAP basieren und deshalb nicht weiter betrachtet werden. Die Suchbasis muss in die Zeichen für Größer > und Kleiner < eingeschlossen werden. Die Suchbasis kann zudem als Angabe den Verzeichnisserver enthalten, mit dem die Verbindung aufgenommen werden soll. Fehlt die Angabe, wählt ADSI einen Server aus. Die Angabe einer Suchbasis würde zum Beispiel folgendermaßen aussehen:

<LDAP://server/OU=test,DC=domain,DC=de>.

Die Angabe des Ergebnisses besteht aus einer Liste von Attributbezeichnern, die von den gefundenen Objekten zurückgeliefert werden sollen. Beispielsweise würde diese nur telephoneNumber beinhalten, wenn nach den Telefonnummern der Damen und Herren mit dem Nachnamen Meier gesucht würde.

Die Suchtiefe gibt an, ob nur in dem bezeichneten Verzeichnisobjekt oder auch in Unterobjekten gesucht werden soll. Mögliche Werte sich hier base, onelevel, subtree. Base sucht nur an der bezeichneten Stelle, onelevel auch in direkten Unterobjekten und Subtree beliebig tief in Unterzweigen.

Anwendungsmöglichkeiten

Ein Platz, an dem die hier gezeigten Suchfilter zu Tage treten, sind die gespeicherten Abfragen im Verwaltungsprogramm Active Directory-Benutzer und -Computer (ADUC). Im Dialog zur Erstellung neuer Abfragen können über verschiedene Felder Suchen erstellt werden. Der resultierende LDAP-Filter wird dann unter Abfragezeichenfolge angezeigt. Das Ergebnis lässt sich nach der Anlage einsehen. Auf diese Weise kann jedenfalls für nicht allzu komplexe Suchen die eigenhändige Erstellung umgangen werden. Zum anderen ist es auch eine gute Möglichkeit, sich einen Überblick über die Abfrage-Syntax zu verschaffen.

Im gleichen Programm lassen sich die einzelnen LDAP-Abfragen direkt einsetzen. Im Kontextmenü (rechte Maustaste) des Domänenbaums wählt man im Dialogfeld Suchen unter Suchen dann Benutzerdefinierte Suche aus. In der Registerkarte Erweitert kann in das enthaltene Textfeld eine LDAP-Anfrage im beschriebenen Filter-Format angegeben und damit eine Suche gestartet werden.

Ein weiterer wichtiger Platz, bei dem die beschriebenen LDAP-Abfragen benötigt werden, sind administrative Skripts. Analog gilt dies für andere Skript- und Programmiersprachen, die auf ADSI oder die entsprechenden .NET-Klassen zugreifen können, wie auch die neue Windows PowerShell, die die Grundlage für die kommende Verwaltungsschnittstelle von Exchange Server 2007 bilden wird.

Bild 2: In ADUC können LDAP-Filter auch im Klartext eingegeben werden.

Auch im Programm LDP, das Teil der Windows Server Support Tools ist, kommen LDAP-Suchabfragen zum Einsatz. Dieses Hilfsprogramm zeichnet sich dadurch aus, dass es im Vergleich zu den Standardverwaltungsprogrammen das unterliegende LDAP-Protokoll wesentlich weniger abstrahiert. Hierdurch lassen sich verschiedene Dinge protokollnäher untersuchen. Auch hier kann über das Kontextmenü eines Verzeichnisobjekts ein Suchdialog geöffnet werden. Desgleichen werden LDAP-Suchabfragen im Programm LDIFDE verwendet, das ebenfalls in den Support Tools enthalten ist und im Wesentlichen zum Datenim- und export eingesetzt wird.

Ein anderes Hilfsprogramm der Microsoft-Produktunterstützung, das zur Durchführung einer größeren Anzahl von Änderungen beispielsweise bei einem Abteilungsumzug hilft, ist ADModify (http://workspaces.gotdotnet.com/ADModify).Hier können die zu ändernden Objekte ebenfalls über einen LDAP-Filter ausgewählt werden.

Ein Exchange-spezifisches Anwendungsfeld ist schließlich die Definition von benutzerdefinierten Adresslisten. Globale Adresslisten (GAL) werden über LDAP-Filter festgelegt, wobei sich mehrere GAL-Filter definieren lassen, die verschiedenen Anwendern zugeordnet werden können. Auf diese Weise ist es möglich, in großen Unternehmen die GALs übersichtlich zu gestalten, da sie nur die Anwender einer Niederlassung oder eines Unternehmensteils enthalten. Besonders wichtig wird dies im Hostingbereich, wo mehrere Kunden in einer Exchange-Struktur untergebracht werden, die aber nur die jeweils eigenen Anwender zu sehen bekommen dürfen. Auch die abfragebasierten Verteilerlisten werden über LDAP-Filter generiert. Diese können entweder über Dialogmasken oder über die direkte Eingabe des LDAP-Filters erstellt werden.