Description de la norme

Description générale

Contenu de la norme

Comme on vient de le voir, la norme LDAP est défini par un ensemble de RFCs. Nous allons maintenant aborder ce que définissent ces RFCs:

Le protocole réseau LDAP
Il s'agit du protocole réseau, s'appuyant sur TCP/IP permettant d'accéder à l'information contenue dans l'annuaire. C'est de lui qu'est né la norme LDAP.
Le modèle d'information
Il définit la forme et le type d'informations stockées dans l'annuaire.
Le modèle de nommage
Il définit l'organisation, le référencement et l'accessibilité de l'information dans l'annuaire.
Le modèle fonctionnel
Il définit l'ensemble des opérations permettant d'accéder à l'information dans l'annuaire, que ce soit en lecture ou en écriture.
Le modèle de sécurité
Il définit les mécanisme d'authentification auprès de l'annuaire.
Un modèle de répartition
Il définit comment un annuaire peut être réparti entre plusieurs serveurs.
Des méthodes d'extensions
La norme définit des méthodes pour pouvoir d'une part ajouter de nouvelles opérations à celles définies dans le modèle fonctionnel, et d'autre part pour modifier le comportement des fonctions du modèle.

Bien que cela ne soit pas inclus stricto sensu dans la norme définie par la [rfc3377], il est d'usage de considérer que le format de fichier LDIF défini dans la [rfc2849] fait partie de la norme, ainsi que des API de programmation en C.

Le protocole LDAP

Le protocole LDAP est défini dans la [rfc3377], qui est une mise à jour de la [rfc1777]. Ce protocole réseau basé sur TCP/IP décrit de façon classique les interactions entre un client et un serveur. Le protocole permet d'effectuer indifféremment des opérations synchrones ou asynchrones. Les serveurs peuvent répondent à un client par un referral, c'est à dire par un pointeur vers un autre serveur que le client devra contacter de lui même.

Le protocole définit un ensemble de commandes de base standards, correspondant en fait aux opérations définies par le modèle fonctionnel. Il existe néanmoins la possibilité d'effectuer des opérations étendues, pourvu que client et serveur savent tous deux les gérer.

Bien que la plupart des données transmises soient encodées sous la forme de chaînes, la syntaxe BER est utilisée, si bien que les données envoyée ne sont jamais de l'ASCII. L'avantage de cette syntaxe est bien sûr son indépendance vis à vis du système d'exploitation et de la machine. L'inconvénient est qu'il n'est pas possible de tester un serveur ou un client LDAP avec l'illustre commande telnet.

Modèle de données

Les informations de l'annuaire sont appelées des entrées. Chaque entrée est constituée d'un ensemble d'attributs, chaque attribut d'une entrée ayant une ou plusieurs valeurs. Les attributs ont une syntaxe. Les attributs peuvent aussi avoir des options. Par exemple une entrée de l'annuaire pourrait modéliser une personne et posséder un attribut s'appelant telephone, ayant une syntaxe de numéro de téléphone. Cette entrée de l'annuaire pourrait avoir deux valeurs, chacune de ces valeurs devant respecter la syntaxe numéro de téléphone.

Plus précisément chaque entrée de l'annuaire appartient à une ou plusieurs classes d'objets. Ce sont les classes d'objets qui définissent quels attributs une entrée peut avoir. Les classes d'objet qui définissent aussi les attributs qui sont obligatoires et ceux qui ne le sont pas.

Un annuaire connaît un certains nombres d'attributs et de classes d'objet. La norme LDAP et en particulier les [rfc2256] et [rfc2252] en définissent plusieurs issus des annuaires X500. L'ensemble des classes d'objets et des attributs que connaît un annuaire, ainsi que les syntaxe et les règles de correspondance que nous verrons plus tard, constituent le schéma d'un annuaire. Un chapitre dédié présente en détail les schémas d'annuaire, et par là même le modèle des données LDAP.

Modèle de nommage

Les entrées d'un annuaire sont stockées dans une structure arborescente. L'arbre des entrées s'appelle l'arbre informationnel de l'annuaire (Directory Information Tree en anglais). Le sommet de l'arbre de l'arbre s'appelle le suffixe, ou bien la racine.

Chaque entrée dans l'annuaire possède un identifiant. Cet identifiant est constitué du chemin qui mène de de la racine à l'entrée. Ce chemin s'appelle le Distinguish Name, que l'on peut traduire par le nom distinctif. On préférera utiliser l'abréviation DN par la suite.

Alors que le DN est l'identifiant absolu d'une entrée dans un annuaire, le RDN, pour Relative Distinguish Name, ou encore nom distinctif relatif, est son identifiant relatif. Un RDN est constitué d'un attribut de l'entrée et d'une de ses valeurs. L'attribut choisi devra donc identifier l'entrée par rapport aux autres entrées du même parent.

Bien que cela soit peu utilisé il est possible d'avoir plusieurs attributs qui servent de RDNs.

Modèle fonctionnel

Ensemble des opérations

La norme LDAP définit neuf opérations de bases, que l'on peut regrouper en trois catégories:

Authentification et contrôle
Bind
Connexion à l'annuaire
Unbind
Déconnexion
Abandon
Pour interrompre une opération en cours
Opérations d'interrogation
Search
l'opération de recherche, détaillée ci-dessous;
Compare
L'opération de comparaison
Opération d'écriture
add
Pour ajouter une entrée dans l'annuaire.
delete
Pour effacer une entrée.
modify
Pour modifier le contenu d'un entrée, c'est à dire modifier les valeurs de ses attributs. Éventuellement rajouter des valeurs, en effacer ou supprimer, quelques valeurs ou toutes.
modifyDN
L'opération précédente ne permet pas de modifier l'identifiant d'une entrée. Il n'est pas possible à l'opération modify de modifier la valeur d'un attribut qui sert de RDN[3]. L'opération modifyDN est dédiée à cette action.

Nous n'entrerons pas dans le détail de chacune de ces opérations. Nous nous contenterons d'en étudier une seule, l'opération de recherche.

La fonction recherche

L'opération de recherche est à la fois l'une des plus utilisées, et l'une des plus significatives. Connaître son fonctionnement permet de comprendre comment marche LDAP. Sa description dans la [rfc2251] est la plus longue parmi celles des neuf opérations. Elle décrite dans la section 4.5, de la page 25 à la page 31.

La liste des paramètres de cette fonction est donc la suivante:

baseObject
Entrée à partir de laquelle la recherche est effectuée.
scope

Profondeur de la recherche. Il y a trois types de profondeur possible

base
La recherche ne s'effectuera que sur le baseObject. La recherche devient alors l'équivalent d'une lecture, à condition toutefois que le baseObject réponde positivement au filtre. .
one
Tous les enfants directs du baseObject et seulement les enfants directs sont concernés par la recherche.
sub
Tous les descendants de baseObject, ainsi que baseObject lui même sont concernés par la recherche.

derefAliases

Ce paramètre indique comment doivent être considérés les objets de type alias. Une entrée de classe alias est une copie d'une autre entrée de l'annuaire, qui apparaît aussi à plusieurs endroits de l'annuaire. Il y a trois valeurs possibles:

neverDerefAliases
La recherche ne va jamais traiter les alias qu'elle recontrera au sens où elle n'ira pas effectuer la recherche sur les entrées originales pointées par les éventuels alias.
derefInSearching
L'alias est résolu seulement dans les entrées sous le baseObject, mais pas dans le baseObject lui même.
derefFindingBaseObj
L'alias est résolu, l'entrée originale sera lu, seulement dans le baseObject.
derefAlways
Les alias seront toujours résolus.

sizeLimit
Nombre maximum d'entrées retournées par la recherche. 0 signifie aucune limite imposée par le client.
timeLimit
Temps en secondes maximum permis pour l'exécution de la requête. 0 signifie aucune limite imposée par le client.
typesOnly
Booléen indiquant si la recherche doit retourner les valeurs des attributs, avec leur type ou pas.
filter
Filtre de recherche. La syntaxe des filtres est explicitée dans un autre chapitre.
attributes
Liste des attributs à retourner pour les entrées récupérées par la recherche. Si ce paramètre contient une chaîne vide ou bien *, tous les attributs seront retournés. Certains attributs demandés peuvent ne pas être retournés si l'utilisateur n'a pas le droit d'accès dessus. Mais aucun message d'erreur ne sera renvoyé, puisqu'il aura accès aux autres attributs. Si l'attribut dont l'OID est 1.1 transmis, cela signifie que le client n'attend aucune attribut.

Modèle de sécurité

Un annuaire LDAP peut nécessiter une authentification. L'originalité des serveurs LDAP consiste en ce que l'utilisateur devra s'authentifier en se présentant comme une entrée de l'annuaire. Au lieu du traditionnel login utilisé par d'autres types d'applications, un DN devra être fourni.

L'opération bind est l'opération de connexion et d'authentification auprès d'un serveur annuaire en endossant l'identité d'une entrée. Cette opération peut être simple, auquel cas l'utilisateur doit donner un mot de passe, ou bien elle peut prendre en paramètre un jeton SASL.

Étendre LDAP

Dès la conception du protocole LDAP dans sa version 3, il a été prévu d'y intégrer la possibilité d'étendre la norme, soit en modifiant le comportement des opérations existantes, soit en ajoutant des nouvelles opérations. Nous allons dans cette section décrire ces deux possibilités.

Les contrôles

Les contrôles sont un mécanisme qui permet de modifier le comportement des opérations standards. Ils sont envoyés par le client au serveur, en même temps qu'une requête classique. Ils sont décrits dans le paragraphe 4.1.12 de la [rfc2251].

Dans une requête, un contrôle est caractérisé par

Type
Il s'agit d'un identifiant du contrôle, sous la forme d'un OID.
Criticité
Un booléen qui indique si le contrôle est critique ou pas. Si le contrôle est signalé comme étant critique par le client, le serveur doit absolument exécuter la requête avec le contrôle associé. S'il ne le peut pas, par exemple parce qu'il n'implémente pas le contrôle ou parce que le contrôle est inapproprié avec la requête demandée, il doit retourner l'erreur unsupportedCriticalExtension et ne pas exécuter la requête.
Valeur
Ce champs est utilisé pour transmettre des valeurs supplémentaires. Son contenu dépend donc du contrôle.

Les contrôles peuvent être aussi retournés par un serveur dans une réponse à un client. Ainsi des interactions sont possibles entre le client et le serveur. Un exemple d'une telle interaction est le contrôle de recherche paginée, défini dans la [rfc2696] et supporté par Openldap à partir de version 2.2.

Ce contrôle permet à un client d'effectuer une recherche, et de récupérer le résultat de sa recherche par blocs, au lieu de recevoir toutes les entrées en une seule fois. Lorsqu'il reçoit une telle requête, le serveur inclus dans sa réponse le même contrôle, en y incluant un identifiant dans le champs valeur. Cet identifiant sera ensuite renvoyé par le client à son tour, afin de demander le bloc suivant.

D'autres contrôles ne nécessitent pas une telle interaction. C'est le cas du contrôle matchedValuesOnly[4], dont l'OID est 1.2.826.0.1.3344810.2.2, et qui est encore à l'état de draft auprès de l'IETF. Ce contrôle, qui doit être associé à une recherche, demande à un serveur de ne retourner, parmi toutes les valeurs des attributs d'une entrée, que celles qui ont répondu positivement au filtre de la recherche. Ce contrôle est supporté par Openldap.

Les opérations étendues

La section 4.12 de la [rfc2251] décrit les opérations étendues. Les opérations étendus sont des opérations dont la syntaxe et la sémantique pourront être définies dans des documents futurs. Il est ainsi possible aux clients et aux serveurs LDAP d'effectuer des opérations supplémentaires aux neuf opérations vues précédemment. Il faut évidemment que le serveur implémente l'opération étendue demandée par le client.

Une opération étendue, et la réponse d'un serveur à une telle opération, sont décrites très succinctement par la RFC. Elles sont composées très simplement d'un identifiant, un OID donc, de la requête ou de la réponse, et d'un champs supplémentaire contenant des données, dont la signification dépend du contexte.

Que ce soit pour les contrôles ou pour les opérations étendues, il est préférable pour le client de connaître à l'avance quelles extensions supporte le serveur. La section suivante décrit comment le client peut obtenir ces informations du serveur, en se basant toujours sur le protocole LDAP.

Meta recherche

La [rfc2251] dans sa section 3.4 a prévu un mécanisme permettant de découvrir les extensions, les contrôles et le schéma d'un serveur annuaire. Cela permet au client d'interagir au mieux avec un serveur, en évitant, par exemple, de créer ou de modifier des objets de façon illégale vis à vis du schéma, ou bien de ne demander que les contrôles et les opérations étendues implémentées par le serveur.

Le Root DSE

Pour obtenir des informations sur les capacités d'un annuaire il faut interroger une entrée spéciale qui s'appelle le Root DSE. Cette entrée n'a aucun DN, et doit être récupérée avec le filtre (objectclass=*). Elle ne doit pas être retournée autrement que par une requête avec ce filtre et dont le base_dn est vide. Elle peut être soumise à des restrictions de contrôle d'accès. La [rfc2251] précise que le serveur pourrait autoriser la modification des attributs de cette entrée, mais Openldap lui ne le permet pas.

Voici la liste des attributs d'un Root DSE définis par [rfc2251]:

namingContexts
Liste des suffixes gérés par le serveur.
subschemaSubentry
DN de l'entrée subschema. Cette entrée contient une description du schéma gérée par le serveur. Cet attribut peut être absent si le serveur ne gère pas lui même des entrées schéma. Il est multiple, dans le cas où le serveur gère plusieurs annuaire, chacun ayant son propre schéma.
altServer
Serveur à contacter si le serveur ne répond plus.
supportedExtension
Liste des opérations étendues supportées.
supportedControl
Liste des contrôles supportés.
supportedSASLMechanisms
Liste des fonctionnalités SASL supportées.
supportedLDAPVersion
Version du protocole LDAP supportée par le serveur.

Les entrées subschema

Nous venons de voir comment récupérer un certain nombre d'information sur un annuaire, et en particulier comment récupérer le DN des entrées subschema. Comme le Root DSE, les entrées subschema sont des entrées particulières d'un serveur, qui ne sont pas placées sous la racine de l'annuaire. Ces entrées décrivent le schéma supporté par le serveur, c'est à dire la liste des objets, des attributs, des règles de comparaison, etc. qu'il connaît. Il est possible, d'après la [rfc2251] de modifier ses entrées, mais ce n'est pas obligatoire pour respecter la version 3 de la norme LDAP.

La section 3.2.2 de cette RFC définit la liste des attributs d'une entrée subschema. Certains attributs sont obligatoires, d'autres pas. Cette liste est la suivante:

cn
Cet attribut doit être le RDN de l'entrée subschema. Cet attribut est obligatoire dans une entrée subschema.
objectClass
Il s'agit des classes de l'entrée subschema. Il doit au moins contenir les valeurs top et subschema. Cet attribut est obligatoire dans une entrée subschema.
objectClasses
Cet attribut multivalué contient les classes gérées par le serveur. Il a autant de valeurs que de classes gérées. Cet attribut est obligatoire dans une entrée subschema.
attributeTypes
Cet attribut multivalué contient les attributs gérés par le serveur. Il a autant de valeurs que d'attributs gérés. Cet attribut est obligatoire dans une entrée
matchingRules
Liste des règles de comparaison gérées par le serveur. Cet attribut a autant de valeur que de règles, et n'est pas obligatoire.
matchingRuleUse
Usage des règles de comparaison. Il y a autant de valeurs de cet attribut que de règles de comparaison. Et pour chaque règle, une valeur contient la liste des attributs sur lesquels elle s'applique. Cet attribut n'est pas obligatoire.
ldapSyntaxes
Liste des syntaxes supportées par le serveur. Cet attribut n'est pas obligatoire.

Les attributs dITStructureRules, dITContentRules, nameForms existent aussi, et sont optionnels. Ils ne sont pas supportés par Openldap. Ils décrivent des règles sur l'arbre informationnel.



[3] L'erreur retournée est notAllowedOnRDN.